All Downloads are FREE. Search and download functionalities are using the official Maven repository.

xapi.bytecode.MethodInfo Maven / Gradle / Ivy

Go to download

Everything needed to run a comprehensive dev environment. Just type X_ and pick a service from autocomplete; new dev modules will be added as they are built. The only dev service not included in the uber jar is xapi-dev-maven, as it includes all runtime dependencies of maven, adding ~4 seconds to build time, and 6 megabytes to the final output jar size (without xapi-dev-maven, it's ~1MB).

The newest version!
/*
 * Javassist, a Java-bytecode translator toolkit.
 * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License.  Alternatively, the contents of this file may be used under
 * the terms of the GNU Lesser General Public License Version 2.1 or later,
 * or the Apache License Version 2.0.
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * MODIFIED BY James Nelson of We The Internet, 2013.
 * Repackaged to avoid conflicts with different versions of Javassist,
 * and modified Javassist APIs to make them more accessible to outside code.
 */
package xapi.bytecode;

import java.io.DataInput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Map;

import xapi.bytecode.annotation.AnnotationDefaultAttribute;
import xapi.bytecode.annotation.AnnotationsAttribute;
import xapi.bytecode.attributes.AttributeInfo;
import xapi.bytecode.attributes.CodeAttribute;
import xapi.bytecode.attributes.ExceptionsAttribute;
import xapi.bytecode.attributes.LineNumberAttribute;
import xapi.bytecode.attributes.ParameterAnnotationsAttribute;
import xapi.bytecode.attributes.SignatureAttribute;
import xapi.util.X_Byte;

public class MethodInfo extends MemberInfo {
    ConstPool constPool;
    int accessFlags;
    int name;
    String cachedName;
    int descriptor;

    /**
     * If this value is true, Javassist maintains a StackMap attribute
     * generated by the preverify tool of J2ME (CLDC).  The initial
     * value of this field is false.
     */
    public static boolean doPreverify = false;

    /**
     * The name of constructors: <init>.
     */
    public static final String nameInit = "";

    /**
     * The name of class initializer (static initializer):
     * <clinit>.
     */
    public static final String nameClinit = "";

    private MethodInfo(final ConstPool cp) {
        constPool = cp;
        attribute = null;
    }

    /**
     * Constructs a method_info structure. The initial value of
     * access_flags is zero.
     *
     * @param cp
     *            a constant pool table
     * @param methodname
     *            method name
     * @param desc
     *            method descriptor
     * @see Descriptor
     */
    public MethodInfo(final ConstPool cp, final String methodname, final String desc) {
        this(cp);
        accessFlags = 0;
        name = cp.addUtf8Info(methodname);
        cachedName = methodname;
        descriptor = constPool.addUtf8Info(desc);
    }

    MethodInfo(final ConstPool cp, final DataInput in) throws IOException {
        this(cp);
        read(in);
    }

    /**
     * Constructs a copy of method_info structure. Class names
     * appearing in the source method_info are renamed according
     * to classnameMap.
     *
     * 

* Note: only Code and Exceptions attributes * are copied from the source. The other attributes are ignored. * * @param cp * a constant pool table * @param methodname * a method name * @param src * a source method_info * @param classnameMap * specifies pairs of replaced and substituted name. * @see Descriptor */ public MethodInfo(final ConstPool cp, final String methodname, final MethodInfo src, final Map classnameMap) throws BadBytecode { this(cp); read(src, methodname, classnameMap); } /** * Returns a string representation of the object. */ @Override public String toString() { return getSignature(); } @Override public String getSignature() { return getName() + " " + getDescriptor(); } /** * Copies all constant pool items to a given new constant pool * and replaces the original items with the new ones. * This is used for garbage collecting the items of removed fields * and methods. * * @param cp the destination */ void compact(final ConstPool cp) { name = cp.addUtf8Info(getName()); descriptor = cp.addUtf8Info(getDescriptor()); attribute = AttributeInfo.copyAll(attribute, cp); constPool = cp; } void prune(final ConstPool cp) { final ArrayList newAttributes = new ArrayList(); AttributeInfo invisibleAnnotations = getAttribute(AnnotationsAttribute.invisibleTag); if (invisibleAnnotations != null) { invisibleAnnotations = invisibleAnnotations.copy(cp, null); newAttributes.add(invisibleAnnotations); } AttributeInfo visibleAnnotations = getAttribute(AnnotationsAttribute.visibleTag); if (visibleAnnotations != null) { visibleAnnotations = visibleAnnotations.copy(cp, null); newAttributes.add(visibleAnnotations); } AttributeInfo parameterInvisibleAnnotations = getAttribute(ParameterAnnotationsAttribute.invisibleTag); if (parameterInvisibleAnnotations != null) { parameterInvisibleAnnotations = parameterInvisibleAnnotations.copy(cp, null); newAttributes.add(parameterInvisibleAnnotations); } AttributeInfo parameterVisibleAnnotations = getAttribute(ParameterAnnotationsAttribute.visibleTag); if (parameterVisibleAnnotations != null) { parameterVisibleAnnotations = parameterVisibleAnnotations.copy(cp, null); newAttributes.add(parameterVisibleAnnotations); } final AnnotationDefaultAttribute defaultAttribute = (AnnotationDefaultAttribute) getAttribute(AnnotationDefaultAttribute.tag); if (defaultAttribute != null) { newAttributes.add(defaultAttribute); } final ExceptionsAttribute ea = getExceptionsAttribute(); if (ea != null) { newAttributes.add(ea); } AttributeInfo signature = getAttribute(SignatureAttribute.tag); if (signature != null) { signature = signature.copy(cp, null); newAttributes.add(signature); } attribute = newAttributes; name = cp.addUtf8Info(getName()); descriptor = cp.addUtf8Info(getDescriptor()); constPool = cp; } /** * Returns a method name. */ public String getName() { if (cachedName == null) { cachedName = constPool.getUtf8Info(name); } return cachedName; } /** * Sets a method name. */ public void setName(final String newName) { name = constPool.addUtf8Info(newName); cachedName = newName; } /** * Returns true if this is not a constructor or a class initializer (static * initializer). */ public boolean isMethod() { final String n = getName(); return !n.equals(nameInit) && !n.equals(nameClinit); } /** * Returns a constant pool table used by this method. */ public ConstPool getConstPool() { return constPool; } /** * Returns true if this is a constructor. */ public boolean isConstructor() { return getName().equals(nameInit); } /** * Returns true if this is a class initializer (static initializer). */ public boolean isStaticInitializer() { return getName().equals(nameClinit); } /** * Returns access flags. * * @see AccessFlag */ public int getAccessFlags() { return accessFlags; } /** * Sets access flags. * * @see AccessFlag */ public void setAccessFlags(final int acc) { accessFlags = acc; } /** * Returns a method descriptor. * * @see Descriptor */ public String getDescriptor() { return constPool.getUtf8Info(descriptor); } /** * Sets a method descriptor. * * @see Descriptor */ public void setDescriptor(final String desc) { if (!desc.equals(getDescriptor())) { descriptor = constPool.addUtf8Info(desc); } } /** * Appends an attribute. If there is already an attribute with the same * name, the new one substitutes for it. * * @see #getAttributes() */ public void addAttribute(final AttributeInfo info) { if (attribute == null) { attribute = new ArrayList(); } AttributeInfo.remove(attribute, info.getName()); attribute.add(info); } /** * Returns an Exceptions attribute. * * @return an Exceptions attribute or null if it is not specified. */ public ExceptionsAttribute getExceptionsAttribute() { final AttributeInfo info = AttributeInfo.lookup(attribute, ExceptionsAttribute.tag); return (ExceptionsAttribute)info; } /** * Returns a Code attribute. * * @return a Code attribute or null if it is not specified. */ public CodeAttribute getCodeAttribute() { final AttributeInfo info = AttributeInfo.lookup(attribute, CodeAttribute.tag); return (CodeAttribute)info; } /** * Removes an Exception attribute. */ public void removeExceptionsAttribute() { AttributeInfo.remove(attribute, ExceptionsAttribute.tag); } /** * Adds an Exception attribute. * *

* The added attribute must share the same constant pool table as this * method_info structure. */ public void setExceptionsAttribute(final ExceptionsAttribute cattr) { removeExceptionsAttribute(); if (attribute == null) { attribute = new ArrayList(); } attribute.add(cattr); } /** * Removes a Code attribute. */ public void removeCodeAttribute() { AttributeInfo.remove(attribute, CodeAttribute.tag); } /** * Adds a Code attribute. * *

* The added attribute must share the same constant pool table as this * method_info structure. */ public void setCodeAttribute(final CodeAttribute cattr) { removeCodeAttribute(); if (attribute == null) { attribute = new ArrayList(); } attribute.add(cattr); } // /** // * Rebuilds a stack map table if the class file is for Java 6 // * or later. Java 5 or older Java VMs do not recognize a stack // * map table. If doPreverify is true, this method // * also rebuilds a stack map for J2ME (CLDC). // * // * @param pool used for making type hierarchy. // * @param cf rebuild if this class file is for Java 6 or later. // * @see #rebuildStackMap(ClassPool) // * @see #rebuildStackMapForME(ClassPool) // * @since 3.6 // */ // public void rebuildStackMapIf6(ClassPool pool, ClassFile cf) // throws BadBytecode // { // if (cf.getMajorVersion() >= ClassFile.JAVA_6) // rebuildStackMap(pool); // // if (doPreverify) // rebuildStackMapForME(pool); // } // // /** // * Rebuilds a stack map table. If no stack map table is included, // * a new one is created. If this MethodInfo does not // * include a code attribute, nothing happens. // * // * @param pool used for making type hierarchy. // * @see StackMapTable // * @since 3.6 // */ // public void rebuildStackMap(ClassPool pool) throws BadBytecode { // CodeAttribute ca = getCodeAttribute(); // if (ca != null) { // StackMapTable smt = MapMaker.make(pool, this); // ca.setAttribute(smt); // } // } // /** // * Rebuilds a stack map table for J2ME (CLDC). If no stack map table is included, // * a new one is created. If this MethodInfo does not // * include a code attribute, nothing happens. // * // * @param pool used for making type hierarchy. // * @see StackMapTable // * @since 3.12 // */ // public void rebuildStackMapForME(ClassPool pool) throws BadBytecode { // CodeAttribute ca = getCodeAttribute(); // if (ca != null) { // StackMap sm = MapMaker.make2(pool, this); // ca.setAttribute(sm); // } // } /** * Returns the line number of the source line corresponding to the specified * bytecode contained in this method. * * @param pos * the position of the bytecode (>= 0). an index into the code * array. * @return -1 if this information is not available. */ public int getLineNumber(final int pos) { final CodeAttribute ca = getCodeAttribute(); if (ca == null) { return -1; } final LineNumberAttribute ainfo = (LineNumberAttribute)ca .getAttribute(LineNumberAttribute.tag); if (ainfo == null) { return -1; } return ainfo.toLineNumber(pos); } /** * Changes a super constructor called by this constructor. * *

* This method modifies a call to super(), which should be * at the head of a constructor body, so that a constructor in a different * super class is called. This method does not change actual parameters. * Hence the new super class must have a constructor with the same signature * as the original one. * *

* This method should be called when the super class of the class declaring * this method is changed. * *

* This method does not perform anything unless this MethodInfo * represents a constructor. * * @param superclass * the new super class */ public void setSuperclass(final String superclass) throws BadBytecode { if (!isConstructor()) { return; } final CodeAttribute ca = getCodeAttribute(); final byte[] code = ca.getCode(); final CodeIterator iterator = ca.iterator(); final int pos = iterator.skipSuperConstructor(); if (pos >= 0) { // not this() final ConstPool cp = constPool; final int mref = X_Byte.readU16bit(code, pos + 1); final int nt = cp.getMethodrefNameAndType(mref); final int sc = cp.addClassInfo(superclass); final int mref2 = cp.addMethodrefInfo(sc, nt); X_Byte.write16bit(mref2, code, pos + 1); } } /** * @throws BadBytecode */ private void read(final MethodInfo src, final String methodname, final Map classnames) throws BadBytecode { final ConstPool destCp = constPool; accessFlags = src.accessFlags; name = destCp.addUtf8Info(methodname); cachedName = methodname; final ConstPool srcCp = src.constPool; final String desc = srcCp.getUtf8Info(src.descriptor); final String desc2 = Descriptor.rename(desc, classnames); descriptor = destCp.addUtf8Info(desc2); attribute = new ArrayList(); final ExceptionsAttribute eattr = src.getExceptionsAttribute(); if (eattr != null) { attribute.add(eattr.copy(destCp, classnames)); } final CodeAttribute cattr = src.getCodeAttribute(); if (cattr != null) { attribute.add(cattr.copy(destCp, classnames)); } } private void read(final DataInput in) throws IOException { accessFlags = in.readUnsignedShort(); name = in.readUnsignedShort(); descriptor = in.readUnsignedShort(); final int n = in.readUnsignedShort(); attribute = new ArrayList(); for (int i = 0; i < n; ++i) { attribute.add(AttributeInfo.read(constPool, in)); } } void write(final DataOutputStream out) throws IOException { out.writeShort(accessFlags); out.writeShort(name); out.writeShort(descriptor); if (attribute == null) { out.writeShort(0); } else { out.writeShort(attribute.size()); AttributeInfo.writeAll(attribute, out); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy