diff --git a/jersey-server/src/main/java/com/sun/jersey/spi/scanning/AnnotationScannerListener.java b/jersey-server/src/main/java/com/sun/jersey/spi/scanning/AnnotationScannerListener.java index 4025bb0a0..753da1c01 100644 --- a/jersey-server/src/main/java/com/sun/jersey/spi/scanning/AnnotationScannerListener.java +++ b/jersey-server/src/main/java/com/sun/jersey/spi/scanning/AnnotationScannerListener.java @@ -39,19 +39,9 @@ */ package com.sun.jersey.spi.scanning; -import java.io.IOException; -import java.io.InputStream; -import java.lang.annotation.Annotation; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.Set; - import com.sun.jersey.core.osgi.OsgiRegistry; import com.sun.jersey.core.reflection.ReflectionHelper; import com.sun.jersey.core.spi.scanning.ScannerListener; -import java.security.AccessController; -import java.security.PrivilegedActionException; - import jersey.repackaged.org.objectweb.asm.AnnotationVisitor; import jersey.repackaged.org.objectweb.asm.Attribute; import jersey.repackaged.org.objectweb.asm.ClassReader; @@ -60,6 +50,15 @@ import jersey.repackaged.org.objectweb.asm.MethodVisitor; import jersey.repackaged.org.objectweb.asm.Opcodes; +import java.io.IOException; +import java.io.InputStream; +import java.lang.annotation.Annotation; +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Set; + /** * A scanner listener that processes Java class files (resource names * ending in ".class") annotated with one or more of a set of declared @@ -156,7 +155,7 @@ private final class AnnotatedClassVisitor extends ClassVisitor { private boolean isAnnotated; private AnnotatedClassVisitor() { - super(Opcodes.ASM5); + super(Opcodes.ASM6); } public void visit(int version, int access, String name, diff --git a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/AnnotationVisitor.java b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/AnnotationVisitor.java index 83a1c97e5..2d82497bd 100644 --- a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/AnnotationVisitor.java +++ b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/AnnotationVisitor.java @@ -33,7 +33,7 @@ * A visitor to visit a Java annotation. The methods of this class must be * called in the following order: ( visit | visitEnum | * visitAnnotation | visitArray )* visitEnd. - * + * * @author Eric Bruneton * @author Eugene Kuleshov */ @@ -41,7 +41,7 @@ public abstract class AnnotationVisitor { /** * The ASM API version implemented by this visitor. The value of this field - * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + * must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. */ protected final int api; @@ -53,10 +53,10 @@ public abstract class AnnotationVisitor { /** * Constructs a new {@link AnnotationVisitor}. - * + * * @param api * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. */ public AnnotationVisitor(final int api) { this(api, null); @@ -64,16 +64,16 @@ public AnnotationVisitor(final int api) { /** * Constructs a new {@link AnnotationVisitor}. - * + * * @param api * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. * @param av * the annotation visitor to which this visitor must delegate * method calls. May be null. */ public AnnotationVisitor(final int api, final AnnotationVisitor av) { - if (api != Opcodes.ASM4 && api != Opcodes.ASM5) { + if (api < Opcodes.ASM4 || api > Opcodes.ASM6) { throw new IllegalArgumentException(); } this.api = api; @@ -82,14 +82,14 @@ public AnnotationVisitor(final int api, final AnnotationVisitor av) { /** * Visits a primitive value of the annotation. - * + * * @param name * the value name. * @param value * the actual value, whose type must be {@link Byte}, * {@link Boolean}, {@link Character}, {@link Short}, * {@link Integer} , {@link Long}, {@link Float}, {@link Double}, - * {@link String} or {@link Type} or OBJECT or ARRAY sort. This + * {@link String} or {@link Type} of OBJECT or ARRAY sort. This * value can also be an array of byte, boolean, short, char, int, * long, float or double values (this is equivalent to using * {@link #visitArray visitArray} and visiting each array element @@ -103,7 +103,7 @@ public void visit(String name, Object value) { /** * Visits an enumeration value of the annotation. - * + * * @param name * the value name. * @param desc @@ -119,7 +119,7 @@ public void visitEnum(String name, String desc, String value) { /** * Visits a nested annotation value of the annotation. - * + * * @param name * the value name. * @param desc @@ -142,7 +142,7 @@ public AnnotationVisitor visitAnnotation(String name, String desc) { * types (such as byte, boolean, short, char, int, long, float or double) * can be passed as value to {@link #visit visit}. This is what * {@link ClassReader} does. - * + * * @param name * the value name. * @return a visitor to visit the actual array value elements, or diff --git a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/AnnotationWriter.java b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/AnnotationWriter.java index 7926a1af5..8011f42e2 100644 --- a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/AnnotationWriter.java +++ b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/AnnotationWriter.java @@ -31,7 +31,7 @@ /** * An {@link AnnotationVisitor} that generates annotations in bytecode form. - * + * * @author Eric Bruneton * @author Eugene Kuleshov */ @@ -89,7 +89,7 @@ final class AnnotationWriter extends AnnotationVisitor { /** * Constructs a new {@link AnnotationWriter}. - * + * * @param cw * the class writer to which this annotation must be added. * @param named @@ -104,7 +104,7 @@ final class AnnotationWriter extends AnnotationVisitor { */ AnnotationWriter(final ClassWriter cw, final boolean named, final ByteVector bv, final ByteVector parent, final int offset) { - super(Opcodes.ASM5); + super(Opcodes.ASM6); this.cw = cw; this.named = named; this.bv = bv; @@ -237,7 +237,7 @@ public void visitEnd() { /** * Returns the size of this annotation writer list. - * + * * @return the size of this annotation writer list. */ int getSize() { @@ -253,7 +253,7 @@ int getSize() { /** * Puts the annotations of this annotation writer list into the given byte * vector. - * + * * @param out * where the annotations must be put. */ @@ -281,7 +281,7 @@ void put(final ByteVector out) { /** * Puts the given annotation lists into the given byte vector. - * + * * @param panns * an array of annotation writer lists. * @param off @@ -319,7 +319,7 @@ static void put(final AnnotationWriter[] panns, final int off, /** * Puts the given type reference and type path into the given bytevector. * LOCAL_VARIABLE and RESOURCE_VARIABLE target types are not supported. - * + * * @param typeRef * a reference to the annotated type. See {@link TypeReference}. * @param typePath diff --git a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Attribute.java b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Attribute.java index a86ec0978..5ef8d9d0a 100644 --- a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Attribute.java +++ b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Attribute.java @@ -31,7 +31,7 @@ /** * A non standard class, field, method or code attribute. - * + * * @author Eric Bruneton * @author Eugene Kuleshov */ @@ -54,7 +54,7 @@ public class Attribute { /** * Constructs a new empty attribute. - * + * * @param type * the type of the attribute. */ @@ -65,7 +65,7 @@ protected Attribute(final String type) { /** * Returns true if this type of attribute is unknown. The default * implementation of this method always returns true. - * + * * @return true if this type of attribute is unknown. */ public boolean isUnknown() { @@ -74,7 +74,7 @@ public boolean isUnknown() { /** * Returns true if this type of attribute is a code attribute. - * + * * @return true if this type of attribute is a code attribute. */ public boolean isCodeAttribute() { @@ -83,7 +83,7 @@ public boolean isCodeAttribute() { /** * Returns the labels corresponding to this attribute. - * + * * @return the labels corresponding to this attribute, or null if * this attribute is not a code attribute that contains labels. */ @@ -96,7 +96,7 @@ protected Label[] getLabels() { * new {@link Attribute} object, of type {@link #type type}, * corresponding to the len bytes starting at the given offset, in * the given class reader. - * + * * @param cr * the class that contains the attribute to be read. * @param off @@ -133,7 +133,7 @@ protected Attribute read(final ClassReader cr, final int off, /** * Returns the byte array form of this attribute. - * + * * @param cw * the class to which this attribute must be added. This * parameter can be used to add to the constant pool of this @@ -166,7 +166,7 @@ protected ByteVector write(final ClassWriter cw, final byte[] code, /** * Returns the length of the attribute list that begins with this attribute. - * + * * @return the length of the attribute list that begins with this attribute. */ final int getCount() { @@ -181,7 +181,7 @@ final int getCount() { /** * Returns the size of all the attributes in this attribute list. - * + * * @param cw * the class writer to be used to convert the attributes into * byte arrays, with the {@link #write write} method. @@ -219,7 +219,7 @@ final int getSize(final ClassWriter cw, final byte[] code, final int len, /** * Writes all the attributes of this attribute list in the given byte * vector. - * + * * @param cw * the class writer to be used to convert the attributes into * byte arrays, with the {@link #write write} method. diff --git a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/ByteVector.java b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/ByteVector.java index 654985299..2fc3e5a8c 100644 --- a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/ByteVector.java +++ b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/ByteVector.java @@ -32,7 +32,7 @@ /** * A dynamically extensible vector of bytes. This class is roughly equivalent to * a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient. - * + * * @author Eric Bruneton */ public class ByteVector { @@ -58,7 +58,7 @@ public ByteVector() { /** * Constructs a new {@link ByteVector ByteVector} with the given initial * size. - * + * * @param initialSize * the initial size of the byte vector to be constructed. */ @@ -69,7 +69,7 @@ public ByteVector(final int initialSize) { /** * Puts a byte into this byte vector. The byte vector is automatically * enlarged if necessary. - * + * * @param b * a byte. * @return this byte vector. @@ -87,7 +87,7 @@ public ByteVector putByte(final int b) { /** * Puts two bytes into this byte vector. The byte vector is automatically * enlarged if necessary. - * + * * @param b1 * a byte. * @param b2 @@ -109,7 +109,7 @@ ByteVector put11(final int b1, final int b2) { /** * Puts a short into this byte vector. The byte vector is automatically * enlarged if necessary. - * + * * @param s * a short. * @return this byte vector. @@ -129,7 +129,7 @@ public ByteVector putShort(final int s) { /** * Puts a byte and a short into this byte vector. The byte vector is * automatically enlarged if necessary. - * + * * @param b * a byte. * @param s @@ -152,7 +152,7 @@ ByteVector put12(final int b, final int s) { /** * Puts an int into this byte vector. The byte vector is automatically * enlarged if necessary. - * + * * @param i * an int. * @return this byte vector. @@ -174,7 +174,7 @@ public ByteVector putInt(final int i) { /** * Puts a long into this byte vector. The byte vector is automatically * enlarged if necessary. - * + * * @param l * a long. * @return this byte vector. @@ -202,7 +202,7 @@ public ByteVector putLong(final long l) { /** * Puts an UTF8 string into this byte vector. The byte vector is * automatically enlarged if necessary. - * + * * @param s * a String whose UTF8 encoded length must be less than 65536. * @return this byte vector. @@ -243,7 +243,7 @@ public ByteVector putUTF8(final String s) { * automatically enlarged if necessary. The string length is encoded in two * bytes before the encoded characters, if there is space for that (i.e. if * this.length - i - 2 >= 0). - * + * * @param s * the String to encode. * @param i @@ -301,7 +301,7 @@ ByteVector encodeUTF8(final String s, int i, int maxByteLength) { /** * Puts an array of bytes into this byte vector. The byte vector is * automatically enlarged if necessary. - * + * * @param b * an array of bytes. May be null to put len * null bytes into this byte vector. @@ -324,7 +324,7 @@ public ByteVector putByteArray(final byte[] b, final int off, final int len) { /** * Enlarge this byte vector so that it can receive n more bytes. - * + * * @param size * number of additional bytes that this byte vector should be * able to receive. diff --git a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassReader.java b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassReader.java index 9f7ed33fa..c095e2692 100644 --- a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassReader.java +++ b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassReader.java @@ -37,37 +37,12 @@ * This class parses a byte array conforming to the Java class file format and * calls the appropriate visit methods of a given class visitor for each field, * method and bytecode instruction encountered. - * + * * @author Eric Bruneton * @author Eugene Kuleshov */ public class ClassReader { - /** - * True to enable signatures support. - */ - static final boolean SIGNATURES = true; - - /** - * True to enable annotations support. - */ - static final boolean ANNOTATIONS = true; - - /** - * True to enable stack map frames support. - */ - static final boolean FRAMES = true; - - /** - * True to enable bytecode writing support. - */ - static final boolean WRITER = true; - - /** - * True to enable JSR_W and GOTO_W support. - */ - static final boolean RESIZE = true; - /** * Flag to skip method code. If this class is set CODE * attribute won't be visited. This can be used, for example, to retrieve @@ -104,6 +79,21 @@ public class ClassReader { */ public static final int EXPAND_FRAMES = 8; + /** + * Flag to expand the ASM pseudo instructions into an equivalent sequence of + * standard bytecode instructions. When resolving a forward jump it may + * happen that the signed 2 bytes offset reserved for it is not sufficient + * to store the bytecode offset. In this case the jump instruction is + * replaced with a temporary ASM pseudo instruction using an unsigned 2 + * bytes offset (see Label#resolve). This internal flag is used to re-read + * classes containing such instructions, in order to replace them with + * standard instructions. In addition, when this flag is used, GOTO_W and + * JSR_W are not converted into GOTO and JSR, to make sure that + * infinite loops where a GOTO_W is replaced with a GOTO in ClassReader and + * converted back to a GOTO_W in ClassWriter cannot occur. + */ + static final int EXPAND_ASM_INSNS = 256; + /** * The class to be parsed. The content of this array must not be * modified. This field is intended for {@link Attribute} sub classes, and @@ -145,7 +135,7 @@ public class ClassReader { /** * Constructs a new {@link ClassReader} object. - * + * * @param b * the bytecode of the class to be read. */ @@ -155,7 +145,7 @@ public ClassReader(final byte[] b) { /** * Constructs a new {@link ClassReader} object. - * + * * @param b * the bytecode of the class to be read. * @param off @@ -166,7 +156,7 @@ public ClassReader(final byte[] b) { public ClassReader(final byte[] b, final int off, final int len) { this.b = b; // checks the class version - if (readShort(off + 6) > Opcodes.V1_8) { + if (readShort(off + 6) > Opcodes.V9) { throw new IllegalArgumentException(); } // parses the constant pool @@ -205,6 +195,8 @@ public ClassReader(final byte[] b, final int off, final int len) { // case ClassWriter.CLASS: // case ClassWriter.STR: // case ClassWriter.MTYPE + // case ClassWriter.PACKAGE: + // case ClassWriter.MODULE: default: size = 3; break; @@ -220,9 +212,9 @@ public ClassReader(final byte[] b, final int off, final int len) { * Returns the class's access flags (see {@link Opcodes}). This value may * not reflect Deprecated and Synthetic flags when bytecode is before 1.5 * and those flags are represented by attributes. - * + * * @return the class access flags - * + * * @see ClassVisitor#visit(int, int, String, String, String, String[]) */ public int getAccess() { @@ -232,9 +224,9 @@ public int getAccess() { /** * Returns the internal name of the class (see * {@link Type#getInternalName() getInternalName}). - * + * * @return the internal class name - * + * * @see ClassVisitor#visit(int, int, String, String, String, String[]) */ public String getClassName() { @@ -245,10 +237,10 @@ public String getClassName() { * Returns the internal of name of the super class (see * {@link Type#getInternalName() getInternalName}). For interfaces, the * super class is {@link Object}. - * + * * @return the internal name of super class, or null for * {@link Object} class. - * + * * @see ClassVisitor#visit(int, int, String, String, String, String[]) */ public String getSuperName() { @@ -258,10 +250,10 @@ public String getSuperName() { /** * Returns the internal names of the class's interfaces (see * {@link Type#getInternalName() getInternalName}). - * + * * @return the array of internal names for all implemented interfaces or * null. - * + * * @see ClassVisitor#visit(int, int, String, String, String, String[]) */ public String[] getInterfaces() { @@ -281,7 +273,7 @@ public String[] getInterfaces() { /** * Copies the constant pool data into the given {@link ClassWriter}. Should * be called before the {@link #accept(ClassVisitor,int)} method. - * + * * @param classWriter * the {@link ClassWriter} to copy constant pool into. */ @@ -348,7 +340,9 @@ void copyPool(final ClassWriter classWriter) { break; // case ClassWriter.STR: // case ClassWriter.CLASS: - // case ClassWriter.MTYPE + // case ClassWriter.MTYPE: + // case ClassWriter.MODULE: + // case ClassWriter.PACKAGE: default: item.set(tag, readUTF8(index, buf), null, null); break; @@ -369,7 +363,7 @@ void copyPool(final ClassWriter classWriter) { /** * Copies the bootstrap method data into the given {@link ClassWriter}. * Should be called before the {@link #accept(ClassVisitor,int)} method. - * + * * @param classWriter * the {@link ClassWriter} to copy bootstrap methods into. */ @@ -414,7 +408,7 @@ private void copyBootstrapMethods(final ClassWriter classWriter, /** * Constructs a new {@link ClassReader} object. - * + * * @param is * an input stream from which to read the class. * @throws IOException @@ -426,7 +420,7 @@ public ClassReader(final InputStream is) throws IOException { /** * Constructs a new {@link ClassReader} object. - * + * * @param name * the binary qualified name of the class to be read. * @throws IOException @@ -440,7 +434,7 @@ public ClassReader(final String name) throws IOException { /** * Reads the bytecode of a class. - * + * * @param is * an input stream from which to read the class. * @param close @@ -494,7 +488,7 @@ private static byte[] readClass(final InputStream is, boolean close) * Makes the given visitor visit the Java class of this {@link ClassReader} * . This class is the one specified in the constructor (see * {@link #ClassReader(byte[]) ClassReader}). - * + * * @param classVisitor * the visitor that must visit this class. * @param flags @@ -510,7 +504,7 @@ public void accept(final ClassVisitor classVisitor, final int flags) { * Makes the given visitor visit the Java class of this {@link ClassReader}. * This class is the one specified in the constructor (see * {@link #ClassReader(byte[]) ClassReader}). - * + * * @param classVisitor * the visitor that must visit this class. * @param attrs @@ -555,11 +549,14 @@ public void accept(final ClassVisitor classVisitor, String enclosingOwner = null; String enclosingName = null; String enclosingDesc = null; + String moduleMainClass = null; int anns = 0; int ianns = 0; int tanns = 0; int itanns = 0; int innerClasses = 0; + int module = 0; + int packages = 0; Attribute attributes = null; u = getAttributes(); @@ -578,13 +575,11 @@ public void accept(final ClassVisitor classVisitor, enclosingName = readUTF8(items[item], c); enclosingDesc = readUTF8(items[item] + 2, c); } - } else if (SIGNATURES && "Signature".equals(attrName)) { + } else if ("Signature".equals(attrName)) { signature = readUTF8(u + 8, c); - } else if (ANNOTATIONS - && "RuntimeVisibleAnnotations".equals(attrName)) { + } else if ("RuntimeVisibleAnnotations".equals(attrName)) { anns = u + 8; - } else if (ANNOTATIONS - && "RuntimeVisibleTypeAnnotations".equals(attrName)) { + } else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) { tanns = u + 8; } else if ("Deprecated".equals(attrName)) { access |= Opcodes.ACC_DEPRECATED; @@ -594,12 +589,16 @@ public void accept(final ClassVisitor classVisitor, } else if ("SourceDebugExtension".equals(attrName)) { int len = readInt(u + 4); sourceDebug = readUTF(u + 8, len, new char[len]); - } else if (ANNOTATIONS - && "RuntimeInvisibleAnnotations".equals(attrName)) { + } else if ("RuntimeInvisibleAnnotations".equals(attrName)) { ianns = u + 8; - } else if (ANNOTATIONS - && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { + } else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) { itanns = u + 8; + } else if ("Module".equals(attrName)) { + module = u + 8; + } else if ("ModuleMainClass".equals(attrName)) { + moduleMainClass = readClass(u + 8, c); + } else if ("ModulePackages".equals(attrName)) { + packages = u + 10; } else if ("BootstrapMethods".equals(attrName)) { int[] bootstrapMethods = new int[readUnsignedShort(u + 8)]; for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) { @@ -628,6 +627,12 @@ public void accept(final ClassVisitor classVisitor, classVisitor.visitSource(sourceFile, sourceDebug); } + // visits the module info and associated attributes + if (module != 0) { + readModule(classVisitor, context, module, + moduleMainClass, packages); + } + // visits the outer class if (enclosingOwner != null) { classVisitor.visitOuterClass(enclosingOwner, enclosingName, @@ -635,19 +640,19 @@ public void accept(final ClassVisitor classVisitor, } // visits the class annotations and type annotations - if (ANNOTATIONS && anns != 0) { + if (anns != 0) { for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { v = readAnnotationValues(v + 2, c, true, classVisitor.visitAnnotation(readUTF8(v, c), true)); } } - if (ANNOTATIONS && ianns != 0) { + if (ianns != 0) { for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { v = readAnnotationValues(v + 2, c, true, classVisitor.visitAnnotation(readUTF8(v, c), false)); } } - if (ANNOTATIONS && tanns != 0) { + if (tanns != 0) { for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) { v = readAnnotationTarget(context, v); v = readAnnotationValues(v + 2, c, true, @@ -655,7 +660,7 @@ public void accept(final ClassVisitor classVisitor, context.typePath, readUTF8(v, c), true)); } } - if (ANNOTATIONS && itanns != 0) { + if (itanns != 0) { for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) { v = readAnnotationTarget(context, v); v = readAnnotationValues(v + 2, c, true, @@ -697,9 +702,123 @@ public void accept(final ClassVisitor classVisitor, classVisitor.visitEnd(); } + /** + * Reads the module attribute and visit it. + * + * @param classVisitor + * the current class visitor + * @param context + * information about the class being parsed. + * @param u + * start offset of the module attribute in the class file. + * @param mainClass + * name of the main class of a module or null. + * @param packages + * start offset of the concealed package attribute. + */ + private void readModule(final ClassVisitor classVisitor, + final Context context, int u, + final String mainClass, int packages) { + + char[] buffer = context.buffer; + + // reads module name, flags and version + String name = readModule(u, buffer); + int flags = readUnsignedShort(u + 2); + String version = readUTF8(u + 4, buffer); + u += 6; + + ModuleVisitor mv = classVisitor.visitModule(name, flags, version); + if (mv == null) { + return; + } + + // module attributes (main class, packages) + if (mainClass != null) { + mv.visitMainClass(mainClass); + } + + if (packages != 0) { + for (int i = readUnsignedShort(packages - 2); i > 0; --i) { + String packaze = readPackage(packages, buffer); + mv.visitPackage(packaze); + packages += 2; + } + } + + // reads requires + u += 2; + for (int i = readUnsignedShort(u - 2); i > 0; --i) { + String module = readModule(u, buffer); + int access = readUnsignedShort(u + 2); + String requireVersion = readUTF8(u + 4, buffer); + mv.visitRequire(module, access, requireVersion); + u += 6; + } + + // reads exports + u += 2; + for (int i = readUnsignedShort(u - 2); i > 0; --i) { + String export = readPackage(u, buffer); + int access = readUnsignedShort(u + 2); + int exportToCount = readUnsignedShort(u + 4); + u += 6; + String[] tos = null; + if (exportToCount != 0) { + tos = new String[exportToCount]; + for (int j = 0; j < tos.length; ++j) { + tos[j] = readModule(u, buffer); + u += 2; + } + } + mv.visitExport(export, access, tos); + } + + // reads opens + u += 2; + for (int i = readUnsignedShort(u - 2); i > 0; --i) { + String open = readPackage(u, buffer); + int access = readUnsignedShort(u + 2); + int openToCount = readUnsignedShort(u + 4); + u += 6; + String[] tos = null; + if (openToCount != 0) { + tos = new String[openToCount]; + for (int j = 0; j < tos.length; ++j) { + tos[j] = readModule(u, buffer); + u += 2; + } + } + mv.visitOpen(open, access, tos); + } + + // read uses + u += 2; + for (int i = readUnsignedShort(u - 2); i > 0; --i) { + mv.visitUse(readClass(u, buffer)); + u += 2; + } + + // read provides + u += 2; + for (int i = readUnsignedShort(u - 2); i > 0; --i) { + String service = readClass(u, buffer); + int provideWithCount = readUnsignedShort(u + 2); + u += 4; + String[] withs = new String[provideWithCount]; + for (int j = 0; j < withs.length; ++j) { + withs[j] = readClass(u, buffer); + u += 2; + } + mv.visitProvide(service, withs); + } + + mv.visitEnd(); + } + /** * Reads a field and makes the given visitor visit it. - * + * * @param classVisitor * the visitor that must visit the field. * @param context @@ -733,24 +852,20 @@ private int readField(final ClassVisitor classVisitor, if ("ConstantValue".equals(attrName)) { int item = readUnsignedShort(u + 8); value = item == 0 ? null : readConst(item, c); - } else if (SIGNATURES && "Signature".equals(attrName)) { + } else if ("Signature".equals(attrName)) { signature = readUTF8(u + 8, c); } else if ("Deprecated".equals(attrName)) { access |= Opcodes.ACC_DEPRECATED; } else if ("Synthetic".equals(attrName)) { access |= Opcodes.ACC_SYNTHETIC | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE; - } else if (ANNOTATIONS - && "RuntimeVisibleAnnotations".equals(attrName)) { + } else if ("RuntimeVisibleAnnotations".equals(attrName)) { anns = u + 8; - } else if (ANNOTATIONS - && "RuntimeVisibleTypeAnnotations".equals(attrName)) { + } else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) { tanns = u + 8; - } else if (ANNOTATIONS - && "RuntimeInvisibleAnnotations".equals(attrName)) { + } else if ("RuntimeInvisibleAnnotations".equals(attrName)) { ianns = u + 8; - } else if (ANNOTATIONS - && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { + } else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) { itanns = u + 8; } else { Attribute attr = readAttribute(context.attrs, attrName, u + 8, @@ -772,19 +887,19 @@ private int readField(final ClassVisitor classVisitor, } // visits the field annotations and type annotations - if (ANNOTATIONS && anns != 0) { + if (anns != 0) { for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { v = readAnnotationValues(v + 2, c, true, fv.visitAnnotation(readUTF8(v, c), true)); } } - if (ANNOTATIONS && ianns != 0) { + if (ianns != 0) { for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { v = readAnnotationValues(v + 2, c, true, fv.visitAnnotation(readUTF8(v, c), false)); } } - if (ANNOTATIONS && tanns != 0) { + if (tanns != 0) { for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) { v = readAnnotationTarget(context, v); v = readAnnotationValues(v + 2, c, true, @@ -792,7 +907,7 @@ private int readField(final ClassVisitor classVisitor, context.typePath, readUTF8(v, c), true)); } } - if (ANNOTATIONS && itanns != 0) { + if (itanns != 0) { for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) { v = readAnnotationTarget(context, v); v = readAnnotationValues(v + 2, c, true, @@ -817,7 +932,7 @@ private int readField(final ClassVisitor classVisitor, /** * Reads a method and makes the given visitor visit it. - * + * * @param classVisitor * the visitor that must visit the method. * @param context @@ -866,32 +981,26 @@ private int readMethod(final ClassVisitor classVisitor, exceptions[j] = readClass(exception, c); exception += 2; } - } else if (SIGNATURES && "Signature".equals(attrName)) { + } else if ("Signature".equals(attrName)) { signature = readUTF8(u + 8, c); } else if ("Deprecated".equals(attrName)) { context.access |= Opcodes.ACC_DEPRECATED; - } else if (ANNOTATIONS - && "RuntimeVisibleAnnotations".equals(attrName)) { + } else if ("RuntimeVisibleAnnotations".equals(attrName)) { anns = u + 8; - } else if (ANNOTATIONS - && "RuntimeVisibleTypeAnnotations".equals(attrName)) { + } else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) { tanns = u + 8; - } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) { + } else if ("AnnotationDefault".equals(attrName)) { dann = u + 8; } else if ("Synthetic".equals(attrName)) { context.access |= Opcodes.ACC_SYNTHETIC | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE; - } else if (ANNOTATIONS - && "RuntimeInvisibleAnnotations".equals(attrName)) { + } else if ("RuntimeInvisibleAnnotations".equals(attrName)) { ianns = u + 8; - } else if (ANNOTATIONS - && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { + } else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) { itanns = u + 8; - } else if (ANNOTATIONS - && "RuntimeVisibleParameterAnnotations".equals(attrName)) { + } else if ("RuntimeVisibleParameterAnnotations".equals(attrName)) { mpanns = u + 8; - } else if (ANNOTATIONS - && "RuntimeInvisibleParameterAnnotations".equals(attrName)) { + } else if ("RuntimeInvisibleParameterAnnotations".equals(attrName)) { impanns = u + 8; } else if ("MethodParameters".equals(attrName)) { methodParameters = u + 8; @@ -924,7 +1033,7 @@ private int readMethod(final ClassVisitor classVisitor, * access, name and descriptor can have been changed, this is not * important since they are not copied as is from the reader). */ - if (WRITER && mv instanceof MethodWriter) { + if (mv instanceof MethodWriter) { MethodWriter mw = (MethodWriter) mv; if (mw.cw.cr == this && signature == mw.signature) { boolean sameExceptions = false; @@ -961,26 +1070,26 @@ private int readMethod(final ClassVisitor classVisitor, } // visits the method annotations - if (ANNOTATIONS && dann != 0) { + if (dann != 0) { AnnotationVisitor dv = mv.visitAnnotationDefault(); readAnnotationValue(dann, c, null, dv); if (dv != null) { dv.visitEnd(); } } - if (ANNOTATIONS && anns != 0) { + if (anns != 0) { for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { v = readAnnotationValues(v + 2, c, true, mv.visitAnnotation(readUTF8(v, c), true)); } } - if (ANNOTATIONS && ianns != 0) { + if (ianns != 0) { for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { v = readAnnotationValues(v + 2, c, true, mv.visitAnnotation(readUTF8(v, c), false)); } } - if (ANNOTATIONS && tanns != 0) { + if (tanns != 0) { for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) { v = readAnnotationTarget(context, v); v = readAnnotationValues(v + 2, c, true, @@ -988,7 +1097,7 @@ private int readMethod(final ClassVisitor classVisitor, context.typePath, readUTF8(v, c), true)); } } - if (ANNOTATIONS && itanns != 0) { + if (itanns != 0) { for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) { v = readAnnotationTarget(context, v); v = readAnnotationValues(v + 2, c, true, @@ -996,10 +1105,10 @@ private int readMethod(final ClassVisitor classVisitor, context.typePath, readUTF8(v, c), false)); } } - if (ANNOTATIONS && mpanns != 0) { + if (mpanns != 0) { readParameterAnnotations(mv, context, mpanns, true); } - if (ANNOTATIONS && impanns != 0) { + if (impanns != 0) { readParameterAnnotations(mv, context, impanns, false); } @@ -1025,7 +1134,7 @@ private int readMethod(final ClassVisitor classVisitor, /** * Reads the bytecode of a method and makes the given visitor visit it. - * + * * @param mv * the visitor that must visit the method's code. * @param context @@ -1046,7 +1155,7 @@ private void readCode(final MethodVisitor mv, final Context context, int u) { int codeStart = u; int codeEnd = u + codeLength; Label[] labels = context.labels = new Label[codeLength + 2]; - readLabel(codeLength + 1, labels); + createLabel(codeLength + 1, labels); while (u < codeEnd) { int offset = u - codeStart; int opcode = b[u] & 0xFF; @@ -1056,11 +1165,16 @@ private void readCode(final MethodVisitor mv, final Context context, int u) { u += 1; break; case ClassWriter.LABEL_INSN: - readLabel(offset + readShort(u + 1), labels); + createLabel(offset + readShort(u + 1), labels); + u += 3; + break; + case ClassWriter.ASM_LABEL_INSN: + createLabel(offset + readUnsignedShort(u + 1), labels); u += 3; break; case ClassWriter.LABELW_INSN: - readLabel(offset + readInt(u + 1), labels); + case ClassWriter.ASM_LABELW_INSN: + createLabel(offset + readInt(u + 1), labels); u += 5; break; case ClassWriter.WIDE_INSN: @@ -1075,9 +1189,9 @@ private void readCode(final MethodVisitor mv, final Context context, int u) { // skips 0 to 3 padding bytes u = u + 4 - (offset & 3); // reads instruction - readLabel(offset + readInt(u), labels); + createLabel(offset + readInt(u), labels); for (int i = readInt(u + 8) - readInt(u + 4) + 1; i > 0; --i) { - readLabel(offset + readInt(u + 12), labels); + createLabel(offset + readInt(u + 12), labels); u += 4; } u += 12; @@ -1086,9 +1200,9 @@ private void readCode(final MethodVisitor mv, final Context context, int u) { // skips 0 to 3 padding bytes u = u + 4 - (offset & 3); // reads instruction - readLabel(offset + readInt(u), labels); + createLabel(offset + readInt(u), labels); for (int i = readInt(u + 4); i > 0; --i) { - readLabel(offset + readInt(u + 12), labels); + createLabel(offset + readInt(u + 12), labels); u += 8; } u += 8; @@ -1118,9 +1232,9 @@ private void readCode(final MethodVisitor mv, final Context context, int u) { // reads the try catch entries to find the labels, and also visits them for (int i = readUnsignedShort(u); i > 0; --i) { - Label start = readLabel(readUnsignedShort(u + 2), labels); - Label end = readLabel(readUnsignedShort(u + 4), labels); - Label handler = readLabel(readUnsignedShort(u + 6), labels); + Label start = createLabel(readUnsignedShort(u + 2), labels); + Label end = createLabel(readUnsignedShort(u + 4), labels); + Label handler = createLabel(readUnsignedShort(u + 6), labels); String type = readUTF8(items[readUnsignedShort(u + 8)], c); mv.visitTryCatchBlock(start, end, handler, type); u += 8; @@ -1151,13 +1265,9 @@ private void readCode(final MethodVisitor mv, final Context context, int u) { varTable = u + 8; for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) { int label = readUnsignedShort(v + 10); - if (labels[label] == null) { - readLabel(label, labels).status |= Label.DEBUG; - } + createDebugLabel(label, labels); label += readUnsignedShort(v + 12); - if (labels[label] == null) { - readLabel(label, labels).status |= Label.DEBUG; - } + createDebugLabel(label, labels); v += 10; } } @@ -1167,24 +1277,27 @@ private void readCode(final MethodVisitor mv, final Context context, int u) { if ((context.flags & SKIP_DEBUG) == 0) { for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) { int label = readUnsignedShort(v + 10); - if (labels[label] == null) { - readLabel(label, labels).status |= Label.DEBUG; + createDebugLabel(label, labels); + Label l = labels[label]; + while (l.line > 0) { + if (l.next == null) { + l.next = new Label(); + } + l = l.next; } - labels[label].line = readUnsignedShort(v + 12); + l.line = readUnsignedShort(v + 12); v += 4; } } - } else if (ANNOTATIONS - && "RuntimeVisibleTypeAnnotations".equals(attrName)) { + } else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) { tanns = readTypeAnnotations(mv, context, u + 8, true); ntoff = tanns.length == 0 || readByte(tanns[0]) < 0x43 ? -1 : readUnsignedShort(tanns[0] + 1); - } else if (ANNOTATIONS - && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { + } else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) { itanns = readTypeAnnotations(mv, context, u + 8, false); nitoff = itanns.length == 0 || readByte(itanns[0]) < 0x43 ? -1 : readUnsignedShort(itanns[0] + 1); - } else if (FRAMES && "StackMapTable".equals(attrName)) { + } else if ("StackMapTable".equals(attrName)) { if ((context.flags & SKIP_FRAMES) == 0) { stackMap = u + 10; stackMapSize = readInt(u + 4); @@ -1208,7 +1321,7 @@ private void readCode(final MethodVisitor mv, final Context context, int u) { * this by parsing the stack map table without a full decoding * (see below). */ - } else if (FRAMES && "StackMap".equals(attrName)) { + } else if ("StackMap".equals(attrName)) { if ((context.flags & SKIP_FRAMES) == 0) { zip = false; stackMap = u + 10; @@ -1237,7 +1350,7 @@ private void readCode(final MethodVisitor mv, final Context context, int u) { u += 2; // generates the first (implicit) stack map frame - if (FRAMES && stackMap != 0) { + if (stackMap != 0) { /* * for the first explicit frame the offset is not offset_delta + 1 * but only offset_delta; setting the implicit frame offset to -1 @@ -1270,14 +1383,31 @@ private void readCode(final MethodVisitor mv, final Context context, int u) { int v = readUnsignedShort(i + 1); if (v >= 0 && v < codeLength) { if ((b[codeStart + v] & 0xFF) == Opcodes.NEW) { - readLabel(v, labels); + createLabel(v, labels); } } } } } + if ((context.flags & EXPAND_ASM_INSNS) != 0 + && (context.flags & EXPAND_FRAMES) != 0) { + // Expanding the ASM pseudo instructions can introduce F_INSERT + // frames, even if the method does not currently have any frame. + // Also these inserted frames must be computed by simulating the + // effect of the bytecode instructions one by one, starting from the + // first one and the last existing frame (or the implicit first + // one). Finally, due to the way MethodWriter computes this (with + // the compute = INSERTED_FRAMES option), MethodWriter needs to know + // maxLocals before the first instruction is visited. For all these + // reasons we always visit the implicit first frame in this case + // (passing only maxLocals - the rest can be and is computed in + // MethodWriter). + mv.visitFrame(Opcodes.F_NEW, maxLocals, null, 0, null); + } // visits the instructions + int opcodeDelta = (context.flags & EXPAND_ASM_INSNS) == 0 ? -33 : 0; + boolean insertFrame = false; u = codeStart; while (u < codeEnd) { int offset = u - codeStart; @@ -1285,14 +1415,20 @@ private void readCode(final MethodVisitor mv, final Context context, int u) { // visits the label and line number for this offset, if any Label l = labels[offset]; if (l != null) { + Label next = l.next; + l.next = null; mv.visitLabel(l); if ((context.flags & SKIP_DEBUG) == 0 && l.line > 0) { mv.visitLineNumber(l.line, l); + while (next != null) { + mv.visitLineNumber(next.line, l); + next = next.next; + } } } // visits the frame for this offset, if any - while (FRAMES && frame != null + while (frame != null && (frame.offset == offset || frame.offset == -1)) { // if there is a frame for this offset, makes the visitor visit // it, and reads the next frame if there is one. @@ -1304,6 +1440,9 @@ private void readCode(final MethodVisitor mv, final Context context, int u) { mv.visitFrame(frame.mode, frame.localDiff, frame.local, frame.stackCount, frame.stack); } + // if there is already a frame for this offset, there is no + // need to insert a new one. + insertFrame = false; } if (frameCount > 0) { stackMap = readFrame(stackMap, zip, unzip, frame); @@ -1312,6 +1451,13 @@ private void readCode(final MethodVisitor mv, final Context context, int u) { frame = null; } } + // inserts a frame for this offset, if requested by setting + // insertFrame to true during the previous iteration. The actual + // frame content will be computed in MethodWriter. + if (insertFrame) { + mv.visitFrame(ClassWriter.F_INSERT, 0, null, 0, null); + insertFrame = false; + } // visits the instruction at this offset int opcode = b[u] & 0xFF; @@ -1336,9 +1482,47 @@ private void readCode(final MethodVisitor mv, final Context context, int u) { u += 3; break; case ClassWriter.LABELW_INSN: - mv.visitJumpInsn(opcode - 33, labels[offset + readInt(u + 1)]); + mv.visitJumpInsn(opcode + opcodeDelta, labels[offset + + readInt(u + 1)]); u += 5; break; + case ClassWriter.ASM_LABEL_INSN: { + // changes temporary opcodes 202 to 217 (inclusive), 218 + // and 219 to IFEQ ... JSR (inclusive), IFNULL and + // IFNONNULL + opcode = opcode < 218 ? opcode - 49 : opcode - 20; + Label target = labels[offset + readUnsignedShort(u + 1)]; + // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx + // with IFNOTxxx GOTO_W L:..., where IFNOTxxx is + // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) + // and where designates the instruction just after + // the GOTO_W. + if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) { + mv.visitJumpInsn(opcode + 33, target); + } else { + opcode = opcode <= 166 ? ((opcode + 1) ^ 1) - 1 + : opcode ^ 1; + Label endif = createLabel(offset + 3, labels); + mv.visitJumpInsn(opcode, endif); + mv.visitJumpInsn(200, target); // GOTO_W + // endif designates the instruction just after GOTO_W, + // and is visited as part of the next instruction. Since + // it is a jump target, we need to insert a frame here. + insertFrame = true; + } + u += 3; + break; + } + case ClassWriter.ASM_LABELW_INSN: { + // replaces the pseudo GOTO_W instruction with a real one. + mv.visitJumpInsn(200, labels[offset + readInt(u + 1)]); + // The instruction just after is a jump target (because pseudo + // GOTO_W are used in patterns IFNOTxxx GOTO_W L:..., + // see MethodWriter), so we need to insert a frame here. + insertFrame = true; + u += 5; + break; + } case ClassWriter.WIDE_INSN: opcode = b[u + 1] & 0xFF; if (opcode == Opcodes.IINC) { @@ -1557,7 +1741,7 @@ context.end, context.index, readUTF8(v, c), /** * Parses a type annotation table to find the labels, and to visit the try * catch block annotations. - * + * * @param u * the start offset of a type annotation table. * @param mv @@ -1594,8 +1778,8 @@ private int[] readTypeAnnotations(final MethodVisitor mv, for (int j = readUnsignedShort(u + 1); j > 0; --j) { int start = readUnsignedShort(u + 3); int length = readUnsignedShort(u + 5); - readLabel(start, context.labels); - readLabel(start + length, context.labels); + createLabel(start, context.labels); + createLabel(start + length, context.labels); u += 6; } u += 3; @@ -1640,7 +1824,7 @@ private int[] readTypeAnnotations(final MethodVisitor mv, * start offset of the rest of the type_annotation structure (i.e. the * offset to the type_index field, which is followed by * num_element_value_pairs and then the name,value pairs). - * + * * @param context * information about the class being parsed. This is where the * extracted target_type and target_path must be stored. @@ -1674,8 +1858,8 @@ private int readAnnotationTarget(final Context context, int u) { for (int i = 0; i < n; ++i) { int start = readUnsignedShort(u); int length = readUnsignedShort(u + 2); - context.start[i] = readLabel(start, context.labels); - context.end[i] = readLabel(start + length, context.labels); + context.start[i] = createLabel(start, context.labels); + context.end[i] = createLabel(start + length, context.labels); context.index[i] = readUnsignedShort(u + 4); u += 6; } @@ -1711,7 +1895,7 @@ private int readAnnotationTarget(final Context context, int u) { /** * Reads parameter annotations and makes the given visitor visit them. - * + * * @param mv * the visitor that must visit the annotations. * @param context @@ -1754,7 +1938,7 @@ private void readParameterAnnotations(final MethodVisitor mv, /** * Reads the values of an annotation and makes the given visitor visit them. - * + * * @param v * the start offset in {@link #b b} of the values to be read * (including the unsigned short that gives the number of @@ -1790,7 +1974,7 @@ private int readAnnotationValues(int v, final char[] buf, /** * Reads a value of an annotation and makes the given visitor visit it. - * + * * @param v * the start offset in {@link #b b} of the value to be read * (not including the value name constant pool index). @@ -1828,8 +2012,7 @@ private int readAnnotationValue(int v, final char[] buf, final String name, v += 2; break; case 'B': // pointer to CONSTANT_Byte - av.visit(name, - new Byte((byte) readInt(items[readUnsignedShort(v)]))); + av.visit(name, (byte) readInt(items[readUnsignedShort(v)])); v += 2; break; case 'Z': // pointer to CONSTANT_Boolean @@ -1839,13 +2022,11 @@ private int readAnnotationValue(int v, final char[] buf, final String name, v += 2; break; case 'S': // pointer to CONSTANT_Short - av.visit(name, new Short( - (short) readInt(items[readUnsignedShort(v)]))); + av.visit(name, (short) readInt(items[readUnsignedShort(v)])); v += 2; break; case 'C': // pointer to CONSTANT_Char - av.visit(name, new Character( - (char) readInt(items[readUnsignedShort(v)]))); + av.visit(name, (char) readInt(items[readUnsignedShort(v)])); v += 2; break; case 's': // pointer to CONSTANT_Utf8 @@ -1956,7 +2137,7 @@ private int readAnnotationValue(int v, final char[] buf, final String name, /** * Computes the implicit frame of the method currently being parsed (as * defined in the given {@link Context}) and stores it in the given context. - * + * * @param frame * information about the class being parsed. */ @@ -2019,7 +2200,7 @@ private void getImplicitFrame(final Context frame) { /** * Reads a stack map frame and stores the result in the given * {@link Context} object. - * + * * @param stackMap * the start offset of a stack map frame in the class file. * @param zip @@ -2098,14 +2279,14 @@ private int readFrame(int stackMap, boolean zip, boolean unzip, } } frame.offset += delta + 1; - readLabel(frame.offset, labels); + createLabel(frame.offset, labels); return stackMap; } /** * Reads a stack map frame type and stores it at the given index in the * given array. - * + * * @param frame * the array where the parsed type must be stored. * @param index @@ -2151,7 +2332,7 @@ private int readFrameType(final Object[] frame, final int index, int v, v += 2; break; default: // Uninitialized - frame[index] = readLabel(readUnsignedShort(v), labels); + frame[index] = createLabel(readUnsignedShort(v), labels); v += 2; } return v; @@ -2161,7 +2342,7 @@ private int readFrameType(final Object[] frame, final int index, int v, * Returns the label corresponding to the given offset. The default * implementation of this method creates a label for the given offset if it * has not been already created. - * + * * @param offset * a bytecode offset in a method. * @param labels @@ -2177,9 +2358,42 @@ protected Label readLabel(int offset, Label[] labels) { return labels[offset]; } + /** + * Creates a label without the Label.DEBUG flag set, for the given offset. + * The label is created with a call to {@link #readLabel} and its + * Label.DEBUG flag is cleared. + * + * @param offset + * a bytecode offset in a method. + * @param labels + * the already created labels, indexed by their offset. + * @return a Label without the Label.DEBUG flag set. + */ + private Label createLabel(int offset, Label[] labels) { + Label label = readLabel(offset, labels); + label.status &= ~Label.DEBUG; + return label; + } + + /** + * Creates a label with the Label.DEBUG flag set, if there is no already + * existing label for the given offset (otherwise does nothing). The label + * is created with a call to {@link #readLabel}. + * + * @param offset + * a bytecode offset in a method. + * @param labels + * the already created labels, indexed by their offset. + */ + private void createDebugLabel(int offset, Label[] labels) { + if (labels[offset] == null) { + readLabel(offset, labels).status |= Label.DEBUG; + } + } + /** * Returns the start index of the attribute_info structure of this class. - * + * * @return the start index of the attribute_info structure of this class. */ private int getAttributes() { @@ -2205,7 +2419,7 @@ private int getAttributes() { /** * Reads an attribute in {@link #b b}. - * + * * @param attrs * prototypes of the attributes that must be parsed during the * visit of the class. Any attribute whose type is not equal to @@ -2253,7 +2467,7 @@ private Attribute readAttribute(final Attribute[] attrs, final String type, /** * Returns the number of constant pool items in {@link #b b}. - * + * * @return the number of constant pool items in {@link #b b}. */ public int getItemCount() { @@ -2264,7 +2478,7 @@ public int getItemCount() { * Returns the start index of the constant pool item in {@link #b b}, plus * one. This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. - * + * * @param item * the index a constant pool item. * @return the start index of the constant pool item in {@link #b b}, plus @@ -2277,7 +2491,7 @@ public int getItem(final int item) { /** * Returns the maximum length of the strings contained in the constant pool * of the class. - * + * * @return the maximum length of the strings contained in the constant pool * of the class. */ @@ -2289,7 +2503,7 @@ public int getMaxStringLength() { * Reads a byte value in {@link #b b}. This method is intended for * {@link Attribute} sub classes, and is normally not needed by class * generators or adapters. - * + * * @param index * the start index of the value to be read in {@link #b b}. * @return the read value. @@ -2302,7 +2516,7 @@ public int readByte(final int index) { * Reads an unsigned short value in {@link #b b}. This method is intended * for {@link Attribute} sub classes, and is normally not needed by class * generators or adapters. - * + * * @param index * the start index of the value to be read in {@link #b b}. * @return the read value. @@ -2316,7 +2530,7 @@ public int readUnsignedShort(final int index) { * Reads a signed short value in {@link #b b}. This method is intended * for {@link Attribute} sub classes, and is normally not needed by class * generators or adapters. - * + * * @param index * the start index of the value to be read in {@link #b b}. * @return the read value. @@ -2330,7 +2544,7 @@ public short readShort(final int index) { * Reads a signed int value in {@link #b b}. This method is intended for * {@link Attribute} sub classes, and is normally not needed by class * generators or adapters. - * + * * @param index * the start index of the value to be read in {@link #b b}. * @return the read value. @@ -2345,7 +2559,7 @@ public int readInt(final int index) { * Reads a signed long value in {@link #b b}. This method is intended for * {@link Attribute} sub classes, and is normally not needed by class * generators or adapters. - * + * * @param index * the start index of the value to be read in {@link #b b}. * @return the read value. @@ -2360,7 +2574,7 @@ public long readLong(final int index) { * Reads an UTF8 string constant pool item in {@link #b b}. This method * is intended for {@link Attribute} sub classes, and is normally not needed * by class generators or adapters. - * + * * @param index * the start index of an unsigned short value in {@link #b b}, * whose value is the index of an UTF8 constant pool item. @@ -2384,7 +2598,7 @@ public String readUTF8(int index, final char[] buf) { /** * Reads UTF8 string in {@link #b b}. - * + * * @param index * start offset of the UTF8 string to be read. * @param utfLen @@ -2431,11 +2645,25 @@ private String readUTF(int index, final int utfLen, final char[] buf) { return new String(buf, 0, strLen); } + /** + * Read a stringish constant item (CONSTANT_Class, CONSTANT_String, + * CONSTANT_MethodType, CONSTANT_Module or CONSTANT_Package + * @param index + * @param buf + * @return + */ + private String readStringish(final int index, final char[] buf) { + // computes the start index of the item in b + // and reads the CONSTANT_Utf8 item designated by + // the first two bytes of this item + return readUTF8(items[readUnsignedShort(index)], buf); + } + /** * Reads a class constant pool item in {@link #b b}. This method is * intended for {@link Attribute} sub classes, and is normally not needed by * class generators or adapters. - * + * * @param index * the start index of an unsigned short value in {@link #b b}, * whose value is the index of a class constant pool item. @@ -2445,17 +2673,48 @@ private String readUTF(int index, final int utfLen, final char[] buf) { * @return the String corresponding to the specified class item. */ public String readClass(final int index, final char[] buf) { - // computes the start index of the CONSTANT_Class item in b - // and reads the CONSTANT_Utf8 item designated by - // the first two bytes of this CONSTANT_Class item - return readUTF8(items[readUnsignedShort(index)], buf); + return readStringish(index, buf); + } + + /** + * Reads a module constant pool item in {@link #b b}. This method is + * intended for {@link Attribute} sub classes, and is normally not needed by + * class generators or adapters. + * + * @param index + * the start index of an unsigned short value in {@link #b b}, + * whose value is the index of a module constant pool item. + * @param buf + * buffer to be used to read the item. This buffer must be + * sufficiently large. It is not automatically resized. + * @return the String corresponding to the specified module item. + */ + public String readModule(final int index, final char[] buf) { + return readStringish(index, buf); + } + + /** + * Reads a module constant pool item in {@link #b b}. This method is + * intended for {@link Attribute} sub classes, and is normally not needed by + * class generators or adapters. + * + * @param index + * the start index of an unsigned short value in {@link #b b}, + * whose value is the index of a module constant pool item. + * @param buf + * buffer to be used to read the item. This buffer must be + * sufficiently large. It is not automatically resized. + * @return the String corresponding to the specified module item. + */ + public String readPackage(final int index, final char[] buf) { + return readStringish(index, buf); } /** * Reads a numeric or string constant pool item in {@link #b b}. This * method is intended for {@link Attribute} sub classes, and is normally not * needed by class generators or adapters. - * + * * @param item * the index of a constant pool item. * @param buf @@ -2469,13 +2728,13 @@ public Object readConst(final int item, final char[] buf) { int index = items[item]; switch (b[index - 1]) { case ClassWriter.INT: - return new Integer(readInt(index)); + return readInt(index); case ClassWriter.FLOAT: - return new Float(Float.intBitsToFloat(readInt(index))); + return Float.intBitsToFloat(readInt(index)); case ClassWriter.LONG: - return new Long(readLong(index)); + return readLong(index); case ClassWriter.DOUBLE: - return new Double(Double.longBitsToDouble(readLong(index))); + return Double.longBitsToDouble(readLong(index)); case ClassWriter.CLASS: return Type.getObjectType(readUTF8(index, buf)); case ClassWriter.STR: @@ -2486,11 +2745,12 @@ public Object readConst(final int item, final char[] buf) { int tag = readByte(index); int[] items = this.items; int cpIndex = items[readUnsignedShort(index + 1)]; + boolean itf = b[cpIndex - 1] == ClassWriter.IMETH; String owner = readClass(cpIndex, buf); cpIndex = items[readUnsignedShort(cpIndex + 2)]; String name = readUTF8(cpIndex, buf); String desc = readUTF8(cpIndex + 2, buf); - return new Handle(tag, owner, name, desc); + return new Handle(tag, owner, name, desc, itf); } } } diff --git a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassVisitor.java b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassVisitor.java index 4c340ae24..b467e3385 100644 --- a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassVisitor.java +++ b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassVisitor.java @@ -32,18 +32,18 @@ /** * A visitor to visit a Java class. The methods of this class must be called in * the following order: visit [ visitSource ] [ - * visitOuterClass ] ( visitAnnotation | + * visitModule ][ visitOuterClass ] ( visitAnnotation | * visitTypeAnnotation | visitAttribute )* ( * visitInnerClass | visitField | visitMethod )* * visitEnd. - * + * * @author Eric Bruneton */ public abstract class ClassVisitor { /** * The ASM API version implemented by this visitor. The value of this field - * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + * must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. */ protected final int api; @@ -55,10 +55,10 @@ public abstract class ClassVisitor { /** * Constructs a new {@link ClassVisitor}. - * + * * @param api * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. */ public ClassVisitor(final int api) { this(api, null); @@ -66,16 +66,16 @@ public ClassVisitor(final int api) { /** * Constructs a new {@link ClassVisitor}. - * + * * @param api * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. * @param cv * the class visitor to which this visitor must delegate method * calls. May be null. */ public ClassVisitor(final int api, final ClassVisitor cv) { - if (api != Opcodes.ASM4 && api != Opcodes.ASM5) { + if (api < Opcodes.ASM4 || api > Opcodes.ASM6) { throw new IllegalArgumentException(); } this.api = api; @@ -84,7 +84,7 @@ public ClassVisitor(final int api, final ClassVisitor cv) { /** * Visits the header of the class. - * + * * @param version * the class version. * @param access @@ -116,7 +116,7 @@ public void visit(int version, int access, String name, String signature, /** * Visits the source of the class. - * + * * @param source * the name of the source file from which the class was compiled. * May be null. @@ -130,11 +130,33 @@ public void visitSource(String source, String debug) { cv.visitSource(source, debug); } } + + /** + * Visit the module corresponding to the class. + * @param name + * module name + * @param access + * module flags, among {@code ACC_OPEN}, {@code ACC_SYNTHETIC} + * and {@code ACC_MANDATED}. + * @param version + * module version or null. + * @return a visitor to visit the module values, or null if + * this visitor is not interested in visiting this module. + */ + public ModuleVisitor visitModule(String name, int access, String version) { + if (api < Opcodes.ASM6) { + throw new RuntimeException(); + } + if (cv != null) { + return cv.visitModule(name, access, version); + } + return null; + } /** * Visits the enclosing class of the class. This method must be called only * if the class has an enclosing class. - * + * * @param owner * internal name of the enclosing class of the class. * @param name @@ -154,7 +176,7 @@ public void visitOuterClass(String owner, String name, String desc) { /** * Visits an annotation of the class. - * + * * @param desc * the class descriptor of the annotation class. * @param visible @@ -171,7 +193,7 @@ public AnnotationVisitor visitAnnotation(String desc, boolean visible) { /** * Visits an annotation on a type in the class signature. - * + * * @param typeRef * a reference to the annotated type. The sort of this type * reference must be {@link TypeReference#CLASS_TYPE_PARAMETER @@ -204,7 +226,7 @@ public AnnotationVisitor visitTypeAnnotation(int typeRef, /** * Visits a non standard attribute of the class. - * + * * @param attr * an attribute. */ @@ -217,7 +239,7 @@ public void visitAttribute(Attribute attr) { /** * Visits information about an inner class. This inner class is not * necessarily a member of the class being visited. - * + * * @param name * the internal name of an inner class (see * {@link Type#getInternalName() getInternalName}). @@ -241,7 +263,7 @@ public void visitInnerClass(String name, String outerName, /** * Visits a field of the class. - * + * * @param access * the field's access flags (see {@link Opcodes}). This parameter * also indicates if the field is synthetic and/or deprecated. @@ -278,7 +300,7 @@ public FieldVisitor visitField(int access, String name, String desc, * Visits a method of the class. This method must return a new * {@link MethodVisitor} instance (or null) each time it is called, * i.e., it should not return a previously returned visitor. - * + * * @param access * the method's access flags (see {@link Opcodes}). This * parameter also indicates if the method is synthetic and/or diff --git a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassWriter.java b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassWriter.java index db426108a..72ec27cd4 100644 --- a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassWriter.java +++ b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassWriter.java @@ -35,7 +35,7 @@ * file format. It can be used alone, to generate a Java class "from scratch", * or with one or more {@link ClassReader ClassReader} and adapter class visitor * to generate a modified class from one or more existing Java classes. - * + * * @author Eric Bruneton */ public class ClassWriter extends ClassVisitor { @@ -47,7 +47,7 @@ public class ClassWriter extends ClassVisitor { * {@link MethodVisitor} returned by the {@link #visitMethod visitMethod} * method will be ignored, and computed automatically from the signature and * the bytecode of each method. - * + * * @see #ClassWriter(int) */ public static final int COMPUTE_MAXS = 1; @@ -58,9 +58,9 @@ public class ClassWriter extends ClassVisitor { * {@link MethodVisitor#visitFrame} method are ignored, and the stack map * frames are recomputed from the methods bytecode. The arguments of the * {@link MethodVisitor#visitMaxs visitMaxs} method are also ignored and - * recomputed from the bytecode. In other words, computeFrames implies - * computeMaxs. - * + * recomputed from the bytecode. In other words, COMPUTE_FRAMES implies + * COMPUTE_MAXS. + * * @see #ClassWriter(int) */ public static final int COMPUTE_FRAMES = 2; @@ -167,6 +167,27 @@ public class ClassWriter extends ClassVisitor { */ static final int WIDE_INSN = 17; + /** + * The type of the ASM pseudo instructions with an unsigned 2 bytes offset + * label (see Label#resolve). + */ + static final int ASM_LABEL_INSN = 18; + + /** + * The type of the ASM pseudo instructions with a 4 bytes offset label. + */ + static final int ASM_LABELW_INSN = 19; + + /** + * Represents a frame inserted between already existing frames. This kind of + * frame can only be used if the frame content can be computed from the + * previous existing frame and from the instructions between this existing + * frame and the inserted one, without any knowledge of the type hierarchy. + * This kind of frame is only used when an unconditional jump is inserted in + * a method while expanding an ASM pseudo instruction (see ClassReader). + */ + static final int F_INSERT = 256; + /** * The instruction types of all JVM opcodes. */ @@ -242,10 +263,20 @@ public class ClassWriter extends ClassVisitor { */ static final int INDY = 18; + /** + * The type of CONSTANT_Module constant pool items. + */ + static final int MODULE = 19; + + /** + * The type of CONSTANT_Package constant pool items. + */ + static final int PACKAGE = 20; + /** * The base value for all CONSTANT_MethodHandle constant pool items. * Internally, ASM store the 9 variations of CONSTANT_MethodHandle into 9 - * different items. + * different items (from 21 to 29). */ static final int HANDLE_BASE = 20; @@ -394,6 +425,11 @@ public class ClassWriter extends ClassVisitor { */ private ByteVector sourceDebug; + /** + * The module attribute of this class. + */ + private ModuleWriter moduleWriter; + /** * The constant pool item that contains the name of the enclosing class of * this class. @@ -484,25 +520,19 @@ public class ClassWriter extends ClassVisitor { MethodWriter lastMethod; /** - * true if the maximum stack size and number of local variables - * must be automatically computed. - */ - private boolean computeMaxs; - - /** - * true if the stack map frames must be recomputed from scratch. + * Indicates what must be automatically computed. + * + * @see MethodWriter#compute */ - private boolean computeFrames; + private int compute; /** - * true if the stack map tables of this class are invalid. The - * {@link MethodWriter#resizeInstructions} method cannot transform existing - * stack map tables, and so produces potentially invalid classes when it is - * executed. In this case the class is reread and rewritten with the - * {@link #COMPUTE_FRAMES} option (the resizeInstructions method can resize - * stack map tables when this option is used). + * true if some methods have wide forward jumps using ASM pseudo + * instructions, which need to be expanded into sequences of standard + * bytecode instructions. In this case the class is re-read and re-written + * with a ClassReader -> ClassWriter chain to perform this transformation. */ - boolean invalidFrames; + boolean hasAsmInsns; // ------------------------------------------------------------------------ // Static initializer @@ -513,11 +543,11 @@ public class ClassWriter extends ClassVisitor { */ static { int i; - byte[] b = new byte[220]; + byte[] b = new byte[221]; String s = "AAAAAAAAAAAAAAAABCLMMDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD" + "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAANAAAAAAAAAAAAAAAAAAAAJJJJJJJJJJJJJJJJDOPAA" - + "AAAAGGGGGGGHIFBFAAFFAARQJJKKJJJJJJJJJJJJJJJJJJ"; + + "AAAAGGGGGGGHIFBFAAFFAARQJJKKSSSSSSSSSSSSSSSSSST"; for (i = 0; i < b.length; ++i) { b[i] = (byte) (s.charAt(i) - 'A'); } @@ -571,8 +601,9 @@ public class ClassWriter extends ClassVisitor { // // temporary opcodes used internally by ASM - see Label and // MethodWriter // for (i = 202; i < 220; ++i) { - // b[i] = LABEL_INSN; + // b[i] = ASM_LABEL_INSN; // } + // b[220] = ASM_LABELW_INSN; // // // LDC(_W) instructions // b[Constants.LDC] = LDC_INSN; @@ -598,14 +629,14 @@ public class ClassWriter extends ClassVisitor { /** * Constructs a new {@link ClassWriter} object. - * + * * @param flags * option flags that can be used to modify the default behavior * of this class. See {@link #COMPUTE_MAXS}, * {@link #COMPUTE_FRAMES}. */ public ClassWriter(final int flags) { - super(Opcodes.ASM5); + super(Opcodes.ASM6); index = 1; pool = new ByteVector(); items = new Item[256]; @@ -614,15 +645,16 @@ public ClassWriter(final int flags) { key2 = new Item(); key3 = new Item(); key4 = new Item(); - this.computeMaxs = (flags & COMPUTE_MAXS) != 0; - this.computeFrames = (flags & COMPUTE_FRAMES) != 0; + this.compute = (flags & COMPUTE_FRAMES) != 0 ? MethodWriter.FRAMES + : ((flags & COMPUTE_MAXS) != 0 ? MethodWriter.MAXS + : MethodWriter.NOTHING); } /** * Constructs a new {@link ClassWriter} object and enables optimizations for * "mostly add" bytecode transformations. These optimizations are the * following: - * + * *
    *
  • The constant pool from the original class is copied as is in the new * class, which saves time. New constant pool entries will be added at the @@ -636,7 +668,7 @@ public ClassWriter(final int flags) { * a {@link ClassWriter} (and not from any other {@link ClassVisitor} * instance).
  • *
- * + * * @param classReader * the {@link ClassReader} used to read the original class. It * will be used to copy the entire constant pool from the @@ -645,9 +677,9 @@ public ClassWriter(final int flags) { * @param flags * option flags that can be used to modify the default behavior * of this class. These option flags do not affect methods - * that are copied as is in the new class. This means that the - * maximum stack size nor the stack frames will be computed for - * these methods. See {@link #COMPUTE_MAXS}, + * that are copied as is in the new class. This means that + * neither the maximum stack size nor the stack frames will be + * computed for these methods
. See {@link #COMPUTE_MAXS}, * {@link #COMPUTE_FRAMES}. */ public ClassWriter(final ClassReader classReader, final int flags) { @@ -668,7 +700,7 @@ public final void visit(final int version, final int access, this.access = access; this.name = newClass(name); thisName = name; - if (ClassReader.SIGNATURES && signature != null) { + if (signature != null) { this.signature = newUTF8(signature); } this.superName = superName == null ? 0 : newClass(superName); @@ -692,6 +724,14 @@ public final void visitSource(final String file, final String debug) { } } + @Override + public final ModuleVisitor visitModule(final String name, + final int access, final String version) { + return moduleWriter = new ModuleWriter(this, + newModule(name), access, + version == null ? 0 : newUTF8(version)); + } + @Override public final void visitOuterClass(final String owner, final String name, final String desc) { @@ -704,9 +744,6 @@ public final void visitOuterClass(final String owner, final String name, @Override public final AnnotationVisitor visitAnnotation(final String desc, final boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } ByteVector bv = new ByteVector(); // write type, and reserve space for values count bv.putShort(newUTF8(desc)).putShort(0); @@ -724,9 +761,6 @@ public final AnnotationVisitor visitAnnotation(final String desc, @Override public final AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, final String desc, final boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } ByteVector bv = new ByteVector(); // write target_type and target_info AnnotationWriter.putTarget(typeRef, typePath, bv); @@ -766,7 +800,7 @@ public final void visitInnerClass(final String name, // and equality tests). If so we store the index of this inner class // entry (plus one) in intVal. This hack allows duplicate detection in // O(1) time. - Item nameItem = newClassItem(name); + Item nameItem = newStringishItem(CLASS, name); if (nameItem.intVal == 0) { ++innerClassesCount; innerClasses.putShort(nameItem.index); @@ -791,7 +825,7 @@ public final FieldVisitor visitField(final int access, final String name, public final MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) { return new MethodWriter(this, access, name, desc, signature, - exceptions, computeMaxs, computeFrames); + exceptions, compute); } @Override @@ -804,7 +838,7 @@ public final void visitEnd() { /** * Returns the bytecode of the class that was build with this class writer. - * + * * @return the bytecode of the class that was build with this class writer. */ public byte[] toByteArray() { @@ -835,7 +869,7 @@ public byte[] toByteArray() { size += 8 + bootstrapMethods.length; newUTF8("BootstrapMethods"); } - if (ClassReader.SIGNATURES && signature != 0) { + if (signature != 0) { ++attributeCount; size += 8; newUTF8("Signature"); @@ -873,26 +907,31 @@ public byte[] toByteArray() { size += 8 + innerClasses.length; newUTF8("InnerClasses"); } - if (ClassReader.ANNOTATIONS && anns != null) { + if (anns != null) { ++attributeCount; size += 8 + anns.getSize(); newUTF8("RuntimeVisibleAnnotations"); } - if (ClassReader.ANNOTATIONS && ianns != null) { + if (ianns != null) { ++attributeCount; size += 8 + ianns.getSize(); newUTF8("RuntimeInvisibleAnnotations"); } - if (ClassReader.ANNOTATIONS && tanns != null) { + if (tanns != null) { ++attributeCount; size += 8 + tanns.getSize(); newUTF8("RuntimeVisibleTypeAnnotations"); } - if (ClassReader.ANNOTATIONS && itanns != null) { + if (itanns != null) { ++attributeCount; size += 8 + itanns.getSize(); newUTF8("RuntimeInvisibleTypeAnnotations"); } + if (moduleWriter != null) { + attributeCount += 1 + moduleWriter.attributeCount; + size += 6 + moduleWriter.size + moduleWriter.attributesSize; + newUTF8("Module"); + } if (attrs != null) { attributeCount += attrs.getCount(); size += attrs.getSize(this, null, 0, -1, -1); @@ -929,7 +968,7 @@ public byte[] toByteArray() { bootstrapMethodsCount); out.putByteArray(bootstrapMethods.data, 0, bootstrapMethods.length); } - if (ClassReader.SIGNATURES && signature != 0) { + if (signature != 0) { out.putShort(newUTF8("Signature")).putInt(2).putShort(signature); } if (sourceFile != 0) { @@ -940,6 +979,11 @@ public byte[] toByteArray() { out.putShort(newUTF8("SourceDebugExtension")).putInt(len); out.putByteArray(sourceDebug.data, 0, len); } + if (moduleWriter != null) { + out.putShort(newUTF8("Module")); + moduleWriter.put(out); + moduleWriter.putAttributes(out); + } if (enclosingMethodOwner != 0) { out.putShort(newUTF8("EnclosingMethod")).putInt(4); out.putShort(enclosingMethodOwner).putShort(enclosingMethod); @@ -958,41 +1002,46 @@ public byte[] toByteArray() { out.putInt(innerClasses.length + 2).putShort(innerClassesCount); out.putByteArray(innerClasses.data, 0, innerClasses.length); } - if (ClassReader.ANNOTATIONS && anns != null) { + if (anns != null) { out.putShort(newUTF8("RuntimeVisibleAnnotations")); anns.put(out); } - if (ClassReader.ANNOTATIONS && ianns != null) { + if (ianns != null) { out.putShort(newUTF8("RuntimeInvisibleAnnotations")); ianns.put(out); } - if (ClassReader.ANNOTATIONS && tanns != null) { + if (tanns != null) { out.putShort(newUTF8("RuntimeVisibleTypeAnnotations")); tanns.put(out); } - if (ClassReader.ANNOTATIONS && itanns != null) { + if (itanns != null) { out.putShort(newUTF8("RuntimeInvisibleTypeAnnotations")); itanns.put(out); } if (attrs != null) { attrs.put(this, null, 0, -1, -1, out); } - if (invalidFrames) { + if (hasAsmInsns) { + boolean hasFrames = false; + mb = firstMethod; + while (mb != null) { + hasFrames |= mb.frameCount > 0; + mb = (MethodWriter) mb.mv; + } anns = null; ianns = null; attrs = null; - innerClassesCount = 0; - innerClasses = null; - bootstrapMethodsCount = 0; - bootstrapMethods = null; + moduleWriter = null; firstField = null; lastField = null; firstMethod = null; lastMethod = null; - computeMaxs = false; - computeFrames = true; - invalidFrames = false; - new ClassReader(out.data).accept(this, ClassReader.SKIP_FRAMES); + compute = + hasFrames ? MethodWriter.INSERTED_FRAMES : MethodWriter.NOTHING; + hasAsmInsns = false; + new ClassReader(out.data).accept(this, + (hasFrames ? ClassReader.EXPAND_FRAMES : 0) + | ClassReader.EXPAND_ASM_INSNS); return toByteArray(); } return out.data; @@ -1005,7 +1054,7 @@ public byte[] toByteArray() { /** * Adds a number or string constant to the constant pool of the class being * build. Does nothing if the constant pool already contains a similar item. - * + * * @param cst * the value of the constant to be added to the constant pool. * This parameter must be an {@link Integer}, a {@link Float}, a @@ -1039,20 +1088,20 @@ Item newConstItem(final Object cst) { double val = ((Double) cst).doubleValue(); return newDouble(val); } else if (cst instanceof String) { - return newString((String) cst); + return newStringishItem(STR, (String) cst); } else if (cst instanceof Type) { Type t = (Type) cst; int s = t.getSort(); if (s == Type.OBJECT) { - return newClassItem(t.getInternalName()); + return newStringishItem(CLASS, t.getInternalName()); } else if (s == Type.METHOD) { - return newMethodTypeItem(t.getDescriptor()); + return newStringishItem(MTYPE, t.getDescriptor()); } else { // s == primitive type or array - return newClassItem(t.getDescriptor()); + return newStringishItem(CLASS, t.getDescriptor()); } } else if (cst instanceof Handle) { Handle h = (Handle) cst; - return newHandleItem(h.tag, h.owner, h.name, h.desc); + return newHandleItem(h.tag, h.owner, h.name, h.desc, h.itf); } else { throw new IllegalArgumentException("value " + cst); } @@ -1063,7 +1112,7 @@ Item newConstItem(final Object cst) { * build. Does nothing if the constant pool already contains a similar item. * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. - * + * * @param cst * the value of the constant to be added to the constant pool. * This parameter must be an {@link Integer}, a {@link Float}, a @@ -1080,7 +1129,7 @@ public int newConst(final Object cst) { * nothing if the constant pool already contains a similar item. This * method is intended for {@link Attribute} sub classes, and is normally not * needed by class generators or adapters. - * + * * @param value * the String value. * @return the index of a new or already existing UTF8 item. @@ -1097,20 +1146,21 @@ public int newUTF8(final String value) { } /** - * Adds a class reference to the constant pool of the class being build. + * Adds a string reference, a class reference, a method type, a module + * or a package to the constant pool of the class being build. * Does nothing if the constant pool already contains a similar item. - * This method is intended for {@link Attribute} sub classes, and is - * normally not needed by class generators or adapters. - * + * + * @param type + * a type among STR, CLASS, MTYPE, MODULE or PACKAGE * @param value - * the internal name of the class. - * @return a new or already existing class reference item. + * string value of the reference. + * @return a new or already existing reference item. */ - Item newClassItem(final String value) { - key2.set(CLASS, value, null, null); + Item newStringishItem(final int type, final String value) { + key2.set(type, value, null, null); Item result = get(key2); if (result == null) { - pool.put12(CLASS, newUTF8(value)); + pool.put12(type, newUTF8(value)); result = new Item(index++, key2); put(result); } @@ -1122,13 +1172,13 @@ Item newClassItem(final String value) { * Does nothing if the constant pool already contains a similar item. * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. - * + * * @param value * the internal name of the class. * @return the index of a new or already existing class reference item. */ public int newClass(final String value) { - return newClassItem(value).index; + return newStringishItem(CLASS, value).index; } /** @@ -1136,35 +1186,44 @@ public int newClass(final String value) { * build. Does nothing if the constant pool already contains a similar item. * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. - * + * * @param methodDesc * method descriptor of the method type. - * @return a new or already existing method type reference item. + * @return the index of a new or already existing method type reference + * item. */ - Item newMethodTypeItem(final String methodDesc) { - key2.set(MTYPE, methodDesc, null, null); - Item result = get(key2); - if (result == null) { - pool.put12(MTYPE, newUTF8(methodDesc)); - result = new Item(index++, key2); - put(result); - } - return result; + public int newMethodType(final String methodDesc) { + return newStringishItem(MTYPE, methodDesc).index; } - + /** - * Adds a method type reference to the constant pool of the class being + * Adds a module reference to the constant pool of the class being * build. Does nothing if the constant pool already contains a similar item. * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. - * - * @param methodDesc - * method descriptor of the method type. - * @return the index of a new or already existing method type reference + * + * @param moduleName + * name of the module. + * @return the index of a new or already existing module reference * item. */ - public int newMethodType(final String methodDesc) { - return newMethodTypeItem(methodDesc).index; + public int newModule(final String moduleName) { + return newStringishItem(MODULE, moduleName).index; + } + + /** + * Adds a package reference to the constant pool of the class being + * build. Does nothing if the constant pool already contains a similar item. + * This method is intended for {@link Attribute} sub classes, and is + * normally not needed by class generators or adapters. + * + * @param packageName + * name of the package in its internal form. + * @return the index of a new or already existing module reference + * item. + */ + public int newPackage(final String packageName) { + return newStringishItem(PACKAGE, packageName).index; } /** @@ -1172,7 +1231,7 @@ public int newMethodType(final String methodDesc) { * if the constant pool already contains a similar item. This method is * intended for {@link Attribute} sub classes, and is normally not needed by * class generators or adapters. - * + * * @param tag * the kind of this handle. Must be {@link Opcodes#H_GETFIELD}, * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, @@ -1187,10 +1246,12 @@ public int newMethodType(final String methodDesc) { * the name of the field or method. * @param desc * the descriptor of the field or method. + * @param itf + * true if the owner is an interface. * @return a new or an already existing method type reference item. */ Item newHandleItem(final int tag, final String owner, final String name, - final String desc) { + final String desc, final boolean itf) { key4.set(HANDLE_BASE + tag, owner, name, desc); Item result = get(key4); if (result == null) { @@ -1199,8 +1260,7 @@ Item newHandleItem(final int tag, final String owner, final String name, } else { put112(HANDLE, tag, - newMethod(owner, name, desc, - tag == Opcodes.H_INVOKEINTERFACE)); + newMethod(owner, name, desc, itf)); } result = new Item(index++, key4); put(result); @@ -1213,7 +1273,7 @@ Item newHandleItem(final int tag, final String owner, final String name, * if the constant pool already contains a similar item. This method is * intended for {@link Attribute} sub classes, and is normally not needed by * class generators or adapters. - * + * * @param tag * the kind of this handle. Must be {@link Opcodes#H_GETFIELD}, * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, @@ -1230,18 +1290,52 @@ Item newHandleItem(final int tag, final String owner, final String name, * the descriptor of the field or method. * @return the index of a new or already existing method type reference * item. + * + * @deprecated this method is superseded by + * {@link #newHandle(int, String, String, String, boolean)}. */ + @Deprecated public int newHandle(final int tag, final String owner, final String name, final String desc) { - return newHandleItem(tag, owner, name, desc).index; + return newHandle(tag, owner, name, desc, tag == Opcodes.H_INVOKEINTERFACE); } + /** + * Adds a handle to the constant pool of the class being build. Does nothing + * if the constant pool already contains a similar item. This method is + * intended for {@link Attribute} sub classes, and is normally not needed by + * class generators or adapters. + * + * @param tag + * the kind of this handle. Must be {@link Opcodes#H_GETFIELD}, + * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, + * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL}, + * {@link Opcodes#H_INVOKESTATIC}, + * {@link Opcodes#H_INVOKESPECIAL}, + * {@link Opcodes#H_NEWINVOKESPECIAL} or + * {@link Opcodes#H_INVOKEINTERFACE}. + * @param owner + * the internal name of the field or method owner class. + * @param name + * the name of the field or method. + * @param desc + * the descriptor of the field or method. + * @param itf + * true if the owner is an interface. + * @return the index of a new or already existing method type reference + * item. + */ + public int newHandle(final int tag, final String owner, final String name, + final String desc, final boolean itf) { + return newHandleItem(tag, owner, name, desc, itf).index; + } + /** * Adds an invokedynamic reference to the constant pool of the class being * build. Does nothing if the constant pool already contains a similar item. * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. - * + * * @param name * name of the invoked method. * @param desc @@ -1250,7 +1344,7 @@ public int newHandle(final int tag, final String owner, final String name, * the bootstrap method. * @param bsmArgs * the bootstrap method constant arguments. - * + * * @return a new or an already existing invokedynamic type reference item. */ Item newInvokeDynamicItem(final String name, final String desc, @@ -1265,7 +1359,7 @@ Item newInvokeDynamicItem(final String name, final String desc, int hashCode = bsm.hashCode(); bootstrapMethods.putShort(newHandle(bsm.tag, bsm.owner, bsm.name, - bsm.desc)); + bsm.desc, bsm.isInterface())); int argsLength = bsmArgs.length; bootstrapMethods.putShort(argsLength); @@ -1325,7 +1419,7 @@ Item newInvokeDynamicItem(final String name, final String desc, * build. Does nothing if the constant pool already contains a similar item. * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. - * + * * @param name * name of the invoked method. * @param desc @@ -1334,7 +1428,7 @@ Item newInvokeDynamicItem(final String name, final String desc, * the bootstrap method. * @param bsmArgs * the bootstrap method constant arguments. - * + * * @return the index of a new or already existing invokedynamic reference * item. */ @@ -1346,7 +1440,7 @@ public int newInvokeDynamic(final String name, final String desc, /** * Adds a field reference to the constant pool of the class being build. * Does nothing if the constant pool already contains a similar item. - * + * * @param owner * the internal name of the field's owner class. * @param name @@ -1371,7 +1465,7 @@ Item newFieldItem(final String owner, final String name, final String desc) { * Does nothing if the constant pool already contains a similar item. * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. - * + * * @param owner * the internal name of the field's owner class. * @param name @@ -1387,7 +1481,7 @@ public int newField(final String owner, final String name, final String desc) { /** * Adds a method reference to the constant pool of the class being build. * Does nothing if the constant pool already contains a similar item. - * + * * @param owner * the internal name of the method's owner class. * @param name @@ -1416,7 +1510,7 @@ Item newMethodItem(final String owner, final String name, * Does nothing if the constant pool already contains a similar item. * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. - * + * * @param owner * the internal name of the method's owner class. * @param name @@ -1435,7 +1529,7 @@ public int newMethod(final String owner, final String name, /** * Adds an integer to the constant pool of the class being build. Does * nothing if the constant pool already contains a similar item. - * + * * @param value * the int value. * @return a new or already existing int item. @@ -1454,7 +1548,7 @@ Item newInteger(final int value) { /** * Adds a float to the constant pool of the class being build. Does nothing * if the constant pool already contains a similar item. - * + * * @param value * the float value. * @return a new or already existing float item. @@ -1473,7 +1567,7 @@ Item newFloat(final float value) { /** * Adds a long to the constant pool of the class being build. Does nothing * if the constant pool already contains a similar item. - * + * * @param value * the long value. * @return a new or already existing long item. @@ -1493,7 +1587,7 @@ Item newLong(final long value) { /** * Adds a double to the constant pool of the class being build. Does nothing * if the constant pool already contains a similar item. - * + * * @param value * the double value. * @return a new or already existing double item. @@ -1510,31 +1604,12 @@ Item newDouble(final double value) { return result; } - /** - * Adds a string to the constant pool of the class being build. Does nothing - * if the constant pool already contains a similar item. - * - * @param value - * the String value. - * @return a new or already existing string item. - */ - private Item newString(final String value) { - key2.set(STR, value, null, null); - Item result = get(key2); - if (result == null) { - pool.put12(STR, newUTF8(value)); - result = new Item(index++, key2); - put(result); - } - return result; - } - /** * Adds a name and type to the constant pool of the class being build. Does * nothing if the constant pool already contains a similar item. This * method is intended for {@link Attribute} sub classes, and is normally not * needed by class generators or adapters. - * + * * @param name * a name. * @param desc @@ -1548,7 +1623,7 @@ public int newNameType(final String name, final String desc) { /** * Adds a name and type to the constant pool of the class being build. Does * nothing if the constant pool already contains a similar item. - * + * * @param name * a name. * @param desc @@ -1569,7 +1644,7 @@ Item newNameTypeItem(final String name, final String desc) { /** * Adds the given internal name to {@link #typeTable} and returns its index. * Does nothing if the type table already contains this internal name. - * + * * @param type * the internal name to be added to the type table. * @return the index of this internal name in the type table. @@ -1587,7 +1662,7 @@ int addType(final String type) { * Adds the given "uninitialized" type to {@link #typeTable} and returns its * index. This method is used for UNINITIALIZED types, made of an internal * name and a bytecode offset. - * + * * @param type * the internal name to be added to the type table. * @param offset @@ -1609,7 +1684,7 @@ int addUninitializedType(final String type, final int offset) { /** * Adds the given Item to {@link #typeTable}. - * + * * @param item * the value to be added to the type table. * @return the added Item, which a new Item instance with the same value as @@ -1636,7 +1711,7 @@ private Item addType(final Item item) { * method calls {@link #getCommonSuperClass} and caches the result in the * {@link #items} hash table to speedup future calls with the same * parameters. - * + * * @param type1 * index of an internal name in {@link #typeTable}. * @param type2 @@ -1666,7 +1741,7 @@ int getMergedType(final int type1, final int type2) { * without actually loading any class, or to take into account the class * that is currently being generated by this ClassWriter, which can of * course not be loaded since it is under construction. - * + * * @param type1 * the internal name of a class. * @param type2 @@ -1702,7 +1777,7 @@ protected String getCommonSuperClass(final String type1, final String type2) { /** * Returns the constant pool's hash table item which is equal to the given * item. - * + * * @param key * a constant pool item. * @return the constant pool's hash table item which is equal to the given @@ -1719,7 +1794,7 @@ private Item get(final Item key) { /** * Puts the given item in the constant pool's hash table. The hash table * must not already contains this item. - * + * * @param i * the item to be added to the constant pool's hash table. */ @@ -1748,7 +1823,7 @@ private void put(final Item i) { /** * Puts one byte and two shorts into the constant pool. - * + * * @param b * a byte. * @param s1 @@ -1762,7 +1837,7 @@ private void put122(final int b, final int s1, final int s2) { /** * Puts two bytes and one short into the constant pool. - * + * * @param b1 * a byte. * @param b2 diff --git a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Context.java b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Context.java index 3c460cc41..954ccf632 100644 --- a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Context.java +++ b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Context.java @@ -1,145 +1,145 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -package jersey.repackaged.org.objectweb.asm; - -/** - * Information about a class being parsed in a {@link ClassReader}. - * - * @author Eric Bruneton - */ -class Context { - - /** - * Prototypes of the attributes that must be parsed for this class. - */ - Attribute[] attrs; - - /** - * The {@link ClassReader} option flags for the parsing of this class. - */ - int flags; - - /** - * The buffer used to read strings. - */ - char[] buffer; - - /** - * The start index of each bootstrap method. - */ - int[] bootstrapMethods; - - /** - * The access flags of the method currently being parsed. - */ - int access; - - /** - * The name of the method currently being parsed. - */ - String name; - - /** - * The descriptor of the method currently being parsed. - */ - String desc; - - /** - * The label objects, indexed by bytecode offset, of the method currently - * being parsed (only bytecode offsets for which a label is needed have a - * non null associated Label object). - */ - Label[] labels; - - /** - * The target of the type annotation currently being parsed. - */ - int typeRef; - - /** - * The path of the type annotation currently being parsed. - */ - TypePath typePath; - - /** - * The offset of the latest stack map frame that has been parsed. - */ - int offset; - - /** - * The labels corresponding to the start of the local variable ranges in the - * local variable type annotation currently being parsed. - */ - Label[] start; - - /** - * The labels corresponding to the end of the local variable ranges in the - * local variable type annotation currently being parsed. - */ - Label[] end; - - /** - * The local variable indices for each local variable range in the local - * variable type annotation currently being parsed. - */ - int[] index; - - /** - * The encoding of the latest stack map frame that has been parsed. - */ - int mode; - - /** - * The number of locals in the latest stack map frame that has been parsed. - */ - int localCount; - - /** - * The number locals in the latest stack map frame that has been parsed, - * minus the number of locals in the previous frame. - */ - int localDiff; - - /** - * The local values of the latest stack map frame that has been parsed. - */ - Object[] local; - - /** - * The stack size of the latest stack map frame that has been parsed. - */ - int stackCount; - - /** - * The stack values of the latest stack map frame that has been parsed. - */ - Object[] stack; -} +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +package jersey.repackaged.org.objectweb.asm; + +/** + * Information about a class being parsed in a {@link ClassReader}. + * + * @author Eric Bruneton + */ +class Context { + + /** + * Prototypes of the attributes that must be parsed for this class. + */ + Attribute[] attrs; + + /** + * The {@link ClassReader} option flags for the parsing of this class. + */ + int flags; + + /** + * The buffer used to read strings. + */ + char[] buffer; + + /** + * The start index of each bootstrap method. + */ + int[] bootstrapMethods; + + /** + * The access flags of the method currently being parsed. + */ + int access; + + /** + * The name of the method currently being parsed. + */ + String name; + + /** + * The descriptor of the method currently being parsed. + */ + String desc; + + /** + * The label objects, indexed by bytecode offset, of the method currently + * being parsed (only bytecode offsets for which a label is needed have a + * non null associated Label object). + */ + Label[] labels; + + /** + * The target of the type annotation currently being parsed. + */ + int typeRef; + + /** + * The path of the type annotation currently being parsed. + */ + TypePath typePath; + + /** + * The offset of the latest stack map frame that has been parsed. + */ + int offset; + + /** + * The labels corresponding to the start of the local variable ranges in the + * local variable type annotation currently being parsed. + */ + Label[] start; + + /** + * The labels corresponding to the end of the local variable ranges in the + * local variable type annotation currently being parsed. + */ + Label[] end; + + /** + * The local variable indices for each local variable range in the local + * variable type annotation currently being parsed. + */ + int[] index; + + /** + * The encoding of the latest stack map frame that has been parsed. + */ + int mode; + + /** + * The number of locals in the latest stack map frame that has been parsed. + */ + int localCount; + + /** + * The number locals in the latest stack map frame that has been parsed, + * minus the number of locals in the previous frame. + */ + int localDiff; + + /** + * The local values of the latest stack map frame that has been parsed. + */ + Object[] local; + + /** + * The stack size of the latest stack map frame that has been parsed. + */ + int stackCount; + + /** + * The stack values of the latest stack map frame that has been parsed. + */ + Object[] stack; +} diff --git a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/CurrentFrame.java b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/CurrentFrame.java new file mode 100644 index 000000000..cc4af9642 --- /dev/null +++ b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/CurrentFrame.java @@ -0,0 +1,56 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +package jersey.repackaged.org.objectweb.asm; + +/** + * Information about the input stack map frame at the "current" instruction of a + * method. This is implemented as a Frame subclass for a "basic block" + * containing only one instruction. + * + * @author Eric Bruneton + */ +class CurrentFrame extends Frame { + + /** + * Sets this CurrentFrame to the input stack map frame of the next "current" + * instruction, i.e. the instruction just after the given one. It is assumed + * that the value of this object when this method is called is the stack map + * frame status just before the given instruction is executed. + */ + @Override + void execute(int opcode, int arg, ClassWriter cw, Item item) { + super.execute(opcode, arg, cw, item); + Frame successor = new Frame(); + merge(cw, successor, 0); + set(successor); + owner.inputStackTop = 0; + } +} diff --git a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Edge.java b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Edge.java index 24dfa2d9d..64b2cd74c 100644 --- a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Edge.java +++ b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Edge.java @@ -31,7 +31,7 @@ /** * An edge in the control flow graph of a method body. See {@link Label Label}. - * + * * @author Eric Bruneton */ class Edge { diff --git a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/FieldVisitor.java b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/FieldVisitor.java index bad6a1a9e..6ae196228 100644 --- a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/FieldVisitor.java +++ b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/FieldVisitor.java @@ -33,14 +33,14 @@ * A visitor to visit a Java field. The methods of this class must be called in * the following order: ( visitAnnotation | * visitTypeAnnotation | visitAttribute )* visitEnd. - * + * * @author Eric Bruneton */ public abstract class FieldVisitor { /** * The ASM API version implemented by this visitor. The value of this field - * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + * must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. */ protected final int api; @@ -52,10 +52,10 @@ public abstract class FieldVisitor { /** * Constructs a new {@link FieldVisitor}. - * + * * @param api * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. */ public FieldVisitor(final int api) { this(api, null); @@ -63,16 +63,16 @@ public FieldVisitor(final int api) { /** * Constructs a new {@link FieldVisitor}. - * + * * @param api * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. * @param fv * the field visitor to which this visitor must delegate method * calls. May be null. */ public FieldVisitor(final int api, final FieldVisitor fv) { - if (api != Opcodes.ASM4 && api != Opcodes.ASM5) { + if (api < Opcodes.ASM4 || api > Opcodes.ASM6) { throw new IllegalArgumentException(); } this.api = api; @@ -81,7 +81,7 @@ public FieldVisitor(final int api, final FieldVisitor fv) { /** * Visits an annotation of the field. - * + * * @param desc * the class descriptor of the annotation class. * @param visible @@ -98,7 +98,7 @@ public AnnotationVisitor visitAnnotation(String desc, boolean visible) { /** * Visits an annotation on the type of the field. - * + * * @param typeRef * a reference to the annotated type. The sort of this type * reference must be {@link TypeReference#FIELD FIELD}. See @@ -127,7 +127,7 @@ public AnnotationVisitor visitTypeAnnotation(int typeRef, /** * Visits a non standard attribute of the field. - * + * * @param attr * an attribute. */ diff --git a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/FieldWriter.java b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/FieldWriter.java index a5ec3367e..4dbfcf9a5 100644 --- a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/FieldWriter.java +++ b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/FieldWriter.java @@ -31,7 +31,7 @@ /** * An {@link FieldVisitor} that generates Java fields in bytecode form. - * + * * @author Eric Bruneton */ final class FieldWriter extends FieldVisitor { @@ -102,7 +102,7 @@ final class FieldWriter extends FieldVisitor { /** * Constructs a new {@link FieldWriter}. - * + * * @param cw * the class writer to which this field must be added. * @param access @@ -118,7 +118,7 @@ final class FieldWriter extends FieldVisitor { */ FieldWriter(final ClassWriter cw, final int access, final String name, final String desc, final String signature, final Object value) { - super(Opcodes.ASM5); + super(Opcodes.ASM6); if (cw.firstField == null) { cw.firstField = this; } else { @@ -129,7 +129,7 @@ final class FieldWriter extends FieldVisitor { this.access = access; this.name = cw.newUTF8(name); this.desc = cw.newUTF8(desc); - if (ClassReader.SIGNATURES && signature != null) { + if (signature != null) { this.signature = cw.newUTF8(signature); } if (value != null) { @@ -144,9 +144,6 @@ final class FieldWriter extends FieldVisitor { @Override public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } ByteVector bv = new ByteVector(); // write type, and reserve space for values count bv.putShort(cw.newUTF8(desc)).putShort(0); @@ -164,9 +161,6 @@ public AnnotationVisitor visitAnnotation(final String desc, @Override public AnnotationVisitor visitTypeAnnotation(final int typeRef, final TypePath typePath, final String desc, final boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } ByteVector bv = new ByteVector(); // write target_type and target_info AnnotationWriter.putTarget(typeRef, typePath, bv); @@ -200,7 +194,7 @@ public void visitEnd() { /** * Returns the size of this field. - * + * * @return the size of this field. */ int getSize() { @@ -220,23 +214,23 @@ int getSize() { cw.newUTF8("Deprecated"); size += 6; } - if (ClassReader.SIGNATURES && signature != 0) { + if (signature != 0) { cw.newUTF8("Signature"); size += 8; } - if (ClassReader.ANNOTATIONS && anns != null) { + if (anns != null) { cw.newUTF8("RuntimeVisibleAnnotations"); size += 8 + anns.getSize(); } - if (ClassReader.ANNOTATIONS && ianns != null) { + if (ianns != null) { cw.newUTF8("RuntimeInvisibleAnnotations"); size += 8 + ianns.getSize(); } - if (ClassReader.ANNOTATIONS && tanns != null) { + if (tanns != null) { cw.newUTF8("RuntimeVisibleTypeAnnotations"); size += 8 + tanns.getSize(); } - if (ClassReader.ANNOTATIONS && itanns != null) { + if (itanns != null) { cw.newUTF8("RuntimeInvisibleTypeAnnotations"); size += 8 + itanns.getSize(); } @@ -248,7 +242,7 @@ int getSize() { /** * Puts the content of this field into the given byte vector. - * + * * @param out * where the content of this field must be put. */ @@ -270,19 +264,19 @@ void put(final ByteVector out) { if ((access & Opcodes.ACC_DEPRECATED) != 0) { ++attributeCount; } - if (ClassReader.SIGNATURES && signature != 0) { + if (signature != 0) { ++attributeCount; } - if (ClassReader.ANNOTATIONS && anns != null) { + if (anns != null) { ++attributeCount; } - if (ClassReader.ANNOTATIONS && ianns != null) { + if (ianns != null) { ++attributeCount; } - if (ClassReader.ANNOTATIONS && tanns != null) { + if (tanns != null) { ++attributeCount; } - if (ClassReader.ANNOTATIONS && itanns != null) { + if (itanns != null) { ++attributeCount; } if (attrs != null) { @@ -302,23 +296,23 @@ void put(final ByteVector out) { if ((access & Opcodes.ACC_DEPRECATED) != 0) { out.putShort(cw.newUTF8("Deprecated")).putInt(0); } - if (ClassReader.SIGNATURES && signature != 0) { + if (signature != 0) { out.putShort(cw.newUTF8("Signature")); out.putInt(2).putShort(signature); } - if (ClassReader.ANNOTATIONS && anns != null) { + if (anns != null) { out.putShort(cw.newUTF8("RuntimeVisibleAnnotations")); anns.put(out); } - if (ClassReader.ANNOTATIONS && ianns != null) { + if (ianns != null) { out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations")); ianns.put(out); } - if (ClassReader.ANNOTATIONS && tanns != null) { + if (tanns != null) { out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations")); tanns.put(out); } - if (ClassReader.ANNOTATIONS && itanns != null) { + if (itanns != null) { out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations")); itanns.put(out); } diff --git a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Frame.java b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Frame.java index cf30ba3ee..bcaf08516 100644 --- a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Frame.java +++ b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Frame.java @@ -31,10 +31,10 @@ /** * Information about the input and output stack map frames of a basic block. - * + * * @author Eric Bruneton */ -final class Frame { +class Frame { /* * Frames are computed in a two steps process: during the visit of each @@ -46,14 +46,14 @@ final class Frame { * of the first basic block (which is computed from the method descriptor), * and by using the previously computed output frames to compute the input * state of the other blocks. - * + * * All output and input frames are stored as arrays of integers. Reference * and array types are represented by an index into a type table (which is * not the same as the constant pool of the class, in order to avoid adding * unnecessary constants in the pool - not all computed frames will end up * being stored in the stack map table). This allows very fast type * comparisons. - * + * * Output stack map frames are computed relatively to the input frame of the * basic block, which is not yet known when output frames are computed. It * is therefore necessary to be able to represent abstract types such as @@ -61,7 +61,7 @@ final class Frame { * position x from the top of the input frame stack" or even "the type at * position x in the input frame, with y more (or less) array dimensions". * This explains the rather complicated type format used in output frames. - * + * * This format is the following: DIM KIND VALUE (4, 4 and 24 bits). DIM is a * signed number of array dimensions (from -8 to 7). KIND is either BASE, * LOCAL or STACK. BASE is used for types that are not relative to the input @@ -72,14 +72,14 @@ final class Frame { * relatively to the top of input frame stack. For BASE types, it is either * one of the constants defined below, or for OBJECT and UNINITIALIZED * types, a tag and an index in the type table. - * + * * Output frames can contain types of any kind and with a positive or * negative dimension (and even unassigned types, represented by 0 - which * does not correspond to any valid type value). Input frames can only * contain BASE types of positive or null dimension. In all cases the type * table contains only internal type names (array type descriptors are * forbidden - dimensions must be represented through the DIM field). - * + * * The LONG and DOUBLE types are always represented by using two slots (LONG * + TOP or DOUBLE + TOP), for local variable types as well as in the * operand stack. This is necessary to be able to simulate DUPx_y @@ -107,7 +107,7 @@ final class Frame { /** * Mask to get the kind of a frame type. - * + * * @see #BASE * @see #LOCAL * @see #STACK @@ -489,18 +489,18 @@ final class Frame { /** * Relative size of the output stack. The exact semantics of this field * depends on the algorithm that is used. - * + * * When only the maximum stack size is computed, this field is the size of * the output stack relatively to the top of the input stack. - * + * * When the stack map frames are completely computed, this field is the * actual number of types in {@link #outputStack}. */ - private int outputStackTop; + int outputStackTop; /** * Number of types that are initialized in the basic block. - * + * * @see #initializations */ private int initializationCount; @@ -520,9 +520,113 @@ final class Frame { */ private int[] initializations; + /** + * Sets this frame to the given value. + * + * @param cw + * the ClassWriter to which this label belongs. + * @param nLocal + * the number of local variables. + * @param local + * the local variable types. Primitive types are represented by + * {@link Opcodes#TOP}, {@link Opcodes#INTEGER}, + * {@link Opcodes#FLOAT}, {@link Opcodes#LONG}, + * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or + * {@link Opcodes#UNINITIALIZED_THIS} (long and double are + * represented by a single element). Reference types are + * represented by String objects (representing internal names), + * and uninitialized types by Label objects (this label + * designates the NEW instruction that created this uninitialized + * value). + * @param nStack + * the number of operand stack elements. + * @param stack + * the operand stack types (same format as the "local" array). + */ + final void set(ClassWriter cw, final int nLocal, final Object[] local, + final int nStack, final Object[] stack) { + int i = convert(cw, nLocal, local, inputLocals); + while (i < local.length) { + inputLocals[i++] = TOP; + } + int nStackTop = 0; + for (int j = 0; j < nStack; ++j) { + if (stack[j] == Opcodes.LONG || stack[j] == Opcodes.DOUBLE) { + ++nStackTop; + } + } + inputStack = new int[nStack + nStackTop]; + convert(cw, nStack, stack, inputStack); + outputStackTop = 0; + initializationCount = 0; + } + + /** + * Converts types from the MethodWriter.visitFrame() format to the Frame + * format. + * + * @param cw + * the ClassWriter to which this label belongs. + * @param nInput + * the number of types to convert. + * @param input + * the types to convert. Primitive types are represented by + * {@link Opcodes#TOP}, {@link Opcodes#INTEGER}, + * {@link Opcodes#FLOAT}, {@link Opcodes#LONG}, + * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or + * {@link Opcodes#UNINITIALIZED_THIS} (long and double are + * represented by a single element). Reference types are + * represented by String objects (representing internal names), + * and uninitialized types by Label objects (this label + * designates the NEW instruction that created this uninitialized + * value). + * @param output + * where to store the converted types. + * @return the number of output elements. + */ + private static int convert(ClassWriter cw, int nInput, Object[] input, + int[] output) { + int i = 0; + for (int j = 0; j < nInput; ++j) { + if (input[j] instanceof Integer) { + output[i++] = BASE | ((Integer) input[j]).intValue(); + if (input[j] == Opcodes.LONG || input[j] == Opcodes.DOUBLE) { + output[i++] = TOP; + } + } else if (input[j] instanceof String) { + output[i++] = type(cw, Type.getObjectType((String) input[j]) + .getDescriptor()); + } else { + output[i++] = UNINITIALIZED + | cw.addUninitializedType("", + ((Label) input[j]).position); + } + } + return i; + } + + /** + * Sets this frame to the value of the given frame. WARNING: after this + * method is called the two frames share the same data structures. It is + * recommended to discard the given frame f to avoid unexpected side + * effects. + * + * @param f + * The new frame value. + */ + final void set(final Frame f) { + inputLocals = f.inputLocals; + inputStack = f.inputStack; + outputLocals = f.outputLocals; + outputStack = f.outputStack; + outputStackTop = f.outputStackTop; + initializationCount = f.initializationCount; + initializations = f.initializations; + } + /** * Returns the output frame local variable type at the given index. - * + * * @param local * the index of the local that must be returned. * @return the output frame local variable type at the given index. @@ -545,7 +649,7 @@ private int get(final int local) { /** * Sets the output frame local variable type at the given index. - * + * * @param local * the index of the local that must be set. * @param type @@ -568,7 +672,7 @@ private void set(final int local, final int type) { /** * Pushes a new type onto the output frame stack. - * + * * @param type * the type that must be pushed. */ @@ -585,7 +689,7 @@ private void push(final int type) { } // pushes the type on the output stack outputStack[outputStackTop++] = type; - // updates the maximun height reached by the output stack, if needed + // updates the maximum height reached by the output stack, if needed int top = owner.inputStackTop + outputStackTop; if (top > owner.outputStackMax) { owner.outputStackMax = top; @@ -594,7 +698,7 @@ private void push(final int type) { /** * Pushes a new type onto the output frame stack. - * + * * @param cw * the ClassWriter to which this label belongs. * @param desc @@ -614,14 +718,14 @@ private void push(final ClassWriter cw, final String desc) { /** * Returns the int encoding of the given type. - * + * * @param cw * the ClassWriter to which this label belongs. * @param desc * a type descriptor. * @return the int encoding of the given type. */ - private static int type(final ClassWriter cw, final String desc) { + static int type(final ClassWriter cw, final String desc) { String t; int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0; switch (desc.charAt(index)) { @@ -688,7 +792,7 @@ private static int type(final ClassWriter cw, final String desc) { /** * Pops a type from the output frame stack and returns its value. - * + * * @return the type that has been popped from the output frame stack. */ private int pop() { @@ -702,7 +806,7 @@ private int pop() { /** * Pops the given number of types from the output frame stack. - * + * * @param elements * the number of types that must be popped. */ @@ -720,7 +824,7 @@ private void pop(final int elements) { /** * Pops a type from the output frame stack. - * + * * @param desc * the descriptor of the type to be popped. Can also be a method * descriptor (in this case this method pops the types @@ -740,7 +844,7 @@ private void pop(final String desc) { /** * Adds a new type to the list of types on which a constructor is invoked in * the basic block. - * + * * @param var * a type on a which a constructor is invoked. */ @@ -762,7 +866,7 @@ private void init(final int var) { /** * Replaces the given type with the appropriate type if it is one of the * types on which a constructor is invoked in the basic block. - * + * * @param cw * the ClassWriter to which this label belongs. * @param t @@ -799,7 +903,7 @@ private int init(final ClassWriter cw, final int t) { /** * Initializes the input frame of the first basic block from the method * descriptor. - * + * * @param cw * the ClassWriter to which this label belongs. * @param access @@ -809,7 +913,7 @@ private int init(final ClassWriter cw, final int t) { * @param maxLocals * the maximum number of local variables of this method. */ - void initInputFrame(final ClassWriter cw, final int access, + final void initInputFrame(final ClassWriter cw, final int access, final Type[] args, final int maxLocals) { inputLocals = new int[maxLocals]; inputStack = new int[0]; @@ -835,7 +939,7 @@ void initInputFrame(final ClassWriter cw, final int access, /** * Simulates the action of the given instruction on the output stack frame. - * + * * @param opcode * the opcode of the instruction. * @param arg @@ -952,7 +1056,7 @@ void execute(final int opcode, final int arg, final ClassWriter cw, case Opcodes.AALOAD: pop(1); t1 = pop(); - push(ELEMENT_OF + t1); + push(t1 == NULL ? t1 : ELEMENT_OF + t1); break; case Opcodes.ISTORE: case Opcodes.FSTORE: @@ -1272,7 +1376,7 @@ void execute(final int opcode, final int arg, final ClassWriter cw, * Merges the input frame of the given basic block with the input and output * frames of this basic block. Returns true if the input frame of * the given label has been changed by this operation. - * + * * @param cw * the ClassWriter to which this label belongs. * @param frame @@ -1283,7 +1387,7 @@ void execute(final int opcode, final int arg, final ClassWriter cw, * @return true if the input frame of the given label has been * changed by this operation. */ - boolean merge(final ClassWriter cw, final Frame frame, final int edge) { + final boolean merge(final ClassWriter cw, final Frame frame, final int edge) { boolean changed = false; int i, s, dim, kind, t; @@ -1380,7 +1484,7 @@ boolean merge(final ClassWriter cw, final Frame frame, final int edge) { * Merges the type at the given index in the given type array with the given * type. Returns true if the type array has been modified by this * operation. - * + * * @param cw * the ClassWriter to which this label belongs. * @param t diff --git a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Handle.java b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Handle.java index a17673d6b..2d8546ea8 100644 --- a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Handle.java +++ b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Handle.java @@ -32,7 +32,7 @@ /** * A reference to a field or a method. - * + * * @author Remi Forax * @author Eric Bruneton */ @@ -63,10 +63,16 @@ public final class Handle { * The descriptor of the field or method designated by this handle. */ final String desc; + + + /** + * Indicate if the owner is an interface or not. + */ + final boolean itf; /** * Constructs a new field or method handle. - * + * * @param tag * the kind of field or method designated by this Handle. Must be * {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, @@ -84,17 +90,49 @@ public final class Handle { * @param desc * the descriptor of the field or method designated by this * handle. + * + * @deprecated this constructor has been superseded + * by {@link #Handle(int, String, String, String, boolean)}. */ + @Deprecated public Handle(int tag, String owner, String name, String desc) { + this(tag, owner, name, desc, tag == Opcodes.H_INVOKEINTERFACE); + } + + /** + * Constructs a new field or method handle. + * + * @param tag + * the kind of field or method designated by this Handle. Must be + * {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, + * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, + * {@link Opcodes#H_INVOKEVIRTUAL}, + * {@link Opcodes#H_INVOKESTATIC}, + * {@link Opcodes#H_INVOKESPECIAL}, + * {@link Opcodes#H_NEWINVOKESPECIAL} or + * {@link Opcodes#H_INVOKEINTERFACE}. + * @param owner + * the internal name of the class that owns the field or method + * designated by this handle. + * @param name + * the name of the field or method designated by this handle. + * @param desc + * the descriptor of the field or method designated by this + * handle. + * @param itf + * true if the owner is an interface. + */ + public Handle(int tag, String owner, String name, String desc, boolean itf) { this.tag = tag; this.owner = owner; this.name = name; this.desc = desc; + this.itf = itf; } - + /** * Returns the kind of field or method designated by this handle. - * + * * @return {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, * {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, @@ -109,7 +147,7 @@ public int getTag() { /** * Returns the internal name of the class that owns the field or method * designated by this handle. - * + * * @return the internal name of the class that owns the field or method * designated by this handle. */ @@ -119,7 +157,7 @@ public String getOwner() { /** * Returns the name of the field or method designated by this handle. - * + * * @return the name of the field or method designated by this handle. */ public String getName() { @@ -128,12 +166,23 @@ public String getName() { /** * Returns the descriptor of the field or method designated by this handle. - * + * * @return the descriptor of the field or method designated by this handle. */ public String getDesc() { return desc; } + + /** + * Returns true if the owner of the field or method designated + * by this handle is an interface. + * + * @return true if the owner of the field or method designated + * by this handle is an interface. + */ + public boolean isInterface() { + return itf; + } @Override public boolean equals(Object obj) { @@ -144,27 +193,30 @@ public boolean equals(Object obj) { return false; } Handle h = (Handle) obj; - return tag == h.tag && owner.equals(h.owner) && name.equals(h.name) - && desc.equals(h.desc); + return tag == h.tag && itf == h.itf && owner.equals(h.owner) + && name.equals(h.name) && desc.equals(h.desc); } @Override public int hashCode() { - return tag + owner.hashCode() * name.hashCode() * desc.hashCode(); + return tag + (itf? 64: 0) + owner.hashCode() * name.hashCode() * desc.hashCode(); } /** * Returns the textual representation of this handle. The textual * representation is: - * + * *
+     * for a reference to a class:
      * owner '.' name desc ' ' '(' tag ')'
+     * for a reference to an interface:
+     * owner '.' name desc ' ' '(' tag ' ' itf ')'
      * 
- * + * * . As this format is unambiguous, it can be parsed if necessary. */ @Override public String toString() { - return owner + '.' + name + desc + " (" + tag + ')'; + return owner + '.' + name + desc + " (" + tag + (itf? " itf": "") + ')'; } } diff --git a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Handler.java b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Handler.java index feafd1075..6279de395 100644 --- a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Handler.java +++ b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Handler.java @@ -31,7 +31,7 @@ /** * Information about an exception handler block. - * + * * @author Eric Bruneton */ class Handler { @@ -71,7 +71,7 @@ class Handler { /** * Removes the range between start and end from the given exception * handlers. - * + * * @param h * an exception handler list. * @param start diff --git a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Item.java b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Item.java index 0404810ec..0119a0641 100644 --- a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Item.java +++ b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Item.java @@ -32,7 +32,7 @@ /** * A constant pool item. Constant pool items can be created with the 'newXXX' * methods in the {@link ClassWriter} class. - * + * * @author Eric Bruneton */ final class Item { @@ -51,12 +51,13 @@ final class Item { * {@link ClassWriter#STR}, {@link ClassWriter#CLASS}, * {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD}, * {@link ClassWriter#METH}, {@link ClassWriter#IMETH}, + * {@link ClassWriter#MODULE}, {@link ClassWriter#PACKAGE}, * {@link ClassWriter#MTYPE}, {@link ClassWriter#INDY}. - * + * * MethodHandle constant 9 variations are stored using a range of 9 values * from {@link ClassWriter#HANDLE_BASE} + 1 to * {@link ClassWriter#HANDLE_BASE} + 9. - * + * * Special Item types are used for Items that are stored in the ClassWriter * {@link ClassWriter#typeTable}, instead of the constant pool, in order to * avoid clashes with normal constant pool items in the ClassWriter constant @@ -114,7 +115,7 @@ final class Item { /** * Constructs an uninitialized {@link Item} for constant pool element at * given position. - * + * * @param index * index of the item to be constructed. */ @@ -124,7 +125,7 @@ final class Item { /** * Constructs a copy of the given item. - * + * * @param index * index of the item to be constructed. * @param i @@ -143,7 +144,7 @@ final class Item { /** * Sets this item to an integer item. - * + * * @param intVal * the value of this item. */ @@ -155,7 +156,7 @@ void set(final int intVal) { /** * Sets this item to a long item. - * + * * @param longVal * the value of this item. */ @@ -167,7 +168,7 @@ void set(final long longVal) { /** * Sets this item to a float item. - * + * * @param floatVal * the value of this item. */ @@ -179,7 +180,7 @@ void set(final float floatVal) { /** * Sets this item to a double item. - * + * * @param doubleVal * the value of this item. */ @@ -191,7 +192,7 @@ void set(final double doubleVal) { /** * Sets this item to an item that do not hold a primitive value. - * + * * @param type * the type of this item. * @param strVal1 @@ -201,6 +202,7 @@ void set(final double doubleVal) { * @param strVal3 * third part of the value of this item. */ + @SuppressWarnings("fallthrough") void set(final int type, final String strVal1, final String strVal2, final String strVal3) { this.type = type; @@ -213,6 +215,8 @@ void set(final int type, final String strVal1, final String strVal2, case ClassWriter.UTF8: case ClassWriter.STR: case ClassWriter.MTYPE: + case ClassWriter.MODULE: + case ClassWriter.PACKAGE: case ClassWriter.TYPE_NORMAL: hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()); return; @@ -233,7 +237,7 @@ void set(final int type, final String strVal1, final String strVal2, /** * Sets the item to an InvokeDynamic item. - * + * * @param name * invokedynamic's name. * @param desc @@ -252,7 +256,7 @@ void set(String name, String desc, int bsmIndex) { /** * Sets the item to a BootstrapMethod item. - * + * * @param position * position in byte in the class attribute BootrapMethods. * @param hashCode @@ -269,7 +273,7 @@ void set(int position, int hashCode) { /** * Indicates if the given item is equal to this one. This method assumes * that the two items have the same {@link #type}. - * + * * @param i * the item to be compared to this one. Both items must have the * same {@link #type}. @@ -281,6 +285,8 @@ boolean isEqualTo(final Item i) { case ClassWriter.UTF8: case ClassWriter.STR: case ClassWriter.CLASS: + case ClassWriter.MODULE: + case ClassWriter.PACKAGE: case ClassWriter.MTYPE: case ClassWriter.TYPE_NORMAL: return i.strVal1.equals(strVal1); diff --git a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Label.java b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Label.java index 16c51a247..0f84f1d38 100644 --- a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Label.java +++ b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Label.java @@ -35,7 +35,7 @@ * designates the instruction that is just after. Note however that there * can be other elements between a label and the instruction it designates (such * as other labels, stack map frames, line numbers, etc.). - * + * * @author Eric Bruneton */ public class Label { @@ -117,7 +117,7 @@ public class Label { /** * Flags that indicate the status of this label. - * + * * @see #DEBUG * @see #RESOLVED * @see #RESIZED @@ -131,7 +131,11 @@ public class Label { int status; /** - * The line number corresponding to this label, if known. + * The line number corresponding to this label, if known. If there are + * several lines, each line is stored in a separate label, all linked via + * their next field (these links are created in ClassReader and removed just + * before visitLabel is called, so that this does not impact the rest of the + * code). */ int line; @@ -170,7 +174,7 @@ public class Label { * represented by the Label object that corresponds to the first instruction * of this basic block. Each node also stores the list of its successors in * the graph, as a linked list of Edge objects. - * + * * The control flow analysis algorithms used to compute the maximum stack * size or the stack map frames are similar and use two steps. The first * step, during the visit of each instruction, builds information about the @@ -182,7 +186,7 @@ public class Label { * information about the input frame of each basic block, from the input * state of the first basic block (known from the method signature), and by * the using the previously computed relative output frames. - * + * * The algorithm used to compute the maximum stack size only computes the * relative output and absolute input stack heights, while the algorithm * used to compute stack map frames computes relative output frames and @@ -192,10 +196,10 @@ public class Label { /** * Start of the output stack relatively to the input stack. The exact * semantics of this field depends on the algorithm that is used. - * + * * When only the maximum stack size is computed, this field is the number of * elements in the input stack. - * + * * When the stack map frames are completely computed, this field is the * offset of the first output stack element relatively to the top of the * input stack. This offset is always negative or null. A null offset means @@ -239,8 +243,9 @@ public class Label { * The next basic block in the basic block stack. This stack is used in the * main loop of the fix point algorithm used in the second step of the * control flow analysis algorithms. It is also used in - * {@link #visitSubroutine} to avoid using a recursive method. - * + * {@link #visitSubroutine} to avoid using a recursive method, and in + * ClassReader to temporarily store multiple source lines for a label. + * * @see MethodWriter#visitMaxs */ Label next; @@ -264,7 +269,7 @@ public Label() { * from the start of the method's bytecode. This method is intended for * {@link Attribute} sub classes, and is normally not needed by class * generators or adapters. - * + * * @return the offset corresponding to this label. * @throws IllegalStateException * if this label is not resolved yet. @@ -282,7 +287,7 @@ public int getOffset() { * position of the label is known, the offset is computed and written * directly. Otherwise, a null offset is written and a new forward reference * is declared for this label. - * + * * @param owner * the code writer that calls this method. * @param out @@ -320,7 +325,7 @@ void put(final MethodWriter owner, final ByteVector out, final int source, * for a true forward reference, i.e. only if this label is not resolved * yet. For backward references, the offset of the reference can be, and * must be, computed and stored directly. - * + * * @param sourcePosition * the position of the referencing instruction. This position * will be used to compute the offset of this forward reference. @@ -348,20 +353,19 @@ private void addReference(final int sourcePosition, * when this label is added to the bytecode of the method, i.e. when its * position becomes known. This method fills in the blanks that where left * in the bytecode by each forward reference previously added to this label. - * + * * @param owner * the code writer that calls this method. * @param position * the position of this label in the bytecode. * @param data * the bytecode of the method. - * @return true if a blank that was left for this label was to + * @return true if a blank that was left for this label was too * small to store the offset. In such a case the corresponding jump * instruction is replaced with a pseudo instruction (using unused * opcodes) using an unsigned two bytes offset. These pseudo - * instructions will need to be replaced with true instructions with - * wider offsets (4 bytes instead of 2). This is done in - * {@link MethodWriter#resizeInstructions}. + * instructions will be replaced with standard bytecode instructions + * with wider offsets (4 bytes instead of 2), in ClassReader. * @throws IllegalArgumentException * if this label has already been resolved, or if it has not * been created by the given code writer. @@ -416,11 +420,11 @@ boolean resolve(final MethodWriter owner, final int position, * isolated label or for the first label in a series of successive labels, * this method returns the label itself. For other labels it returns the * first label of the series. - * + * * @return the first label of the series to which this label belongs. */ Label getFirst() { - return !ClassReader.FRAMES || frame == null ? this : frame.owner; + return frame == null ? this : frame.owner; } // ------------------------------------------------------------------------ @@ -429,7 +433,7 @@ Label getFirst() { /** * Returns true is this basic block belongs to the given subroutine. - * + * * @param id * a subroutine id. * @return true is this basic block belongs to the given subroutine. @@ -444,7 +448,7 @@ boolean inSubroutine(final long id) { /** * Returns true if this basic block and the given one belong to a common * subroutine. - * + * * @param block * another basic block. * @return true if this basic block and the given one belong to a common @@ -464,7 +468,7 @@ boolean inSameSubroutine(final Label block) { /** * Marks this basic block as belonging to the given subroutine. - * + * * @param id * a subroutine id. * @param nbSubroutines @@ -483,7 +487,7 @@ void addToSubroutine(final long id, final int nbSubroutines) { * blocks as belonging to this subroutine. This method follows the control * flow graph to find all the blocks that are reachable from the current * block WITHOUT following any JSR target. - * + * * @param JSR * a JSR block that jumps to this subroutine. If this JSR is not * null it is added to the successor of the RET blocks found in @@ -550,7 +554,7 @@ void visitSubroutine(final Label JSR, final long id, final int nbSubroutines) { /** * Returns a string representation of this label. - * + * * @return a string representation of this label. */ @Override diff --git a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/MethodVisitor.java b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/MethodVisitor.java index 0a5d22061..233ae2189 100644 --- a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/MethodVisitor.java +++ b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/MethodVisitor.java @@ -33,15 +33,16 @@ * A visitor to visit a Java method. The methods of this class must be called in * the following order: ( visitParameter )* [ * visitAnnotationDefault ] ( visitAnnotation | - * visitTypeAnnotation | visitAttribute )* [ - * visitCode ( visitFrame | visitXInsn | - * visitLabel | visitInsnAnnotation | - * visitTryCatchBlock | visitTryCatchBlockAnnotation | - * visitLocalVariable | visitLocalVariableAnnotation | - * visitLineNumber )* visitMaxs ] visitEnd. In - * addition, the visitXInsn and visitLabel methods must - * be called in the sequential order of the bytecode instructions of the visited - * code, visitInsnAnnotation must be called after the annotated + * visitParameterAnnotation visitTypeAnnotation | + * visitAttribute )* [ visitCode ( visitFrame | + * visitXInsn | visitLabel | + * visitInsnAnnotation | visitTryCatchBlock | + * visitTryCatchAnnotation | visitLocalVariable | + * visitLocalVariableAnnotation | visitLineNumber )* + * visitMaxs ] visitEnd. In addition, the + * visitXInsn and visitLabel methods must be called in + * the sequential order of the bytecode instructions of the visited code, + * visitInsnAnnotation must be called after the annotated * instruction, visitTryCatchBlock must be called before the * labels passed as arguments have been visited, * visitTryCatchBlockAnnotation must be called after the @@ -49,14 +50,14 @@ * visitLocalVariable, visitLocalVariableAnnotation and * visitLineNumber methods must be called after the labels * passed as arguments have been visited. - * + * * @author Eric Bruneton */ public abstract class MethodVisitor { /** * The ASM API version implemented by this visitor. The value of this field - * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + * must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. */ protected final int api; @@ -68,10 +69,10 @@ public abstract class MethodVisitor { /** * Constructs a new {@link MethodVisitor}. - * + * * @param api * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. */ public MethodVisitor(final int api) { this(api, null); @@ -79,16 +80,16 @@ public MethodVisitor(final int api) { /** * Constructs a new {@link MethodVisitor}. - * + * * @param api * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. + * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. * @param mv * the method visitor to which this visitor must delegate method * calls. May be null. */ public MethodVisitor(final int api, final MethodVisitor mv) { - if (api != Opcodes.ASM4 && api != Opcodes.ASM5) { + if (api < Opcodes.ASM4 || api > Opcodes.ASM6) { throw new IllegalArgumentException(); } this.api = api; @@ -101,7 +102,7 @@ public MethodVisitor(final int api, final MethodVisitor mv) { /** * Visits a parameter of this method. - * + * * @param name * parameter name or null if none is provided. * @param access @@ -120,7 +121,7 @@ public void visitParameter(String name, int access) { /** * Visits the default value of this annotation interface method. - * + * * @return a visitor to the visit the actual default value of this * annotation interface method, or null if this visitor is * not interested in visiting this default value. The 'name' @@ -137,7 +138,7 @@ public AnnotationVisitor visitAnnotationDefault() { /** * Visits an annotation of this method. - * + * * @param desc * the class descriptor of the annotation class. * @param visible @@ -154,7 +155,7 @@ public AnnotationVisitor visitAnnotation(String desc, boolean visible) { /** * Visits an annotation on a type in the method signature. - * + * * @param typeRef * a reference to the annotated type. The sort of this type * reference must be {@link TypeReference#METHOD_TYPE_PARAMETER @@ -190,7 +191,7 @@ public AnnotationVisitor visitTypeAnnotation(int typeRef, /** * Visits an annotation of a parameter this method. - * + * * @param parameter * the parameter index. * @param desc @@ -210,7 +211,7 @@ public AnnotationVisitor visitParameterAnnotation(int parameter, /** * Visits a non standard attribute of this method. - * + * * @param attr * an attribute. */ @@ -271,7 +272,7 @@ public void visitCode() { * and access flags, is implicit and must not be visited. Also, it is * illegal to visit two or more frames for the same code location (i.e., at * least one instruction must be visited between two calls to visitFrame). - * + * * @param type * the type of this stack map frame. Must be * {@link Opcodes#F_NEW} for expanded frames, or @@ -317,7 +318,7 @@ public void visitFrame(int type, int nLocal, Object[] local, int nStack, /** * Visits a zero operand instruction. - * + * * @param opcode * the opcode of the instruction to be visited. This opcode is * either NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, @@ -343,7 +344,7 @@ public void visitInsn(int opcode) { /** * Visits an instruction with a single int operand. - * + * * @param opcode * the opcode of the instruction to be visited. This opcode is * either BIPUSH, SIPUSH or NEWARRAY. @@ -368,7 +369,7 @@ public void visitIntInsn(int opcode, int operand) { /** * Visits a local variable instruction. A local variable instruction is an * instruction that loads or stores the value of a local variable. - * + * * @param opcode * the opcode of the local variable instruction to be visited. * This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, @@ -386,7 +387,7 @@ public void visitVarInsn(int opcode, int var) { /** * Visits a type instruction. A type instruction is an instruction that * takes the internal name of a class as parameter. - * + * * @param opcode * the opcode of the type instruction to be visited. This opcode * is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF. @@ -404,7 +405,7 @@ public void visitTypeInsn(int opcode, String type) { /** * Visits a field instruction. A field instruction is an instruction that * loads or stores the value of a field of an object. - * + * * @param opcode * the opcode of the type instruction to be visited. This opcode * is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD. @@ -426,7 +427,7 @@ public void visitFieldInsn(int opcode, String owner, String name, /** * Visits a method instruction. A method instruction is an instruction that * invokes a method. - * + * * @param opcode * the opcode of the type instruction to be visited. This opcode * is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or @@ -455,7 +456,7 @@ public void visitMethodInsn(int opcode, String owner, String name, /** * Visits a method instruction. A method instruction is an instruction that * invokes a method. - * + * * @param opcode * the opcode of the type instruction to be visited. This opcode * is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or @@ -487,7 +488,7 @@ public void visitMethodInsn(int opcode, String owner, String name, /** * Visits an invokedynamic instruction. - * + * * @param name * the method's name. * @param desc @@ -511,7 +512,7 @@ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, /** * Visits a jump instruction. A jump instruction is an instruction that may * jump to another instruction. - * + * * @param opcode * the opcode of the type instruction to be visited. This opcode * is either IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, @@ -531,7 +532,7 @@ public void visitJumpInsn(int opcode, Label label) { /** * Visits a label. A label designates the instruction that will be visited * just after it. - * + * * @param label * a {@link Label Label} object. */ @@ -550,7 +551,7 @@ public void visitLabel(Label label) { * future versions of the Java Virtual Machine. To easily detect new * constant types, implementations of this method should check for * unexpected constant types, like this: - * + * *
      * if (cst instanceof Integer) {
      *     // ...
@@ -579,7 +580,7 @@ public void visitLabel(Label label) {
      *     // throw an exception
      * }
      * 
- * + * * @param cst * the constant to be loaded on the stack. This parameter must be * a non null {@link Integer}, a {@link Float}, a {@link Long}, a @@ -597,7 +598,7 @@ public void visitLdcInsn(Object cst) { /** * Visits an IINC instruction. - * + * * @param var * index of the local variable to be incremented. * @param increment @@ -611,7 +612,7 @@ public void visitIincInsn(int var, int increment) { /** * Visits a TABLESWITCH instruction. - * + * * @param min * the minimum key value. * @param max @@ -631,7 +632,7 @@ public void visitTableSwitchInsn(int min, int max, Label dflt, /** * Visits a LOOKUPSWITCH instruction. - * + * * @param dflt * beginning of the default handler block. * @param keys @@ -648,7 +649,7 @@ public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { /** * Visits a MULTIANEWARRAY instruction. - * + * * @param desc * an array type descriptor (see {@link Type Type}). * @param dims @@ -664,7 +665,7 @@ public void visitMultiANewArrayInsn(String desc, int dims) { * Visits an annotation on an instruction. This method must be called just * after the annotated instruction. It can be called several times * for the same instruction. - * + * * @param typeRef * a reference to the annotated type. The sort of this type * reference must be {@link TypeReference#INSTANCEOF INSTANCEOF}, @@ -708,7 +709,7 @@ public AnnotationVisitor visitInsnAnnotation(int typeRef, /** * Visits a try catch block. - * + * * @param start * beginning of the exception handler's scope (inclusive). * @param end @@ -735,7 +736,7 @@ public void visitTryCatchBlock(Label start, Label end, Label handler, * called after the {@link #visitTryCatchBlock} for the annotated * exception handler. It can be called several times for the same exception * handler. - * + * * @param typeRef * a reference to the annotated type. The sort of this type * reference must be {@link TypeReference#EXCEPTION_PARAMETER @@ -764,7 +765,7 @@ public AnnotationVisitor visitTryCatchAnnotation(int typeRef, /** * Visits a local variable declaration. - * + * * @param name * the name of a local variable. * @param desc @@ -794,7 +795,7 @@ public void visitLocalVariable(String name, String desc, String signature, /** * Visits an annotation on a local variable type. - * + * * @param typeRef * a reference to the annotated type. The sort of this type * reference must be {@link TypeReference#LOCAL_VARIABLE @@ -836,7 +837,7 @@ public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, /** * Visits a line number declaration. - * + * * @param line * a line number. This number refers to the source file from * which the class was compiled. @@ -855,7 +856,7 @@ public void visitLineNumber(int line, Label start) { /** * Visits the maximum stack size and the maximum number of local variables * of the method. - * + * * @param maxStack * maximum stack size of the method. * @param maxLocals diff --git a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/MethodWriter.java b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/MethodWriter.java index 5355b3f05..bf6624ce5 100644 --- a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/MethodWriter.java +++ b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/MethodWriter.java @@ -33,7 +33,7 @@ * A {@link MethodVisitor} that generates methods in bytecode form. Each visit * method of this class appends the bytecode corresponding to the visited * instruction to a byte vector, in the order these methods are called. - * + * * @author Eric Bruneton * @author Eugene Kuleshov */ @@ -96,25 +96,37 @@ class MethodWriter extends MethodVisitor { * Indicates that the stack map frames must be recomputed from scratch. In * this case the maximum stack size and number of local variables is also * recomputed from scratch. - * + * + * @see #compute + */ + static final int FRAMES = 0; + + /** + * Indicates that the stack map frames of type F_INSERT must be computed. + * The other frames are not (re)computed. They should all be of type F_NEW + * and should be sufficient to compute the content of the F_INSERT frames, + * together with the bytecode instructions between a F_NEW and a F_INSERT + * frame - and without any knowledge of the type hierarchy (by definition of + * F_INSERT). + * * @see #compute */ - private static final int FRAMES = 0; + static final int INSERTED_FRAMES = 1; /** * Indicates that the maximum stack size and number of local variables must * be automatically computed. - * + * * @see #compute */ - private static final int MAXS = 1; + static final int MAXS = 2; /** * Indicates that nothing must be automatically computed. - * + * * @see #compute */ - private static final int NOTHING = 2; + static final int NOTHING = 3; /** * The class writer to which this method must be added. @@ -248,7 +260,7 @@ class MethodWriter extends MethodVisitor { /** * Number of stack map frames in the StackMapTable attribute. */ - private int frameCount; + int frameCount; /** * The StackMapTable attribute. @@ -263,7 +275,7 @@ class MethodWriter extends MethodVisitor { /** * The last frame that was written in the StackMapTable attribute. - * + * * @see #frame */ private int[] previousFrame; @@ -354,11 +366,6 @@ class MethodWriter extends MethodVisitor { */ private Attribute cattrs; - /** - * Indicates if some jump instructions are too small and need to be resized. - */ - private boolean resize; - /** * The number of subroutines in this method. */ @@ -378,8 +385,9 @@ class MethodWriter extends MethodVisitor { /** * Indicates what must be automatically computed. - * + * * @see #FRAMES + * @see #INSERTED_FRAMES * @see #MAXS * @see #NOTHING */ @@ -428,7 +436,7 @@ class MethodWriter extends MethodVisitor { /** * Constructs a new {@link MethodWriter}. - * + * * @param cw * the class writer in which the method must be added. * @param access @@ -442,18 +450,13 @@ class MethodWriter extends MethodVisitor { * @param exceptions * the internal names of the method's exceptions. May be * null. - * @param computeMaxs - * true if the maximum stack size and number of local - * variables must be automatically computed. - * @param computeFrames - * true if the stack map tables must be recomputed from - * scratch. + * @param compute + * Indicates what must be automatically computed (see #compute). */ MethodWriter(final ClassWriter cw, final int access, final String name, final String desc, final String signature, - final String[] exceptions, final boolean computeMaxs, - final boolean computeFrames) { - super(Opcodes.ASM5); + final String[] exceptions, final int compute) { + super(Opcodes.ASM6); if (cw.firstMethod == null) { cw.firstMethod = this; } else { @@ -468,9 +471,7 @@ class MethodWriter extends MethodVisitor { this.name = cw.newUTF8(name); this.desc = cw.newUTF8(desc); this.descriptor = desc; - if (ClassReader.SIGNATURES) { - this.signature = signature; - } + this.signature = signature; if (exceptions != null && exceptions.length > 0) { exceptionCount = exceptions.length; this.exceptions = new int[exceptionCount]; @@ -478,8 +479,8 @@ class MethodWriter extends MethodVisitor { this.exceptions[i] = cw.newClass(exceptions[i]); } } - this.compute = computeFrames ? FRAMES : (computeMaxs ? MAXS : NOTHING); - if (computeMaxs || computeFrames) { + this.compute = compute; + if (compute != NOTHING) { // updates maxLocals int size = Type.getArgumentsAndReturnSizes(descriptor) >> 2; if ((access & Opcodes.ACC_STATIC) != 0) { @@ -510,9 +511,6 @@ public void visitParameter(String name, int access) { @Override public AnnotationVisitor visitAnnotationDefault() { - if (!ClassReader.ANNOTATIONS) { - return null; - } annd = new ByteVector(); return new AnnotationWriter(cw, false, annd, null, 0); } @@ -520,9 +518,6 @@ public AnnotationVisitor visitAnnotationDefault() { @Override public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } ByteVector bv = new ByteVector(); // write type, and reserve space for values count bv.putShort(cw.newUTF8(desc)).putShort(0); @@ -540,9 +535,6 @@ public AnnotationVisitor visitAnnotation(final String desc, @Override public AnnotationVisitor visitTypeAnnotation(final int typeRef, final TypePath typePath, final String desc, final boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } ByteVector bv = new ByteVector(); // write target_type and target_info AnnotationWriter.putTarget(typeRef, typePath, bv); @@ -563,9 +555,6 @@ public AnnotationVisitor visitTypeAnnotation(final int typeRef, @Override public AnnotationVisitor visitParameterAnnotation(final int parameter, final String desc, final boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } ByteVector bv = new ByteVector(); if ("Ljava/lang/Synthetic;".equals(desc)) { // workaround for a bug in javac with synthetic parameters @@ -610,11 +599,33 @@ public void visitCode() { @Override public void visitFrame(final int type, final int nLocal, final Object[] local, final int nStack, final Object[] stack) { - if (!ClassReader.FRAMES || compute == FRAMES) { + if (compute == FRAMES) { return; } - if (type == Opcodes.F_NEW) { + if (compute == INSERTED_FRAMES) { + if (currentBlock.frame == null) { + // This should happen only once, for the implicit first frame + // (which is explicitly visited in ClassReader if the + // EXPAND_ASM_INSNS option is used). + currentBlock.frame = new CurrentFrame(); + currentBlock.frame.owner = currentBlock; + currentBlock.frame.initInputFrame(cw, access, + Type.getArgumentTypes(descriptor), nLocal); + visitImplicitFirstFrame(); + } else { + if (type == Opcodes.F_NEW) { + currentBlock.frame.set(cw, nLocal, local, nStack, stack); + } else { + // In this case type is equal to F_INSERT by hypothesis, and + // currentBlock.frame contains the stack map frame at the + // current instruction, computed from the last F_NEW frame + // and the bytecode instructions in between (via calls to + // CurrentFrame#execute). + } + visitFrame(currentBlock.frame); + } + } else if (type == Opcodes.F_NEW) { if (previousFrame == null) { visitImplicitFirstFrame(); } @@ -622,10 +633,10 @@ public void visitFrame(final int type, final int nLocal, int frameIndex = startFrame(code.length, nLocal, nStack); for (int i = 0; i < nLocal; ++i) { if (local[i] instanceof String) { - frame[frameIndex++] = Frame.OBJECT - | cw.addType((String) local[i]); + String desc = Type.getObjectType((String) local[i]).getDescriptor(); + frame[frameIndex++] = Frame.type(cw, desc); } else if (local[i] instanceof Integer) { - frame[frameIndex++] = ((Integer) local[i]).intValue(); + frame[frameIndex++] = Frame.BASE | ((Integer) local[i]).intValue(); } else { frame[frameIndex++] = Frame.UNINITIALIZED | cw.addUninitializedType("", @@ -634,10 +645,10 @@ public void visitFrame(final int type, final int nLocal, } for (int i = 0; i < nStack; ++i) { if (stack[i] instanceof String) { - frame[frameIndex++] = Frame.OBJECT - | cw.addType((String) stack[i]); + String desc = Type.getObjectType((String) stack[i]).getDescriptor(); + frame[frameIndex++] = Frame.type(cw, desc); } else if (stack[i] instanceof Integer) { - frame[frameIndex++] = ((Integer) stack[i]).intValue(); + frame[frameIndex++] = Frame.BASE | ((Integer) stack[i]).intValue(); } else { frame[frameIndex++] = Frame.UNINITIALIZED | cw.addUninitializedType("", @@ -718,7 +729,7 @@ public void visitInsn(final int opcode) { // update currentBlock // Label currentBlock = this.currentBlock; if (currentBlock != null) { - if (compute == FRAMES) { + if (compute == FRAMES || compute == INSERTED_FRAMES) { currentBlock.frame.execute(opcode, 0, null, null); } else { // updates current and max stack sizes @@ -741,7 +752,7 @@ public void visitIntInsn(final int opcode, final int operand) { lastCodeOffset = code.length; // Label currentBlock = this.currentBlock; if (currentBlock != null) { - if (compute == FRAMES) { + if (compute == FRAMES || compute == INSERTED_FRAMES) { currentBlock.frame.execute(opcode, operand, null, null); } else if (opcode != Opcodes.NEWARRAY) { // updates current and max stack sizes only for NEWARRAY @@ -766,7 +777,7 @@ public void visitVarInsn(final int opcode, final int var) { lastCodeOffset = code.length; // Label currentBlock = this.currentBlock; if (currentBlock != null) { - if (compute == FRAMES) { + if (compute == FRAMES || compute == INSERTED_FRAMES) { currentBlock.frame.execute(opcode, var, null, null); } else { // updates current and max stack sizes @@ -823,10 +834,10 @@ public void visitVarInsn(final int opcode, final int var) { @Override public void visitTypeInsn(final int opcode, final String type) { lastCodeOffset = code.length; - Item i = cw.newClassItem(type); + Item i = cw.newStringishItem(ClassWriter.CLASS, type); // Label currentBlock = this.currentBlock; if (currentBlock != null) { - if (compute == FRAMES) { + if (compute == FRAMES || compute == INSERTED_FRAMES) { currentBlock.frame.execute(opcode, code.length, cw, i); } else if (opcode == Opcodes.NEW) { // updates current and max stack sizes only if opcode == NEW @@ -849,7 +860,7 @@ public void visitFieldInsn(final int opcode, final String owner, Item i = cw.newFieldItem(owner, name, desc); // Label currentBlock = this.currentBlock; if (currentBlock != null) { - if (compute == FRAMES) { + if (compute == FRAMES || compute == INSERTED_FRAMES) { currentBlock.frame.execute(opcode, 0, cw, i); } else { int size; @@ -889,7 +900,7 @@ public void visitMethodInsn(final int opcode, final String owner, int argSize = i.intVal; // Label currentBlock = this.currentBlock; if (currentBlock != null) { - if (compute == FRAMES) { + if (compute == FRAMES || compute == INSERTED_FRAMES) { currentBlock.frame.execute(opcode, 0, cw, i); } else { /* @@ -941,7 +952,7 @@ public void visitInvokeDynamicInsn(final String name, final String desc, int argSize = i.intVal; // Label currentBlock = this.currentBlock; if (currentBlock != null) { - if (compute == FRAMES) { + if (compute == FRAMES || compute == INSERTED_FRAMES) { currentBlock.frame.execute(Opcodes.INVOKEDYNAMIC, 0, cw, i); } else { /* @@ -975,7 +986,9 @@ public void visitInvokeDynamicInsn(final String name, final String desc, } @Override - public void visitJumpInsn(final int opcode, final Label label) { + public void visitJumpInsn(int opcode, final Label label) { + boolean isWide = opcode >= 200; // GOTO_W + opcode = isWide ? opcode - 33 : opcode; lastCodeOffset = code.length; Label nextInsn = null; // Label currentBlock = this.currentBlock; @@ -990,6 +1003,8 @@ public void visitJumpInsn(final int opcode, final Label label) { // creates a Label for the next basic block nextInsn = new Label(); } + } else if (compute == INSERTED_FRAMES) { + currentBlock.frame.execute(opcode, 0, null, null); } else { if (opcode == Opcodes.JSR) { if ((label.status & Label.SUBROUTINE) == 0) { @@ -1021,8 +1036,8 @@ public void visitJumpInsn(final int opcode, final Label label) { /* * case of a backward jump with an offset < -32768. In this case we * automatically replace GOTO with GOTO_W, JSR with JSR_W and IFxxx - * with IFNOTxxx GOTO_W , where IFNOTxxx is the - * "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) and where + * with IFNOTxxx GOTO_W L:..., where IFNOTxxx is the + * "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) and where * designates the instruction just after the GOTO_W. */ if (opcode == Opcodes.GOTO) { @@ -1038,9 +1053,21 @@ public void visitJumpInsn(final int opcode, final Label label) { code.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1 : opcode ^ 1); code.putShort(8); // jump offset - code.putByte(200); // GOTO_W + // ASM pseudo GOTO_W insn, see ClassReader. We don't use a real + // GOTO_W because we might need to insert a frame just after (as + // the target of the IFNOTxxx jump instruction). + code.putByte(220); + cw.hasAsmInsns = true; } label.put(this, code, code.length - 1, true); + } else if (isWide) { + /* + * case of a GOTO_W or JSR_W specified by the user (normally + * ClassReader when used to resize instructions). In this case we + * keep the original instruction. + */ + code.putByte(opcode + 33); + label.put(this, code, code.length - 1, true); } else { /* * case of a backward jump with an offset >= -32768, or of a forward @@ -1068,7 +1095,7 @@ public void visitJumpInsn(final int opcode, final Label label) { @Override public void visitLabel(final Label label) { // resolves previous forward references to label, if any - resize |= label.resolve(this, code.length, code.data); + cw.hasAsmInsns |= label.resolve(this, code.length, code.data); // updates currentBlock if ((label.status & Label.DEBUG) != 0) { return; @@ -1101,6 +1128,18 @@ public void visitLabel(final Label label) { previousBlock.successor = label; } previousBlock = label; + } else if (compute == INSERTED_FRAMES) { + if (currentBlock == null) { + // This case should happen only once, for the visitLabel call in + // the constructor. Indeed, if compute is equal to + // INSERTED_FRAMES currentBlock can not be set back to null (see + // #noSuccessor). + currentBlock = label; + } else { + // Updates the frame owner so that a correct frame offset is + // computed in visitFrame(Frame). + currentBlock.frame.owner = label; + } } else if (compute == MAXS) { if (currentBlock != null) { // ends current block (with one new successor) @@ -1126,7 +1165,7 @@ public void visitLdcInsn(final Object cst) { Item i = cw.newConstItem(cst); // Label currentBlock = this.currentBlock; if (currentBlock != null) { - if (compute == FRAMES) { + if (compute == FRAMES || compute == INSERTED_FRAMES) { currentBlock.frame.execute(Opcodes.LDC, 0, cw, i); } else { int size; @@ -1158,7 +1197,7 @@ public void visitLdcInsn(final Object cst) { public void visitIincInsn(final int var, final int increment) { lastCodeOffset = code.length; if (currentBlock != null) { - if (compute == FRAMES) { + if (compute == FRAMES || compute == INSERTED_FRAMES) { currentBlock.frame.execute(Opcodes.IINC, var, null, null); } } @@ -1242,10 +1281,10 @@ private void visitSwitchInsn(final Label dflt, final Label[] labels) { @Override public void visitMultiANewArrayInsn(final String desc, final int dims) { lastCodeOffset = code.length; - Item i = cw.newClassItem(desc); + Item i = cw.newStringishItem(ClassWriter.CLASS, desc); // Label currentBlock = this.currentBlock; if (currentBlock != null) { - if (compute == FRAMES) { + if (compute == FRAMES || compute == INSERTED_FRAMES) { currentBlock.frame.execute(Opcodes.MULTIANEWARRAY, dims, cw, i); } else { // updates current stack size (max stack size unchanged because @@ -1260,9 +1299,6 @@ public void visitMultiANewArrayInsn(final String desc, final int dims) { @Override public AnnotationVisitor visitInsnAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } ByteVector bv = new ByteVector(); // write target_type and target_info typeRef = (typeRef & 0xFF0000FF) | (lastCodeOffset << 8); @@ -1302,9 +1338,6 @@ public void visitTryCatchBlock(final Label start, final Label end, @Override public AnnotationVisitor visitTryCatchAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } ByteVector bv = new ByteVector(); // write target_type and target_info AnnotationWriter.putTarget(typeRef, typePath, bv); @@ -1358,9 +1391,6 @@ public void visitLocalVariable(final String name, final String desc, public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, TypePath typePath, Label[] start, Label[] end, int[] index, String desc, boolean visible) { - if (!ClassReader.ANNOTATIONS) { - return null; - } ByteVector bv = new ByteVector(); // write target_type and target_info bv.putByte(typeRef >>> 24).putShort(start.length); @@ -1401,15 +1431,7 @@ public void visitLineNumber(final int line, final Label start) { @Override public void visitMaxs(final int maxStack, final int maxLocals) { - if (resize) { - // replaces the temporary jump opcodes introduced by Label.resolve. - if (ClassReader.RESIZE) { - resizeInstructions(); - } else { - throw new RuntimeException("Method code too large!"); - } - } - if (ClassReader.FRAMES && compute == FRAMES) { + if (compute == FRAMES) { // completes the control flow graph with exception handler blocks Handler handler = firstHandler; while (handler != null) { @@ -1439,8 +1461,8 @@ public void visitMaxs(final int maxStack, final int maxLocals) { // creates and visits the first (implicit) frame Frame f = labels.frame; - Type[] args = Type.getArgumentTypes(descriptor); - f.initInputFrame(cw, access, args, this.maxLocals); + f.initInputFrame(cw, access, Type.getArgumentTypes(descriptor), + this.maxLocals); visitFrame(f); /* @@ -1657,7 +1679,7 @@ public void visitEnd() { /** * Adds a successor to the {@link #currentBlock currentBlock} block. - * + * * @param info * information about the control flow edge to be added. * @param successor @@ -1688,7 +1710,9 @@ private void noSuccessor() { } else { currentBlock.outputStackMax = maxStackSize; } - currentBlock = null; + if (compute != INSERTED_FRAMES) { + currentBlock = null; + } } // ------------------------------------------------------------------------ @@ -1697,7 +1721,7 @@ private void noSuccessor() { /** * Visits a frame that has been computed from scratch. - * + * * @param f * the frame that must be visited. */ @@ -1760,7 +1784,7 @@ private void visitImplicitFirstFrame() { if ((access & ACC_CONSTRUCTOR) == 0) { frame[frameIndex++] = Frame.OBJECT | cw.addType(cw.thisName); } else { - frame[frameIndex++] = 6; // Opcodes.UNINITIALIZED_THIS; + frame[frameIndex++] = Frame.UNINITIALIZED_THIS; } } int i = 1; @@ -1772,16 +1796,16 @@ private void visitImplicitFirstFrame() { case 'B': case 'S': case 'I': - frame[frameIndex++] = 1; // Opcodes.INTEGER; + frame[frameIndex++] = Frame.INTEGER; break; case 'F': - frame[frameIndex++] = 2; // Opcodes.FLOAT; + frame[frameIndex++] = Frame.FLOAT; break; case 'J': - frame[frameIndex++] = 4; // Opcodes.LONG; + frame[frameIndex++] = Frame.LONG; break; case 'D': - frame[frameIndex++] = 3; // Opcodes.DOUBLE; + frame[frameIndex++] = Frame.DOUBLE; break; case '[': while (descriptor.charAt(i) == '[') { @@ -1793,8 +1817,7 @@ private void visitImplicitFirstFrame() { ++i; } } - frame[frameIndex++] = Frame.OBJECT - | cw.addType(descriptor.substring(j, ++i)); + frame[frameIndex++] = Frame.type(cw, descriptor.substring(j, ++i)); break; case 'L': while (descriptor.charAt(i) != ';') { @@ -1813,7 +1836,7 @@ private void visitImplicitFirstFrame() { /** * Starts the visit of a stack map frame. - * + * * @param offset * the offset of the instruction to which the frame corresponds. * @param nLocal @@ -1942,7 +1965,7 @@ private void writeFrame() { * StackMapTableAttribute. This method converts types from the format used * in {@link Label} to the format used in StackMapTable attributes. In * particular, it converts type table indexes to constant pool indexes. - * + * * @param start * index of the first type in {@link #frame} to write. * @param end @@ -2023,7 +2046,7 @@ private void writeFrameType(final Object type) { /** * Returns the size of the bytecode of this method. - * + * * @return the size of the bytecode of this method. */ final int getSize() { @@ -2032,7 +2055,7 @@ final int getSize() { } int size = 8; if (code.length > 0) { - if (code.length > 65536) { + if (code.length > 65535) { throw new RuntimeException("Method code too large!"); } cw.newUTF8("Code"); @@ -2054,11 +2077,11 @@ final int getSize() { cw.newUTF8(zip ? "StackMapTable" : "StackMap"); size += 8 + stackMap.length; } - if (ClassReader.ANNOTATIONS && ctanns != null) { + if (ctanns != null) { cw.newUTF8("RuntimeVisibleTypeAnnotations"); size += 8 + ctanns.getSize(); } - if (ClassReader.ANNOTATIONS && ictanns != null) { + if (ictanns != null) { cw.newUTF8("RuntimeInvisibleTypeAnnotations"); size += 8 + ictanns.getSize(); } @@ -2082,7 +2105,7 @@ final int getSize() { cw.newUTF8("Deprecated"); size += 6; } - if (ClassReader.SIGNATURES && signature != null) { + if (signature != null) { cw.newUTF8("Signature"); cw.newUTF8(signature); size += 8; @@ -2091,34 +2114,34 @@ final int getSize() { cw.newUTF8("MethodParameters"); size += 7 + methodParameters.length; } - if (ClassReader.ANNOTATIONS && annd != null) { + if (annd != null) { cw.newUTF8("AnnotationDefault"); size += 6 + annd.length; } - if (ClassReader.ANNOTATIONS && anns != null) { + if (anns != null) { cw.newUTF8("RuntimeVisibleAnnotations"); size += 8 + anns.getSize(); } - if (ClassReader.ANNOTATIONS && ianns != null) { + if (ianns != null) { cw.newUTF8("RuntimeInvisibleAnnotations"); size += 8 + ianns.getSize(); } - if (ClassReader.ANNOTATIONS && tanns != null) { + if (tanns != null) { cw.newUTF8("RuntimeVisibleTypeAnnotations"); size += 8 + tanns.getSize(); } - if (ClassReader.ANNOTATIONS && itanns != null) { + if (itanns != null) { cw.newUTF8("RuntimeInvisibleTypeAnnotations"); size += 8 + itanns.getSize(); } - if (ClassReader.ANNOTATIONS && panns != null) { + if (panns != null) { cw.newUTF8("RuntimeVisibleParameterAnnotations"); size += 7 + 2 * (panns.length - synthetics); for (int i = panns.length - 1; i >= synthetics; --i) { size += panns[i] == null ? 0 : panns[i].getSize(); } } - if (ClassReader.ANNOTATIONS && ipanns != null) { + if (ipanns != null) { cw.newUTF8("RuntimeInvisibleParameterAnnotations"); size += 7 + 2 * (ipanns.length - synthetics); for (int i = ipanns.length - 1; i >= synthetics; --i) { @@ -2133,7 +2156,7 @@ final int getSize() { /** * Puts the bytecode of this method in the given byte vector. - * + * * @param out * the byte vector into which the bytecode of this method must be * copied. @@ -2164,31 +2187,31 @@ final void put(final ByteVector out) { if ((access & Opcodes.ACC_DEPRECATED) != 0) { ++attributeCount; } - if (ClassReader.SIGNATURES && signature != null) { + if (signature != null) { ++attributeCount; } if (methodParameters != null) { ++attributeCount; } - if (ClassReader.ANNOTATIONS && annd != null) { + if (annd != null) { ++attributeCount; } - if (ClassReader.ANNOTATIONS && anns != null) { + if (anns != null) { ++attributeCount; } - if (ClassReader.ANNOTATIONS && ianns != null) { + if (ianns != null) { ++attributeCount; } - if (ClassReader.ANNOTATIONS && tanns != null) { + if (tanns != null) { ++attributeCount; } - if (ClassReader.ANNOTATIONS && itanns != null) { + if (itanns != null) { ++attributeCount; } - if (ClassReader.ANNOTATIONS && panns != null) { + if (panns != null) { ++attributeCount; } - if (ClassReader.ANNOTATIONS && ipanns != null) { + if (ipanns != null) { ++attributeCount; } if (attrs != null) { @@ -2209,10 +2232,10 @@ final void put(final ByteVector out) { if (stackMap != null) { size += 8 + stackMap.length; } - if (ClassReader.ANNOTATIONS && ctanns != null) { + if (ctanns != null) { size += 8 + ctanns.getSize(); } - if (ClassReader.ANNOTATIONS && ictanns != null) { + if (ictanns != null) { size += 8 + ictanns.getSize(); } if (cattrs != null) { @@ -2244,10 +2267,10 @@ final void put(final ByteVector out) { if (stackMap != null) { ++attributeCount; } - if (ClassReader.ANNOTATIONS && ctanns != null) { + if (ctanns != null) { ++attributeCount; } - if (ClassReader.ANNOTATIONS && ictanns != null) { + if (ictanns != null) { ++attributeCount; } if (cattrs != null) { @@ -2275,11 +2298,11 @@ final void put(final ByteVector out) { out.putInt(stackMap.length + 2).putShort(frameCount); out.putByteArray(stackMap.data, 0, stackMap.length); } - if (ClassReader.ANNOTATIONS && ctanns != null) { + if (ctanns != null) { out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations")); ctanns.put(out); } - if (ClassReader.ANNOTATIONS && ictanns != null) { + if (ictanns != null) { out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations")); ictanns.put(out); } @@ -2304,7 +2327,7 @@ final void put(final ByteVector out) { if ((access & Opcodes.ACC_DEPRECATED) != 0) { out.putShort(cw.newUTF8("Deprecated")).putInt(0); } - if (ClassReader.SIGNATURES && signature != null) { + if (signature != null) { out.putShort(cw.newUTF8("Signature")).putInt(2) .putShort(cw.newUTF8(signature)); } @@ -2314,32 +2337,32 @@ final void put(final ByteVector out) { methodParametersCount); out.putByteArray(methodParameters.data, 0, methodParameters.length); } - if (ClassReader.ANNOTATIONS && annd != null) { + if (annd != null) { out.putShort(cw.newUTF8("AnnotationDefault")); out.putInt(annd.length); out.putByteArray(annd.data, 0, annd.length); } - if (ClassReader.ANNOTATIONS && anns != null) { + if (anns != null) { out.putShort(cw.newUTF8("RuntimeVisibleAnnotations")); anns.put(out); } - if (ClassReader.ANNOTATIONS && ianns != null) { + if (ianns != null) { out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations")); ianns.put(out); } - if (ClassReader.ANNOTATIONS && tanns != null) { + if (tanns != null) { out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations")); tanns.put(out); } - if (ClassReader.ANNOTATIONS && itanns != null) { + if (itanns != null) { out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations")); itanns.put(out); } - if (ClassReader.ANNOTATIONS && panns != null) { + if (panns != null) { out.putShort(cw.newUTF8("RuntimeVisibleParameterAnnotations")); AnnotationWriter.put(panns, synthetics, out); } - if (ClassReader.ANNOTATIONS && ipanns != null) { + if (ipanns != null) { out.putShort(cw.newUTF8("RuntimeInvisibleParameterAnnotations")); AnnotationWriter.put(ipanns, synthetics, out); } @@ -2347,567 +2370,4 @@ final void put(final ByteVector out) { attrs.put(cw, null, 0, -1, -1, out); } } - - // ------------------------------------------------------------------------ - // Utility methods: instruction resizing (used to handle GOTO_W and JSR_W) - // ------------------------------------------------------------------------ - - /** - * Resizes and replaces the temporary instructions inserted by - * {@link Label#resolve} for wide forward jumps, while keeping jump offsets - * and instruction addresses consistent. This may require to resize other - * existing instructions, or even to introduce new instructions: for - * example, increasing the size of an instruction by 2 at the middle of a - * method can increases the offset of an IFEQ instruction from 32766 to - * 32768, in which case IFEQ 32766 must be replaced with IFNEQ 8 GOTO_W - * 32765. This, in turn, may require to increase the size of another jump - * instruction, and so on... All these operations are handled automatically - * by this method. - *

- * This method must be called after all the method that is being built - * has been visited. In particular, the {@link Label Label} objects used - * to construct the method are no longer valid after this method has been - * called. - */ - private void resizeInstructions() { - byte[] b = code.data; // bytecode of the method - int u, v, label; // indexes in b - int i, j; // loop indexes - /* - * 1st step: As explained above, resizing an instruction may require to - * resize another one, which may require to resize yet another one, and - * so on. The first step of the algorithm consists in finding all the - * instructions that need to be resized, without modifying the code. - * This is done by the following "fix point" algorithm: - * - * Parse the code to find the jump instructions whose offset will need - * more than 2 bytes to be stored (the future offset is computed from - * the current offset and from the number of bytes that will be inserted - * or removed between the source and target instructions). For each such - * instruction, adds an entry in (a copy of) the indexes and sizes - * arrays (if this has not already been done in a previous iteration!). - * - * If at least one entry has been added during the previous step, go - * back to the beginning, otherwise stop. - * - * In fact the real algorithm is complicated by the fact that the size - * of TABLESWITCH and LOOKUPSWITCH instructions depends on their - * position in the bytecode (because of padding). In order to ensure the - * convergence of the algorithm, the number of bytes to be added or - * removed from these instructions is over estimated during the previous - * loop, and computed exactly only after the loop is finished (this - * requires another pass to parse the bytecode of the method). - */ - int[] allIndexes = new int[0]; // copy of indexes - int[] allSizes = new int[0]; // copy of sizes - boolean[] resize; // instructions to be resized - int newOffset; // future offset of a jump instruction - - resize = new boolean[code.length]; - - // 3 = loop again, 2 = loop ended, 1 = last pass, 0 = done - int state = 3; - do { - if (state == 3) { - state = 2; - } - u = 0; - while (u < b.length) { - int opcode = b[u] & 0xFF; // opcode of current instruction - int insert = 0; // bytes to be added after this instruction - - switch (ClassWriter.TYPE[opcode]) { - case ClassWriter.NOARG_INSN: - case ClassWriter.IMPLVAR_INSN: - u += 1; - break; - case ClassWriter.LABEL_INSN: - if (opcode > 201) { - // converts temporary opcodes 202 to 217, 218 and - // 219 to IFEQ ... JSR (inclusive), IFNULL and - // IFNONNULL - opcode = opcode < 218 ? opcode - 49 : opcode - 20; - label = u + readUnsignedShort(b, u + 1); - } else { - label = u + readShort(b, u + 1); - } - newOffset = getNewOffset(allIndexes, allSizes, u, label); - if (newOffset < Short.MIN_VALUE - || newOffset > Short.MAX_VALUE) { - if (!resize[u]) { - if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) { - // two additional bytes will be required to - // replace this GOTO or JSR instruction with - // a GOTO_W or a JSR_W - insert = 2; - } else { - // five additional bytes will be required to - // replace this IFxxx instruction with - // IFNOTxxx GOTO_W , where IFNOTxxx - // is the "opposite" opcode of IFxxx (i.e., - // IFNE for IFEQ) and where designates - // the instruction just after the GOTO_W. - insert = 5; - } - resize[u] = true; - } - } - u += 3; - break; - case ClassWriter.LABELW_INSN: - u += 5; - break; - case ClassWriter.TABL_INSN: - if (state == 1) { - // true number of bytes to be added (or removed) - // from this instruction = (future number of padding - // bytes - current number of padding byte) - - // previously over estimated variation = - // = ((3 - newOffset%4) - (3 - u%4)) - u%4 - // = (-newOffset%4 + u%4) - u%4 - // = -(newOffset & 3) - newOffset = getNewOffset(allIndexes, allSizes, 0, u); - insert = -(newOffset & 3); - } else if (!resize[u]) { - // over estimation of the number of bytes to be - // added to this instruction = 3 - current number - // of padding bytes = 3 - (3 - u%4) = u%4 = u & 3 - insert = u & 3; - resize[u] = true; - } - // skips instruction - u = u + 4 - (u & 3); - u += 4 * (readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12; - break; - case ClassWriter.LOOK_INSN: - if (state == 1) { - // like TABL_INSN - newOffset = getNewOffset(allIndexes, allSizes, 0, u); - insert = -(newOffset & 3); - } else if (!resize[u]) { - // like TABL_INSN - insert = u & 3; - resize[u] = true; - } - // skips instruction - u = u + 4 - (u & 3); - u += 8 * readInt(b, u + 4) + 8; - break; - case ClassWriter.WIDE_INSN: - opcode = b[u + 1] & 0xFF; - if (opcode == Opcodes.IINC) { - u += 6; - } else { - u += 4; - } - break; - case ClassWriter.VAR_INSN: - case ClassWriter.SBYTE_INSN: - case ClassWriter.LDC_INSN: - u += 2; - break; - case ClassWriter.SHORT_INSN: - case ClassWriter.LDCW_INSN: - case ClassWriter.FIELDORMETH_INSN: - case ClassWriter.TYPE_INSN: - case ClassWriter.IINC_INSN: - u += 3; - break; - case ClassWriter.ITFMETH_INSN: - case ClassWriter.INDYMETH_INSN: - u += 5; - break; - // case ClassWriter.MANA_INSN: - default: - u += 4; - break; - } - if (insert != 0) { - // adds a new (u, insert) entry in the allIndexes and - // allSizes arrays - int[] newIndexes = new int[allIndexes.length + 1]; - int[] newSizes = new int[allSizes.length + 1]; - System.arraycopy(allIndexes, 0, newIndexes, 0, - allIndexes.length); - System.arraycopy(allSizes, 0, newSizes, 0, allSizes.length); - newIndexes[allIndexes.length] = u; - newSizes[allSizes.length] = insert; - allIndexes = newIndexes; - allSizes = newSizes; - if (insert > 0) { - state = 3; - } - } - } - if (state < 3) { - --state; - } - } while (state != 0); - - // 2nd step: - // copies the bytecode of the method into a new bytevector, updates the - // offsets, and inserts (or removes) bytes as requested. - - ByteVector newCode = new ByteVector(code.length); - - u = 0; - while (u < code.length) { - int opcode = b[u] & 0xFF; - switch (ClassWriter.TYPE[opcode]) { - case ClassWriter.NOARG_INSN: - case ClassWriter.IMPLVAR_INSN: - newCode.putByte(opcode); - u += 1; - break; - case ClassWriter.LABEL_INSN: - if (opcode > 201) { - // changes temporary opcodes 202 to 217 (inclusive), 218 - // and 219 to IFEQ ... JSR (inclusive), IFNULL and - // IFNONNULL - opcode = opcode < 218 ? opcode - 49 : opcode - 20; - label = u + readUnsignedShort(b, u + 1); - } else { - label = u + readShort(b, u + 1); - } - newOffset = getNewOffset(allIndexes, allSizes, u, label); - if (resize[u]) { - // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx - // with IFNOTxxx GOTO_W , where IFNOTxxx is - // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) - // and where designates the instruction just after - // the GOTO_W. - if (opcode == Opcodes.GOTO) { - newCode.putByte(200); // GOTO_W - } else if (opcode == Opcodes.JSR) { - newCode.putByte(201); // JSR_W - } else { - newCode.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1 - : opcode ^ 1); - newCode.putShort(8); // jump offset - newCode.putByte(200); // GOTO_W - // newOffset now computed from start of GOTO_W - newOffset -= 3; - } - newCode.putInt(newOffset); - } else { - newCode.putByte(opcode); - newCode.putShort(newOffset); - } - u += 3; - break; - case ClassWriter.LABELW_INSN: - label = u + readInt(b, u + 1); - newOffset = getNewOffset(allIndexes, allSizes, u, label); - newCode.putByte(opcode); - newCode.putInt(newOffset); - u += 5; - break; - case ClassWriter.TABL_INSN: - // skips 0 to 3 padding bytes - v = u; - u = u + 4 - (v & 3); - // reads and copies instruction - newCode.putByte(Opcodes.TABLESWITCH); - newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4); - label = v + readInt(b, u); - u += 4; - newOffset = getNewOffset(allIndexes, allSizes, v, label); - newCode.putInt(newOffset); - j = readInt(b, u); - u += 4; - newCode.putInt(j); - j = readInt(b, u) - j + 1; - u += 4; - newCode.putInt(readInt(b, u - 4)); - for (; j > 0; --j) { - label = v + readInt(b, u); - u += 4; - newOffset = getNewOffset(allIndexes, allSizes, v, label); - newCode.putInt(newOffset); - } - break; - case ClassWriter.LOOK_INSN: - // skips 0 to 3 padding bytes - v = u; - u = u + 4 - (v & 3); - // reads and copies instruction - newCode.putByte(Opcodes.LOOKUPSWITCH); - newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4); - label = v + readInt(b, u); - u += 4; - newOffset = getNewOffset(allIndexes, allSizes, v, label); - newCode.putInt(newOffset); - j = readInt(b, u); - u += 4; - newCode.putInt(j); - for (; j > 0; --j) { - newCode.putInt(readInt(b, u)); - u += 4; - label = v + readInt(b, u); - u += 4; - newOffset = getNewOffset(allIndexes, allSizes, v, label); - newCode.putInt(newOffset); - } - break; - case ClassWriter.WIDE_INSN: - opcode = b[u + 1] & 0xFF; - if (opcode == Opcodes.IINC) { - newCode.putByteArray(b, u, 6); - u += 6; - } else { - newCode.putByteArray(b, u, 4); - u += 4; - } - break; - case ClassWriter.VAR_INSN: - case ClassWriter.SBYTE_INSN: - case ClassWriter.LDC_INSN: - newCode.putByteArray(b, u, 2); - u += 2; - break; - case ClassWriter.SHORT_INSN: - case ClassWriter.LDCW_INSN: - case ClassWriter.FIELDORMETH_INSN: - case ClassWriter.TYPE_INSN: - case ClassWriter.IINC_INSN: - newCode.putByteArray(b, u, 3); - u += 3; - break; - case ClassWriter.ITFMETH_INSN: - case ClassWriter.INDYMETH_INSN: - newCode.putByteArray(b, u, 5); - u += 5; - break; - // case MANA_INSN: - default: - newCode.putByteArray(b, u, 4); - u += 4; - break; - } - } - - // updates the stack map frame labels - if (compute == FRAMES) { - Label l = labels; - while (l != null) { - /* - * Detects the labels that are just after an IF instruction that - * has been resized with the IFNOT GOTO_W pattern. These labels - * are now the target of a jump instruction (the IFNOT - * instruction). Note that we need the original label position - * here. getNewOffset must therefore never have been called for - * this label. - */ - u = l.position - 3; - if (u >= 0 && resize[u]) { - l.status |= Label.TARGET; - } - getNewOffset(allIndexes, allSizes, l); - l = l.successor; - } - // Update the offsets in the uninitialized types - for (i = 0; i < cw.typeTable.length; ++i) { - Item item = cw.typeTable[i]; - if (item != null && item.type == ClassWriter.TYPE_UNINIT) { - item.intVal = getNewOffset(allIndexes, allSizes, 0, - item.intVal); - } - } - // The stack map frames are not serialized yet, so we don't need - // to update them. They will be serialized in visitMaxs. - } else if (frameCount > 0) { - /* - * Resizing an existing stack map frame table is really hard. Not - * only the table must be parsed to update the offets, but new - * frames may be needed for jump instructions that were inserted by - * this method. And updating the offsets or inserting frames can - * change the format of the following frames, in case of packed - * frames. In practice the whole table must be recomputed. For this - * the frames are marked as potentially invalid. This will cause the - * whole class to be reread and rewritten with the COMPUTE_FRAMES - * option (see the ClassWriter.toByteArray method). This is not very - * efficient but is much easier and requires much less code than any - * other method I can think of. - */ - cw.invalidFrames = true; - } - // updates the exception handler block labels - Handler h = firstHandler; - while (h != null) { - getNewOffset(allIndexes, allSizes, h.start); - getNewOffset(allIndexes, allSizes, h.end); - getNewOffset(allIndexes, allSizes, h.handler); - h = h.next; - } - // updates the instructions addresses in the - // local var and line number tables - for (i = 0; i < 2; ++i) { - ByteVector bv = i == 0 ? localVar : localVarType; - if (bv != null) { - b = bv.data; - u = 0; - while (u < bv.length) { - label = readUnsignedShort(b, u); - newOffset = getNewOffset(allIndexes, allSizes, 0, label); - writeShort(b, u, newOffset); - label += readUnsignedShort(b, u + 2); - newOffset = getNewOffset(allIndexes, allSizes, 0, label) - - newOffset; - writeShort(b, u + 2, newOffset); - u += 10; - } - } - } - if (lineNumber != null) { - b = lineNumber.data; - u = 0; - while (u < lineNumber.length) { - writeShort( - b, - u, - getNewOffset(allIndexes, allSizes, 0, - readUnsignedShort(b, u))); - u += 4; - } - } - // updates the labels of the other attributes - Attribute attr = cattrs; - while (attr != null) { - Label[] labels = attr.getLabels(); - if (labels != null) { - for (i = labels.length - 1; i >= 0; --i) { - getNewOffset(allIndexes, allSizes, labels[i]); - } - } - attr = attr.next; - } - - // replaces old bytecodes with new ones - code = newCode; - } - - /** - * Reads an unsigned short value in the given byte array. - * - * @param b - * a byte array. - * @param index - * the start index of the value to be read. - * @return the read value. - */ - static int readUnsignedShort(final byte[] b, final int index) { - return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF); - } - - /** - * Reads a signed short value in the given byte array. - * - * @param b - * a byte array. - * @param index - * the start index of the value to be read. - * @return the read value. - */ - static short readShort(final byte[] b, final int index) { - return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF)); - } - - /** - * Reads a signed int value in the given byte array. - * - * @param b - * a byte array. - * @param index - * the start index of the value to be read. - * @return the read value. - */ - static int readInt(final byte[] b, final int index) { - return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16) - | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF); - } - - /** - * Writes a short value in the given byte array. - * - * @param b - * a byte array. - * @param index - * where the first byte of the short value must be written. - * @param s - * the value to be written in the given byte array. - */ - static void writeShort(final byte[] b, final int index, final int s) { - b[index] = (byte) (s >>> 8); - b[index + 1] = (byte) s; - } - - /** - * Computes the future value of a bytecode offset. - *

- * Note: it is possible to have several entries for the same instruction in - * the indexes and sizes: two entries (index=a,size=b) and - * (index=a,size=b') are equivalent to a single entry (index=a,size=b+b'). - * - * @param indexes - * current positions of the instructions to be resized. Each - * instruction must be designated by the index of its last - * byte, plus one (or, in other words, by the index of the - * first byte of the next instruction). - * @param sizes - * the number of bytes to be added to the above - * instructions. More precisely, for each i < len, - * sizes[i] bytes will be added at the end of the - * instruction designated by indexes[i] or, if - * sizes[i] is negative, the last | - * sizes[i]| bytes of the instruction will be removed - * (the instruction size must not become negative or - * null). - * @param begin - * index of the first byte of the source instruction. - * @param end - * index of the first byte of the target instruction. - * @return the future value of the given bytecode offset. - */ - static int getNewOffset(final int[] indexes, final int[] sizes, - final int begin, final int end) { - int offset = end - begin; - for (int i = 0; i < indexes.length; ++i) { - if (begin < indexes[i] && indexes[i] <= end) { - // forward jump - offset += sizes[i]; - } else if (end < indexes[i] && indexes[i] <= begin) { - // backward jump - offset -= sizes[i]; - } - } - return offset; - } - - /** - * Updates the offset of the given label. - * - * @param indexes - * current positions of the instructions to be resized. Each - * instruction must be designated by the index of its last - * byte, plus one (or, in other words, by the index of the - * first byte of the next instruction). - * @param sizes - * the number of bytes to be added to the above - * instructions. More precisely, for each i < len, - * sizes[i] bytes will be added at the end of the - * instruction designated by indexes[i] or, if - * sizes[i] is negative, the last | - * sizes[i]| bytes of the instruction will be removed - * (the instruction size must not become negative or - * null). - * @param label - * the label whose offset must be updated. - */ - static void getNewOffset(final int[] indexes, final int[] sizes, - final Label label) { - if ((label.status & Label.RESIZED) == 0) { - label.position = getNewOffset(indexes, sizes, 0, label.position); - label.status |= Label.RESIZED; - } - } } diff --git a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/ModuleVisitor.java b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/ModuleVisitor.java new file mode 100644 index 000000000..670e61b9c --- /dev/null +++ b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/ModuleVisitor.java @@ -0,0 +1,190 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package jersey.repackaged.org.objectweb.asm; + +/** + * A visitor to visit a Java module. The methods of this class must be called in + * the following order: visitMainClass | ( visitPackage | + * visitRequire | visitExport | visitOpen | + * visitUse | visitProvide )* visitEnd. + * + * The methods {@link #visitRequire(String, int, String)}, {@link #visitExport(String, int, String...)}, + * {@link #visitOpen(String, int, String...)} and {@link #visitPackage(String)} + * take as parameter a package name or a module name. Unlike the other names which are internal names + * (names separated by slash), module and package names are qualified names (names separated by dot). + * + * @author Remi Forax + */ +public abstract class ModuleVisitor { + /** + * The ASM API version implemented by this visitor. The value of this field + * must be {@link Opcodes#ASM6}. + */ + protected final int api; + + /** + * The module visitor to which this visitor must delegate method calls. May + * be null. + */ + protected ModuleVisitor mv; + + /** + * Constructs a new {@link ModuleVisitor}. + * + * @param api + * the ASM API version implemented by this visitor. Must be {@link Opcodes#ASM6}. + */ + public ModuleVisitor(final int api) { + this(api, null); + } + + /** + * Constructs a new {@link ModuleVisitor}. + * + * @param api + * the ASM API version implemented by this visitor. Must be {@link Opcodes#ASM6}. + * @param mv + * the module visitor to which this visitor must delegate method + * calls. May be null. + */ + public ModuleVisitor(final int api, final ModuleVisitor mv) { + if (api != Opcodes.ASM6) { + throw new IllegalArgumentException(); + } + this.api = api; + this.mv = mv; + } + + /** + * Visit the main class of the current module. + * + * @param mainClass the internal name of the main class of the current module. + */ + public void visitMainClass(String mainClass) { + if (mv != null) { + mv.visitMainClass(mainClass); + } + } + + /** + * Visit a package of the current module. + * + * @param packaze the qualified name of a package. + */ + public void visitPackage(String packaze) { + if (mv != null) { + mv.visitPackage(packaze); + } + } + + /** + * Visits a dependence of the current module. + * + * @param module the qualified name of the dependence. + * @param access the access flag of the dependence among + * ACC_TRANSITIVE, ACC_STATIC_PHASE, ACC_SYNTHETIC + * and ACC_MANDATED. + * @param version the module version at compile time or null. + */ + public void visitRequire(String module, int access, String version) { + if (mv != null) { + mv.visitRequire(module, access, version); + } + } + + /** + * Visit an exported package of the current module. + * + * @param packaze the qualified name of the exported package. + * @param access the access flag of the exported package, + * valid values are among {@code ACC_SYNTHETIC} and + * {@code ACC_MANDATED}. + * @param modules the qualified names of the modules that can access to + * the public classes of the exported package or + * null. + */ + public void visitExport(String packaze, int access, String... modules) { + if (mv != null) { + mv.visitExport(packaze, access, modules); + } + } + + /** + * Visit an open package of the current module. + * + * @param packaze the qualified name of the opened package. + * @param access the access flag of the opened package, + * valid values are among {@code ACC_SYNTHETIC} and + * {@code ACC_MANDATED}. + * @param modules the qualified names of the modules that can use deep + * reflection to the classes of the open package or + * null. + */ + public void visitOpen(String packaze, int access, String... modules) { + if (mv != null) { + mv.visitOpen(packaze, access, modules); + } + } + + /** + * Visit a service used by the current module. + * The name must be the internal name of an interface or a class. + * + * @param service the internal name of the service. + */ + public void visitUse(String service) { + if (mv != null) { + mv.visitUse(service); + } + } + + /** + * Visit an implementation of a service. + * + * @param service the internal name of the service + * @param providers the internal names of the implementations + * of the service (there is at least one provider). + */ + public void visitProvide(String service, String... providers) { + if (mv != null) { + mv.visitProvide(service, providers); + } + } + + /** + * Visits the end of the module. This method, which is the last one to be + * called, is used to inform the visitor that everything have been visited. + */ + public void visitEnd() { + if (mv != null) { + mv.visitEnd(); + } + } +} diff --git a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/ModuleWriter.java b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/ModuleWriter.java new file mode 100644 index 000000000..0c38c4bda --- /dev/null +++ b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/ModuleWriter.java @@ -0,0 +1,293 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2011 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +package jersey.repackaged.org.objectweb.asm; + +/** + * @author Remi Forax + */ +final class ModuleWriter extends ModuleVisitor { + /** + * The class writer to which this Module attribute must be added. + */ + private final ClassWriter cw; + + /** + * size in byte of the Module attribute. + */ + int size; + + /** + * Number of attributes associated with the current module + * (Version, ConcealPackages, etc) + */ + int attributeCount; + + /** + * Size in bytes of the attributes associated with the current module + */ + int attributesSize; + + /** + * module name index in the constant pool + */ + private final int name; + + /** + * module access flags + */ + private final int access; + + /** + * module version index in the constant pool or 0 + */ + private final int version; + + /** + * module main class index in the constant pool or 0 + */ + private int mainClass; + + /** + * number of packages + */ + private int packageCount; + + /** + * The packages in bytecode form. This byte vector only contains + * the items themselves, the number of items is store in packageCount + */ + private ByteVector packages; + + /** + * number of requires items + */ + private int requireCount; + + /** + * The requires items in bytecode form. This byte vector only contains + * the items themselves, the number of items is store in requireCount + */ + private ByteVector requires; + + /** + * number of exports items + */ + private int exportCount; + + /** + * The exports items in bytecode form. This byte vector only contains + * the items themselves, the number of items is store in exportCount + */ + private ByteVector exports; + + /** + * number of opens items + */ + private int openCount; + + /** + * The opens items in bytecode form. This byte vector only contains + * the items themselves, the number of items is store in openCount + */ + private ByteVector opens; + + /** + * number of uses items + */ + private int useCount; + + /** + * The uses items in bytecode form. This byte vector only contains + * the items themselves, the number of items is store in useCount + */ + private ByteVector uses; + + /** + * number of provides items + */ + private int provideCount; + + /** + * The uses provides in bytecode form. This byte vector only contains + * the items themselves, the number of items is store in provideCount + */ + private ByteVector provides; + + ModuleWriter(final ClassWriter cw, final int name, + final int access, final int version) { + super(Opcodes.ASM6); + this.cw = cw; + this.size = 16; // name + access + version + 5 counts + this.name = name; + this.access = access; + this.version = version; + } + + @Override + public void visitMainClass(String mainClass) { + if (this.mainClass == 0) { // protect against several calls to visitMainClass + cw.newUTF8("ModuleMainClass"); + attributeCount++; + attributesSize += 8; + } + this.mainClass = cw.newClass(mainClass); + } + + @Override + public void visitPackage(String packaze) { + if (packages == null) { + // protect against several calls to visitPackage + cw.newUTF8("ModulePackages"); + packages = new ByteVector(); + attributeCount++; + attributesSize += 8; + } + packages.putShort(cw.newPackage(packaze)); + packageCount++; + attributesSize += 2; + } + + @Override + public void visitRequire(String module, int access, String version) { + if (requires == null) { + requires = new ByteVector(); + } + requires.putShort(cw.newModule(module)) + .putShort(access) + .putShort(version == null? 0: cw.newUTF8(version)); + requireCount++; + size += 6; + } + + @Override + public void visitExport(String packaze, int access, String... modules) { + if (exports == null) { + exports = new ByteVector(); + } + exports.putShort(cw.newPackage(packaze)).putShort(access); + if (modules == null) { + exports.putShort(0); + size += 6; + } else { + exports.putShort(modules.length); + for(String module: modules) { + exports.putShort(cw.newModule(module)); + } + size += 6 + 2 * modules.length; + } + exportCount++; + } + + @Override + public void visitOpen(String packaze, int access, String... modules) { + if (opens == null) { + opens = new ByteVector(); + } + opens.putShort(cw.newPackage(packaze)).putShort(access); + if (modules == null) { + opens.putShort(0); + size += 6; + } else { + opens.putShort(modules.length); + for(String module: modules) { + opens.putShort(cw.newModule(module)); + } + size += 6 + 2 * modules.length; + } + openCount++; + } + + @Override + public void visitUse(String service) { + if (uses == null) { + uses = new ByteVector(); + } + uses.putShort(cw.newClass(service)); + useCount++; + size += 2; + } + + @Override + public void visitProvide(String service, String... providers) { + if (provides == null) { + provides = new ByteVector(); + } + provides.putShort(cw.newClass(service)); + provides.putShort(providers.length); + for(String provider: providers) { + provides.putShort(cw.newClass(provider)); + } + provideCount++; + size += 4 + 2 * providers.length; + } + + @Override + public void visitEnd() { + // empty + } + + void putAttributes(ByteVector out) { + if (mainClass != 0) { + out.putShort(cw.newUTF8("ModuleMainClass")).putInt(2).putShort(mainClass); + } + if (packages != null) { + out.putShort(cw.newUTF8("ModulePackages")) + .putInt(2 + 2 * packageCount) + .putShort(packageCount) + .putByteArray(packages.data, 0, packages.length); + } + } + + void put(ByteVector out) { + out.putInt(size); + out.putShort(name).putShort(access).putShort(version); + out.putShort(requireCount); + if (requires != null) { + out.putByteArray(requires.data, 0, requires.length); + } + out.putShort(exportCount); + if (exports != null) { + out.putByteArray(exports.data, 0, exports.length); + } + out.putShort(openCount); + if (opens != null) { + out.putByteArray(opens.data, 0, opens.length); + } + out.putShort(useCount); + if (uses != null) { + out.putByteArray(uses.data, 0, uses.length); + } + out.putShort(provideCount); + if (provides != null) { + out.putByteArray(provides.data, 0, provides.length); + } + } +} diff --git a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Opcodes.java b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Opcodes.java index 67e8e8d67..9b0722d60 100644 --- a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Opcodes.java +++ b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Opcodes.java @@ -37,7 +37,7 @@ * opcodes are therefore not defined in this interface. Likewise for LDC, * automatically replaced by LDC_W or LDC2_W when necessary, WIDE, GOTO_W and * JSR_W. - * + * * @author Eric Bruneton * @author Eugene Kuleshov */ @@ -47,6 +47,7 @@ public interface Opcodes { int ASM4 = 4 << 16 | 0 << 8 | 0; int ASM5 = 5 << 16 | 0 << 8 | 0; + int ASM6 = 6 << 16 | 0 << 8 | 0; // versions @@ -58,6 +59,7 @@ public interface Opcodes { int V1_6 = 0 << 16 | 50; int V1_7 = 0 << 16 | 51; int V1_8 = 0 << 16 | 52; + int V9 = 0 << 16 | 53; // access flags @@ -68,18 +70,23 @@ public interface Opcodes { int ACC_FINAL = 0x0010; // class, field, method, parameter int ACC_SUPER = 0x0020; // class int ACC_SYNCHRONIZED = 0x0020; // method + int ACC_OPEN = 0x0020; // module + int ACC_TRANSITIVE = 0x0020; // module requires int ACC_VOLATILE = 0x0040; // field int ACC_BRIDGE = 0x0040; // method + int ACC_STATIC_PHASE = 0x0040; // module requires int ACC_VARARGS = 0x0080; // method int ACC_TRANSIENT = 0x0080; // field int ACC_NATIVE = 0x0100; // method int ACC_INTERFACE = 0x0200; // class int ACC_ABSTRACT = 0x0400; // class, method int ACC_STRICT = 0x0800; // method - int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter + int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter, module * int ACC_ANNOTATION = 0x2000; // class int ACC_ENUM = 0x4000; // class(?) field inner - int ACC_MANDATED = 0x8000; // parameter + int ACC_MANDATED = 0x8000; // parameter, module, module * + int ACC_MODULE = 0x8000; // class + // ASM specific pseudo access flags @@ -146,13 +153,17 @@ public interface Opcodes { */ int F_SAME1 = 4; - Integer TOP = new Integer(0); - Integer INTEGER = new Integer(1); - Integer FLOAT = new Integer(2); - Integer DOUBLE = new Integer(3); - Integer LONG = new Integer(4); - Integer NULL = new Integer(5); - Integer UNINITIALIZED_THIS = new Integer(6); + // Do not try to change the following code to use auto-boxing, + // these values are compared by reference and not by value + // The constructor of Integer was deprecated in 9 + // but we are stuck with it by backward compatibility + @SuppressWarnings("deprecation") Integer TOP = new Integer(0); + @SuppressWarnings("deprecation") Integer INTEGER = new Integer(1); + @SuppressWarnings("deprecation") Integer FLOAT = new Integer(2); + @SuppressWarnings("deprecation") Integer DOUBLE = new Integer(3); + @SuppressWarnings("deprecation") Integer LONG = new Integer(4); + @SuppressWarnings("deprecation") Integer NULL = new Integer(5); + @SuppressWarnings("deprecation") Integer UNINITIALIZED_THIS = new Integer(6); // opcodes // visit method (- = idem) diff --git a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Type.java b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Type.java index be809a5af..d60e91d58 100644 --- a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Type.java +++ b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/Type.java @@ -35,7 +35,7 @@ /** * A Java field or method type. This class can be used to make it easier to * manipulate type and method descriptors. - * + * * @author Eric Bruneton * @author Chris Nokleberg */ @@ -189,7 +189,7 @@ public class Type { /** * Constructs a reference type. - * + * * @param sort * the sort of the reference type to be constructed. * @param buf @@ -208,7 +208,7 @@ private Type(final int sort, final char[] buf, final int off, final int len) { /** * Returns the Java type corresponding to the given type descriptor. - * + * * @param typeDescriptor * a field or method type descriptor. * @return the Java type corresponding to the given type descriptor. @@ -219,7 +219,7 @@ public static Type getType(final String typeDescriptor) { /** * Returns the Java type corresponding to the given internal name. - * + * * @param internalName * an internal name. * @return the Java type corresponding to the given internal name. @@ -232,7 +232,7 @@ public static Type getObjectType(final String internalName) { /** * Returns the Java type corresponding to the given method descriptor. * Equivalent to Type.getType(methodDescriptor). - * + * * @param methodDescriptor * a method descriptor. * @return the Java type corresponding to the given method descriptor. @@ -244,7 +244,7 @@ public static Type getMethodType(final String methodDescriptor) { /** * Returns the Java method type corresponding to the given argument and * return types. - * + * * @param returnType * the return type of the method. * @param argumentTypes @@ -259,7 +259,7 @@ public static Type getMethodType(final Type returnType, /** * Returns the Java type corresponding to the given class. - * + * * @param c * a class. * @return the Java type corresponding to the given class. @@ -292,7 +292,7 @@ public static Type getType(final Class c) { /** * Returns the Java method type corresponding to the given constructor. - * + * * @param c * a {@link Constructor Constructor} object. * @return the Java method type corresponding to the given constructor. @@ -303,7 +303,7 @@ public static Type getType(final Constructor c) { /** * Returns the Java method type corresponding to the given method. - * + * * @param m * a {@link Method Method} object. * @return the Java method type corresponding to the given method. @@ -315,7 +315,7 @@ public static Type getType(final Method m) { /** * Returns the Java types corresponding to the argument types of the given * method descriptor. - * + * * @param methodDescriptor * a method descriptor. * @return the Java types corresponding to the argument types of the given @@ -351,7 +351,7 @@ public static Type[] getArgumentTypes(final String methodDescriptor) { /** * Returns the Java types corresponding to the argument types of the given * method. - * + * * @param method * a method. * @return the Java types corresponding to the argument types of the given @@ -369,7 +369,7 @@ public static Type[] getArgumentTypes(final Method method) { /** * Returns the Java type corresponding to the return type of the given * method descriptor. - * + * * @param methodDescriptor * a method descriptor. * @return the Java type corresponding to the return type of the given @@ -377,13 +377,22 @@ public static Type[] getArgumentTypes(final Method method) { */ public static Type getReturnType(final String methodDescriptor) { char[] buf = methodDescriptor.toCharArray(); - return getType(buf, methodDescriptor.indexOf(')') + 1); + int off = 1; + while (true) { + char car = buf[off++]; + if (car == ')') { + return getType(buf, off); + } else if (car == 'L') { + while (buf[off++] != ';') { + } + } + } } /** * Returns the Java type corresponding to the return type of the given * method. - * + * * @param method * a method. * @return the Java type corresponding to the return type of the given @@ -395,7 +404,7 @@ public static Type getReturnType(final Method method) { /** * Computes the size of the arguments and of the return value of a method. - * + * * @param desc * the descriptor of a method. * @return the size of the arguments of the method (plus one for the @@ -436,7 +445,7 @@ public static int getArgumentsAndReturnSizes(final String desc) { * Returns the Java type corresponding to the given type descriptor. For * method descriptors, buf is supposed to contain nothing more than the * descriptor itself. - * + * * @param buf * a buffer containing a type descriptor. * @param off @@ -494,7 +503,7 @@ private static Type getType(final char[] buf, final int off) { /** * Returns the sort of this Java type. - * + * * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN}, {@link #CHAR CHAR}, * {@link #BYTE BYTE}, {@link #SHORT SHORT}, {@link #INT INT}, * {@link #FLOAT FLOAT}, {@link #LONG LONG}, {@link #DOUBLE DOUBLE}, @@ -508,7 +517,7 @@ public int getSort() { /** * Returns the number of dimensions of this array type. This method should * only be used for an array type. - * + * * @return the number of dimensions of this array type. */ public int getDimensions() { @@ -522,7 +531,7 @@ public int getDimensions() { /** * Returns the type of the elements of this array type. This method should * only be used for an array type. - * + * * @return Returns the type of the elements of this array type. */ public Type getElementType() { @@ -532,7 +541,7 @@ public Type getElementType() { /** * Returns the binary name of the class corresponding to this type. This * method must not be used on method types. - * + * * @return the binary name of the class corresponding to this type. */ public String getClassName() { @@ -573,7 +582,7 @@ public String getClassName() { * array type. The internal name of a class is its fully qualified name (as * returned by Class.getName(), where '.' are replaced by '/'. This method * should only be used for an object or array type. - * + * * @return the internal name of the class corresponding to this object type. */ public String getInternalName() { @@ -583,7 +592,7 @@ public String getInternalName() { /** * Returns the argument types of methods of this type. This method should * only be used for method types. - * + * * @return the argument types of methods of this type. */ public Type[] getArgumentTypes() { @@ -593,7 +602,7 @@ public Type[] getArgumentTypes() { /** * Returns the return type of methods of this type. This method should only * be used for method types. - * + * * @return the return type of methods of this type. */ public Type getReturnType() { @@ -603,7 +612,7 @@ public Type getReturnType() { /** * Returns the size of the arguments and of the return value of methods of * this type. This method should only be used for method types. - * + * * @return the size of the arguments (plus one for the implicit this * argument), argSize, and the size of the return value, retSize, * packed into a single @@ -621,11 +630,11 @@ public int getArgumentsAndReturnSizes() { /** * Returns the descriptor corresponding to this Java type. - * + * * @return the descriptor corresponding to this Java type. */ public String getDescriptor() { - StringBuffer buf = new StringBuffer(); + StringBuilder buf = new StringBuilder(); getDescriptor(buf); return buf.toString(); } @@ -633,7 +642,7 @@ public String getDescriptor() { /** * Returns the descriptor corresponding to the given argument and return * types. - * + * * @param returnType * the return type of the method. * @param argumentTypes @@ -643,7 +652,7 @@ public String getDescriptor() { */ public static String getMethodDescriptor(final Type returnType, final Type... argumentTypes) { - StringBuffer buf = new StringBuffer(); + StringBuilder buf = new StringBuilder(); buf.append('('); for (int i = 0; i < argumentTypes.length; ++i) { argumentTypes[i].getDescriptor(buf); @@ -656,11 +665,11 @@ public static String getMethodDescriptor(final Type returnType, /** * Appends the descriptor corresponding to this Java type to the given * string buffer. - * + * * @param buf * the string buffer to which the descriptor must be appended. */ - private void getDescriptor(final StringBuffer buf) { + private void getDescriptor(final StringBuilder buf) { if (this.buf == null) { // descriptor is in byte 3 of 'off' for primitive types (buf == // null) @@ -683,7 +692,7 @@ private void getDescriptor(final StringBuffer buf) { * Returns the internal name of the given class. The internal name of a * class is its fully qualified name, as returned by Class.getName(), where * '.' are replaced by '/'. - * + * * @param c * an object or array class. * @return the internal name of the given class. @@ -694,27 +703,27 @@ public static String getInternalName(final Class c) { /** * Returns the descriptor corresponding to the given Java type. - * + * * @param c * an object class, a primitive class or an array class. * @return the descriptor corresponding to the given class. */ public static String getDescriptor(final Class c) { - StringBuffer buf = new StringBuffer(); + StringBuilder buf = new StringBuilder(); getDescriptor(buf, c); return buf.toString(); } /** * Returns the descriptor corresponding to the given constructor. - * + * * @param c * a {@link Constructor Constructor} object. * @return the descriptor of the given constructor. */ public static String getConstructorDescriptor(final Constructor c) { Class[] parameters = c.getParameterTypes(); - StringBuffer buf = new StringBuffer(); + StringBuilder buf = new StringBuilder(); buf.append('('); for (int i = 0; i < parameters.length; ++i) { getDescriptor(buf, parameters[i]); @@ -724,14 +733,14 @@ public static String getConstructorDescriptor(final Constructor c) { /** * Returns the descriptor corresponding to the given method. - * + * * @param m * a {@link Method Method} object. * @return the descriptor of the given method. */ public static String getMethodDescriptor(final Method m) { Class[] parameters = m.getParameterTypes(); - StringBuffer buf = new StringBuffer(); + StringBuilder buf = new StringBuilder(); buf.append('('); for (int i = 0; i < parameters.length; ++i) { getDescriptor(buf, parameters[i]); @@ -743,13 +752,13 @@ public static String getMethodDescriptor(final Method m) { /** * Appends the descriptor of the given class to the given string buffer. - * + * * @param buf * the string buffer to which the descriptor must be appended. * @param c * the class whose descriptor must be computed. */ - private static void getDescriptor(final StringBuffer buf, final Class c) { + private static void getDescriptor(final StringBuilder buf, final Class c) { Class d = c; while (true) { if (d.isPrimitive()) { @@ -799,7 +808,7 @@ private static void getDescriptor(final StringBuffer buf, final Class c) { /** * Returns the size of values of this type. This method must not be used for * method types. - * + * * @return the size of values of this type, i.e., 2 for long and * double, 0 for void and 1 otherwise. */ @@ -811,7 +820,7 @@ public int getSize() { /** * Returns a JVM instruction opcode adapted to this Java type. This method * must not be used for method types. - * + * * @param opcode * a JVM instruction opcode. This opcode must be one of ILOAD, * ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG, @@ -838,7 +847,7 @@ public int getOpcode(final int opcode) { /** * Tests if the given object is equal to this type. - * + * * @param o * the object to be compared to this type. * @return true if the given object is equal to this type. @@ -870,7 +879,7 @@ public boolean equals(final Object o) { /** * Returns a hash code value for this type. - * + * * @return a hash code value for this type. */ @Override @@ -886,7 +895,7 @@ public int hashCode() { /** * Returns a string representation of this type. - * + * * @return the descriptor of this type. */ @Override diff --git a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/TypePath.java b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/TypePath.java index 033753f01..07dba4789 100644 --- a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/TypePath.java +++ b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/TypePath.java @@ -1,193 +1,196 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2013 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -package jersey.repackaged.org.objectweb.asm; - -/** - * The path to a type argument, wildcard bound, array element type, or static - * inner type within an enclosing type. - * - * @author Eric Bruneton - */ -public class TypePath { - - /** - * A type path step that steps into the element type of an array type. See - * {@link #getStep getStep}. - */ - public final static int ARRAY_ELEMENT = 0; - - /** - * A type path step that steps into the nested type of a class type. See - * {@link #getStep getStep}. - */ - public final static int INNER_TYPE = 1; - - /** - * A type path step that steps into the bound of a wildcard type. See - * {@link #getStep getStep}. - */ - public final static int WILDCARD_BOUND = 2; - - /** - * A type path step that steps into a type argument of a generic type. See - * {@link #getStep getStep}. - */ - public final static int TYPE_ARGUMENT = 3; - - /** - * The byte array where the path is stored, in Java class file format. - */ - byte[] b; - - /** - * The offset of the first byte of the type path in 'b'. - */ - int offset; - - /** - * Creates a new type path. - * - * @param b - * the byte array containing the type path in Java class file - * format. - * @param offset - * the offset of the first byte of the type path in 'b'. - */ - TypePath(byte[] b, int offset) { - this.b = b; - this.offset = offset; - } - - /** - * Returns the length of this path. - * - * @return the length of this path. - */ - public int getLength() { - return b[offset]; - } - - /** - * Returns the value of the given step of this path. - * - * @param index - * an index between 0 and {@link #getLength()}, exclusive. - * @return {@link #ARRAY_ELEMENT ARRAY_ELEMENT}, {@link #INNER_TYPE - * INNER_TYPE}, {@link #WILDCARD_BOUND WILDCARD_BOUND}, or - * {@link #TYPE_ARGUMENT TYPE_ARGUMENT}. - */ - public int getStep(int index) { - return b[offset + 2 * index + 1]; - } - - /** - * Returns the index of the type argument that the given step is stepping - * into. This method should only be used for steps whose value is - * {@link #TYPE_ARGUMENT TYPE_ARGUMENT}. - * - * @param index - * an index between 0 and {@link #getLength()}, exclusive. - * @return the index of the type argument that the given step is stepping - * into. - */ - public int getStepArgument(int index) { - return b[offset + 2 * index + 2]; - } - - /** - * Converts a type path in string form, in the format used by - * {@link #toString()}, into a TypePath object. - * - * @param typePath - * a type path in string form, in the format used by - * {@link #toString()}. May be null or empty. - * @return the corresponding TypePath object, or null if the path is empty. - */ - public static TypePath fromString(final String typePath) { - if (typePath == null || typePath.length() == 0) { - return null; - } - int n = typePath.length(); - ByteVector out = new ByteVector(n); - out.putByte(0); - for (int i = 0; i < n;) { - char c = typePath.charAt(i++); - if (c == '[') { - out.put11(ARRAY_ELEMENT, 0); - } else if (c == '.') { - out.put11(INNER_TYPE, 0); - } else if (c == '*') { - out.put11(WILDCARD_BOUND, 0); - } else if (c >= '0' && c <= '9') { - int typeArg = c - '0'; - while (i < n && (c = typePath.charAt(i)) >= '0' && c <= '9') { - typeArg = typeArg * 10 + c - '0'; - i += 1; - } - out.put11(TYPE_ARGUMENT, typeArg); - } - } - out.data[0] = (byte) (out.length / 2); - return new TypePath(out.data, 0); - } - - /** - * Returns a string representation of this type path. {@link #ARRAY_ELEMENT - * ARRAY_ELEMENT} steps are represented with '[', {@link #INNER_TYPE - * INNER_TYPE} steps with '.', {@link #WILDCARD_BOUND WILDCARD_BOUND} steps - * with '*' and {@link #TYPE_ARGUMENT TYPE_ARGUMENT} steps with their type - * argument index in decimal form. - */ - @Override - public String toString() { - int length = getLength(); - StringBuilder result = new StringBuilder(length * 2); - for (int i = 0; i < length; ++i) { - switch (getStep(i)) { - case ARRAY_ELEMENT: - result.append('['); - break; - case INNER_TYPE: - result.append('.'); - break; - case WILDCARD_BOUND: - result.append('*'); - break; - case TYPE_ARGUMENT: - result.append(getStepArgument(i)); - break; - default: - result.append('_'); - } - } - return result.toString(); - } -} +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2013 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +package jersey.repackaged.org.objectweb.asm; + +/** + * The path to a type argument, wildcard bound, array element type, or static + * inner type within an enclosing type. + * + * @author Eric Bruneton + */ +public class TypePath { + + /** + * A type path step that steps into the element type of an array type. See + * {@link #getStep getStep}. + */ + public final static int ARRAY_ELEMENT = 0; + + /** + * A type path step that steps into the nested type of a class type. See + * {@link #getStep getStep}. + */ + public final static int INNER_TYPE = 1; + + /** + * A type path step that steps into the bound of a wildcard type. See + * {@link #getStep getStep}. + */ + public final static int WILDCARD_BOUND = 2; + + /** + * A type path step that steps into a type argument of a generic type. See + * {@link #getStep getStep}. + */ + public final static int TYPE_ARGUMENT = 3; + + /** + * The byte array where the path is stored, in Java class file format. + */ + byte[] b; + + /** + * The offset of the first byte of the type path in 'b'. + */ + int offset; + + /** + * Creates a new type path. + * + * @param b + * the byte array containing the type path in Java class file + * format. + * @param offset + * the offset of the first byte of the type path in 'b'. + */ + TypePath(byte[] b, int offset) { + this.b = b; + this.offset = offset; + } + + /** + * Returns the length of this path. + * + * @return the length of this path. + */ + public int getLength() { + return b[offset]; + } + + /** + * Returns the value of the given step of this path. + * + * @param index + * an index between 0 and {@link #getLength()}, exclusive. + * @return {@link #ARRAY_ELEMENT ARRAY_ELEMENT}, {@link #INNER_TYPE + * INNER_TYPE}, {@link #WILDCARD_BOUND WILDCARD_BOUND}, or + * {@link #TYPE_ARGUMENT TYPE_ARGUMENT}. + */ + public int getStep(int index) { + return b[offset + 2 * index + 1]; + } + + /** + * Returns the index of the type argument that the given step is stepping + * into. This method should only be used for steps whose value is + * {@link #TYPE_ARGUMENT TYPE_ARGUMENT}. + * + * @param index + * an index between 0 and {@link #getLength()}, exclusive. + * @return the index of the type argument that the given step is stepping + * into. + */ + public int getStepArgument(int index) { + return b[offset + 2 * index + 2]; + } + + /** + * Converts a type path in string form, in the format used by + * {@link #toString()}, into a TypePath object. + * + * @param typePath + * a type path in string form, in the format used by + * {@link #toString()}. May be null or empty. + * @return the corresponding TypePath object, or null if the path is empty. + */ + public static TypePath fromString(final String typePath) { + if (typePath == null || typePath.length() == 0) { + return null; + } + int n = typePath.length(); + ByteVector out = new ByteVector(n); + out.putByte(0); + for (int i = 0; i < n;) { + char c = typePath.charAt(i++); + if (c == '[') { + out.put11(ARRAY_ELEMENT, 0); + } else if (c == '.') { + out.put11(INNER_TYPE, 0); + } else if (c == '*') { + out.put11(WILDCARD_BOUND, 0); + } else if (c >= '0' && c <= '9') { + int typeArg = c - '0'; + while (i < n && (c = typePath.charAt(i)) >= '0' && c <= '9') { + typeArg = typeArg * 10 + c - '0'; + i += 1; + } + if (i < n && typePath.charAt(i) == ';') { + i += 1; + } + out.put11(TYPE_ARGUMENT, typeArg); + } + } + out.data[0] = (byte) (out.length / 2); + return new TypePath(out.data, 0); + } + + /** + * Returns a string representation of this type path. {@link #ARRAY_ELEMENT + * ARRAY_ELEMENT} steps are represented with '[', {@link #INNER_TYPE + * INNER_TYPE} steps with '.', {@link #WILDCARD_BOUND WILDCARD_BOUND} steps + * with '*' and {@link #TYPE_ARGUMENT TYPE_ARGUMENT} steps with their type + * argument index in decimal form followed by ';'. + */ + @Override + public String toString() { + int length = getLength(); + StringBuilder result = new StringBuilder(length * 2); + for (int i = 0; i < length; ++i) { + switch (getStep(i)) { + case ARRAY_ELEMENT: + result.append('['); + break; + case INNER_TYPE: + result.append('.'); + break; + case WILDCARD_BOUND: + result.append('*'); + break; + case TYPE_ARGUMENT: + result.append(getStepArgument(i)).append(';'); + break; + default: + result.append('_'); + } + } + return result.toString(); + } +} diff --git a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/TypeReference.java b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/TypeReference.java index 117d806b9..0b6232a3e 100644 --- a/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/TypeReference.java +++ b/jersey-server/src/main/java/jersey/repackaged/org/objectweb/asm/TypeReference.java @@ -1,452 +1,452 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2013 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -package jersey.repackaged.org.objectweb.asm; - -/** - * A reference to a type appearing in a class, field or method declaration, or - * on an instruction. Such a reference designates the part of the class where - * the referenced type is appearing (e.g. an 'extends', 'implements' or 'throws' - * clause, a 'new' instruction, a 'catch' clause, a type cast, a local variable - * declaration, etc). - * - * @author Eric Bruneton - */ -public class TypeReference { - - /** - * The sort of type references that target a type parameter of a generic - * class. See {@link #getSort getSort}. - */ - public final static int CLASS_TYPE_PARAMETER = 0x00; - - /** - * The sort of type references that target a type parameter of a generic - * method. See {@link #getSort getSort}. - */ - public final static int METHOD_TYPE_PARAMETER = 0x01; - - /** - * The sort of type references that target the super class of a class or one - * of the interfaces it implements. See {@link #getSort getSort}. - */ - public final static int CLASS_EXTENDS = 0x10; - - /** - * The sort of type references that target a bound of a type parameter of a - * generic class. See {@link #getSort getSort}. - */ - public final static int CLASS_TYPE_PARAMETER_BOUND = 0x11; - - /** - * The sort of type references that target a bound of a type parameter of a - * generic method. See {@link #getSort getSort}. - */ - public final static int METHOD_TYPE_PARAMETER_BOUND = 0x12; - - /** - * The sort of type references that target the type of a field. See - * {@link #getSort getSort}. - */ - public final static int FIELD = 0x13; - - /** - * The sort of type references that target the return type of a method. See - * {@link #getSort getSort}. - */ - public final static int METHOD_RETURN = 0x14; - - /** - * The sort of type references that target the receiver type of a method. - * See {@link #getSort getSort}. - */ - public final static int METHOD_RECEIVER = 0x15; - - /** - * The sort of type references that target the type of a formal parameter of - * a method. See {@link #getSort getSort}. - */ - public final static int METHOD_FORMAL_PARAMETER = 0x16; - - /** - * The sort of type references that target the type of an exception declared - * in the throws clause of a method. See {@link #getSort getSort}. - */ - public final static int THROWS = 0x17; - - /** - * The sort of type references that target the type of a local variable in a - * method. See {@link #getSort getSort}. - */ - public final static int LOCAL_VARIABLE = 0x40; - - /** - * The sort of type references that target the type of a resource variable - * in a method. See {@link #getSort getSort}. - */ - public final static int RESOURCE_VARIABLE = 0x41; - - /** - * The sort of type references that target the type of the exception of a - * 'catch' clause in a method. See {@link #getSort getSort}. - */ - public final static int EXCEPTION_PARAMETER = 0x42; - - /** - * The sort of type references that target the type declared in an - * 'instanceof' instruction. See {@link #getSort getSort}. - */ - public final static int INSTANCEOF = 0x43; - - /** - * The sort of type references that target the type of the object created by - * a 'new' instruction. See {@link #getSort getSort}. - */ - public final static int NEW = 0x44; - - /** - * The sort of type references that target the receiver type of a - * constructor reference. See {@link #getSort getSort}. - */ - public final static int CONSTRUCTOR_REFERENCE = 0x45; - - /** - * The sort of type references that target the receiver type of a method - * reference. See {@link #getSort getSort}. - */ - public final static int METHOD_REFERENCE = 0x46; - - /** - * The sort of type references that target the type declared in an explicit - * or implicit cast instruction. See {@link #getSort getSort}. - */ - public final static int CAST = 0x47; - - /** - * The sort of type references that target a type parameter of a generic - * constructor in a constructor call. See {@link #getSort getSort}. - */ - public final static int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48; - - /** - * The sort of type references that target a type parameter of a generic - * method in a method call. See {@link #getSort getSort}. - */ - public final static int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49; - - /** - * The sort of type references that target a type parameter of a generic - * constructor in a constructor reference. See {@link #getSort getSort}. - */ - public final static int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A; - - /** - * The sort of type references that target a type parameter of a generic - * method in a method reference. See {@link #getSort getSort}. - */ - public final static int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B; - - /** - * The type reference value in Java class file format. - */ - private int value; - - /** - * Creates a new TypeReference. - * - * @param typeRef - * the int encoded value of the type reference, as received in a - * visit method related to type annotations, like - * visitTypeAnnotation. - */ - public TypeReference(int typeRef) { - this.value = typeRef; - } - - /** - * Returns a type reference of the given sort. - * - * @param sort - * {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN}, - * {@link #METHOD_RECEIVER METHOD_RECEIVER}, - * {@link #LOCAL_VARIABLE LOCAL_VARIABLE}, - * {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE}, - * {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW}, - * {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE}, or - * {@link #METHOD_REFERENCE METHOD_REFERENCE}. - * @return a type reference of the given sort. - */ - public static TypeReference newTypeReference(int sort) { - return new TypeReference(sort << 24); - } - - /** - * Returns a reference to a type parameter of a generic class or method. - * - * @param sort - * {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or - * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}. - * @param paramIndex - * the type parameter index. - * @return a reference to the given generic class or method type parameter. - */ - public static TypeReference newTypeParameterReference(int sort, - int paramIndex) { - return new TypeReference((sort << 24) | (paramIndex << 16)); - } - - /** - * Returns a reference to a type parameter bound of a generic class or - * method. - * - * @param sort - * {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or - * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}. - * @param paramIndex - * the type parameter index. - * @param boundIndex - * the type bound index within the above type parameters. - * @return a reference to the given generic class or method type parameter - * bound. - */ - public static TypeReference newTypeParameterBoundReference(int sort, - int paramIndex, int boundIndex) { - return new TypeReference((sort << 24) | (paramIndex << 16) - | (boundIndex << 8)); - } - - /** - * Returns a reference to the super class or to an interface of the - * 'implements' clause of a class. - * - * @param itfIndex - * the index of an interface in the 'implements' clause of a - * class, or -1 to reference the super class of the class. - * @return a reference to the given super type of a class. - */ - public static TypeReference newSuperTypeReference(int itfIndex) { - itfIndex &= 0xFFFF; - return new TypeReference((CLASS_EXTENDS << 24) | (itfIndex << 8)); - } - - /** - * Returns a reference to the type of a formal parameter of a method. - * - * @param paramIndex - * the formal parameter index. - * - * @return a reference to the type of the given method formal parameter. - */ - public static TypeReference newFormalParameterReference(int paramIndex) { - return new TypeReference((METHOD_FORMAL_PARAMETER << 24) - | (paramIndex << 16)); - } - - /** - * Returns a reference to the type of an exception, in a 'throws' clause of - * a method. - * - * @param exceptionIndex - * the index of an exception in a 'throws' clause of a method. - * - * @return a reference to the type of the given exception. - */ - public static TypeReference newExceptionReference(int exceptionIndex) { - return new TypeReference((THROWS << 24) | (exceptionIndex << 8)); - } - - /** - * Returns a reference to the type of the exception declared in a 'catch' - * clause of a method. - * - * @param tryCatchBlockIndex - * the index of a try catch block (using the order in which they - * are visited with visitTryCatchBlock). - * - * @return a reference to the type of the given exception. - */ - public static TypeReference newTryCatchReference(int tryCatchBlockIndex) { - return new TypeReference((EXCEPTION_PARAMETER << 24) - | (tryCatchBlockIndex << 8)); - } - - /** - * Returns a reference to the type of a type argument in a constructor or - * method call or reference. - * - * @param sort - * {@link #CAST CAST}, - * {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT - * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, - * {@link #METHOD_INVOCATION_TYPE_ARGUMENT - * METHOD_INVOCATION_TYPE_ARGUMENT}, - * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT - * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or - * {@link #METHOD_REFERENCE_TYPE_ARGUMENT - * METHOD_REFERENCE_TYPE_ARGUMENT}. - * @param argIndex - * the type argument index. - * - * @return a reference to the type of the given type argument. - */ - public static TypeReference newTypeArgumentReference(int sort, int argIndex) { - return new TypeReference((sort << 24) | argIndex); - } - - /** - * Returns the sort of this type reference. - * - * @return {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER}, - * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}, - * {@link #CLASS_EXTENDS CLASS_EXTENDS}, - * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND}, - * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}, - * {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN}, - * {@link #METHOD_RECEIVER METHOD_RECEIVER}, - * {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER}, - * {@link #THROWS THROWS}, {@link #LOCAL_VARIABLE LOCAL_VARIABLE}, - * {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE}, - * {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER}, - * {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW}, - * {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE}, - * {@link #METHOD_REFERENCE METHOD_REFERENCE}, {@link #CAST CAST}, - * {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT - * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, - * {@link #METHOD_INVOCATION_TYPE_ARGUMENT - * METHOD_INVOCATION_TYPE_ARGUMENT}, - * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT - * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or - * {@link #METHOD_REFERENCE_TYPE_ARGUMENT - * METHOD_REFERENCE_TYPE_ARGUMENT}. - */ - public int getSort() { - return value >>> 24; - } - - /** - * Returns the index of the type parameter referenced by this type - * reference. This method must only be used for type references whose sort - * is {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER}, - * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}, - * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or - * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}. - * - * @return a type parameter index. - */ - public int getTypeParameterIndex() { - return (value & 0x00FF0000) >> 16; - } - - /** - * Returns the index of the type parameter bound, within the type parameter - * {@link #getTypeParameterIndex}, referenced by this type reference. This - * method must only be used for type references whose sort is - * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or - * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}. - * - * @return a type parameter bound index. - */ - public int getTypeParameterBoundIndex() { - return (value & 0x0000FF00) >> 8; - } - - /** - * Returns the index of the "super type" of a class that is referenced by - * this type reference. This method must only be used for type references - * whose sort is {@link #CLASS_EXTENDS CLASS_EXTENDS}. - * - * @return the index of an interface in the 'implements' clause of a class, - * or -1 if this type reference references the type of the super - * class. - */ - public int getSuperTypeIndex() { - return (short) ((value & 0x00FFFF00) >> 8); - } - - /** - * Returns the index of the formal parameter whose type is referenced by - * this type reference. This method must only be used for type references - * whose sort is {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER}. - * - * @return a formal parameter index. - */ - public int getFormalParameterIndex() { - return (value & 0x00FF0000) >> 16; - } - - /** - * Returns the index of the exception, in a 'throws' clause of a method, - * whose type is referenced by this type reference. This method must only be - * used for type references whose sort is {@link #THROWS THROWS}. - * - * @return the index of an exception in the 'throws' clause of a method. - */ - public int getExceptionIndex() { - return (value & 0x00FFFF00) >> 8; - } - - /** - * Returns the index of the try catch block (using the order in which they - * are visited with visitTryCatchBlock), whose 'catch' type is referenced by - * this type reference. This method must only be used for type references - * whose sort is {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER} . - * - * @return the index of an exception in the 'throws' clause of a method. - */ - public int getTryCatchBlockIndex() { - return (value & 0x00FFFF00) >> 8; - } - - /** - * Returns the index of the type argument referenced by this type reference. - * This method must only be used for type references whose sort is - * {@link #CAST CAST}, {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT - * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, - * {@link #METHOD_INVOCATION_TYPE_ARGUMENT METHOD_INVOCATION_TYPE_ARGUMENT}, - * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT - * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or - * {@link #METHOD_REFERENCE_TYPE_ARGUMENT METHOD_REFERENCE_TYPE_ARGUMENT}. - * - * @return a type parameter index. - */ - public int getTypeArgumentIndex() { - return value & 0xFF; - } - - /** - * Returns the int encoded value of this type reference, suitable for use in - * visit methods related to type annotations, like visitTypeAnnotation. - * - * @return the int encoded value of this type reference. - */ - public int getValue() { - return value; - } -} +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2013 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +package jersey.repackaged.org.objectweb.asm; + +/** + * A reference to a type appearing in a class, field or method declaration, or + * on an instruction. Such a reference designates the part of the class where + * the referenced type is appearing (e.g. an 'extends', 'implements' or 'throws' + * clause, a 'new' instruction, a 'catch' clause, a type cast, a local variable + * declaration, etc). + * + * @author Eric Bruneton + */ +public class TypeReference { + + /** + * The sort of type references that target a type parameter of a generic + * class. See {@link #getSort getSort}. + */ + public final static int CLASS_TYPE_PARAMETER = 0x00; + + /** + * The sort of type references that target a type parameter of a generic + * method. See {@link #getSort getSort}. + */ + public final static int METHOD_TYPE_PARAMETER = 0x01; + + /** + * The sort of type references that target the super class of a class or one + * of the interfaces it implements. See {@link #getSort getSort}. + */ + public final static int CLASS_EXTENDS = 0x10; + + /** + * The sort of type references that target a bound of a type parameter of a + * generic class. See {@link #getSort getSort}. + */ + public final static int CLASS_TYPE_PARAMETER_BOUND = 0x11; + + /** + * The sort of type references that target a bound of a type parameter of a + * generic method. See {@link #getSort getSort}. + */ + public final static int METHOD_TYPE_PARAMETER_BOUND = 0x12; + + /** + * The sort of type references that target the type of a field. See + * {@link #getSort getSort}. + */ + public final static int FIELD = 0x13; + + /** + * The sort of type references that target the return type of a method. See + * {@link #getSort getSort}. + */ + public final static int METHOD_RETURN = 0x14; + + /** + * The sort of type references that target the receiver type of a method. + * See {@link #getSort getSort}. + */ + public final static int METHOD_RECEIVER = 0x15; + + /** + * The sort of type references that target the type of a formal parameter of + * a method. See {@link #getSort getSort}. + */ + public final static int METHOD_FORMAL_PARAMETER = 0x16; + + /** + * The sort of type references that target the type of an exception declared + * in the throws clause of a method. See {@link #getSort getSort}. + */ + public final static int THROWS = 0x17; + + /** + * The sort of type references that target the type of a local variable in a + * method. See {@link #getSort getSort}. + */ + public final static int LOCAL_VARIABLE = 0x40; + + /** + * The sort of type references that target the type of a resource variable + * in a method. See {@link #getSort getSort}. + */ + public final static int RESOURCE_VARIABLE = 0x41; + + /** + * The sort of type references that target the type of the exception of a + * 'catch' clause in a method. See {@link #getSort getSort}. + */ + public final static int EXCEPTION_PARAMETER = 0x42; + + /** + * The sort of type references that target the type declared in an + * 'instanceof' instruction. See {@link #getSort getSort}. + */ + public final static int INSTANCEOF = 0x43; + + /** + * The sort of type references that target the type of the object created by + * a 'new' instruction. See {@link #getSort getSort}. + */ + public final static int NEW = 0x44; + + /** + * The sort of type references that target the receiver type of a + * constructor reference. See {@link #getSort getSort}. + */ + public final static int CONSTRUCTOR_REFERENCE = 0x45; + + /** + * The sort of type references that target the receiver type of a method + * reference. See {@link #getSort getSort}. + */ + public final static int METHOD_REFERENCE = 0x46; + + /** + * The sort of type references that target the type declared in an explicit + * or implicit cast instruction. See {@link #getSort getSort}. + */ + public final static int CAST = 0x47; + + /** + * The sort of type references that target a type parameter of a generic + * constructor in a constructor call. See {@link #getSort getSort}. + */ + public final static int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48; + + /** + * The sort of type references that target a type parameter of a generic + * method in a method call. See {@link #getSort getSort}. + */ + public final static int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49; + + /** + * The sort of type references that target a type parameter of a generic + * constructor in a constructor reference. See {@link #getSort getSort}. + */ + public final static int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A; + + /** + * The sort of type references that target a type parameter of a generic + * method in a method reference. See {@link #getSort getSort}. + */ + public final static int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B; + + /** + * The type reference value in Java class file format. + */ + private int value; + + /** + * Creates a new TypeReference. + * + * @param typeRef + * the int encoded value of the type reference, as received in a + * visit method related to type annotations, like + * visitTypeAnnotation. + */ + public TypeReference(int typeRef) { + this.value = typeRef; + } + + /** + * Returns a type reference of the given sort. + * + * @param sort + * {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN}, + * {@link #METHOD_RECEIVER METHOD_RECEIVER}, + * {@link #LOCAL_VARIABLE LOCAL_VARIABLE}, + * {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE}, + * {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW}, + * {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE}, or + * {@link #METHOD_REFERENCE METHOD_REFERENCE}. + * @return a type reference of the given sort. + */ + public static TypeReference newTypeReference(int sort) { + return new TypeReference(sort << 24); + } + + /** + * Returns a reference to a type parameter of a generic class or method. + * + * @param sort + * {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or + * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}. + * @param paramIndex + * the type parameter index. + * @return a reference to the given generic class or method type parameter. + */ + public static TypeReference newTypeParameterReference(int sort, + int paramIndex) { + return new TypeReference((sort << 24) | (paramIndex << 16)); + } + + /** + * Returns a reference to a type parameter bound of a generic class or + * method. + * + * @param sort + * {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or + * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}. + * @param paramIndex + * the type parameter index. + * @param boundIndex + * the type bound index within the above type parameters. + * @return a reference to the given generic class or method type parameter + * bound. + */ + public static TypeReference newTypeParameterBoundReference(int sort, + int paramIndex, int boundIndex) { + return new TypeReference((sort << 24) | (paramIndex << 16) + | (boundIndex << 8)); + } + + /** + * Returns a reference to the super class or to an interface of the + * 'implements' clause of a class. + * + * @param itfIndex + * the index of an interface in the 'implements' clause of a + * class, or -1 to reference the super class of the class. + * @return a reference to the given super type of a class. + */ + public static TypeReference newSuperTypeReference(int itfIndex) { + itfIndex &= 0xFFFF; + return new TypeReference((CLASS_EXTENDS << 24) | (itfIndex << 8)); + } + + /** + * Returns a reference to the type of a formal parameter of a method. + * + * @param paramIndex + * the formal parameter index. + * + * @return a reference to the type of the given method formal parameter. + */ + public static TypeReference newFormalParameterReference(int paramIndex) { + return new TypeReference((METHOD_FORMAL_PARAMETER << 24) + | (paramIndex << 16)); + } + + /** + * Returns a reference to the type of an exception, in a 'throws' clause of + * a method. + * + * @param exceptionIndex + * the index of an exception in a 'throws' clause of a method. + * + * @return a reference to the type of the given exception. + */ + public static TypeReference newExceptionReference(int exceptionIndex) { + return new TypeReference((THROWS << 24) | (exceptionIndex << 8)); + } + + /** + * Returns a reference to the type of the exception declared in a 'catch' + * clause of a method. + * + * @param tryCatchBlockIndex + * the index of a try catch block (using the order in which they + * are visited with visitTryCatchBlock). + * + * @return a reference to the type of the given exception. + */ + public static TypeReference newTryCatchReference(int tryCatchBlockIndex) { + return new TypeReference((EXCEPTION_PARAMETER << 24) + | (tryCatchBlockIndex << 8)); + } + + /** + * Returns a reference to the type of a type argument in a constructor or + * method call or reference. + * + * @param sort + * {@link #CAST CAST}, + * {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT + * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, + * {@link #METHOD_INVOCATION_TYPE_ARGUMENT + * METHOD_INVOCATION_TYPE_ARGUMENT}, + * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT + * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or + * {@link #METHOD_REFERENCE_TYPE_ARGUMENT + * METHOD_REFERENCE_TYPE_ARGUMENT}. + * @param argIndex + * the type argument index. + * + * @return a reference to the type of the given type argument. + */ + public static TypeReference newTypeArgumentReference(int sort, int argIndex) { + return new TypeReference((sort << 24) | argIndex); + } + + /** + * Returns the sort of this type reference. + * + * @return {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER}, + * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}, + * {@link #CLASS_EXTENDS CLASS_EXTENDS}, + * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND}, + * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}, + * {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN}, + * {@link #METHOD_RECEIVER METHOD_RECEIVER}, + * {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER}, + * {@link #THROWS THROWS}, {@link #LOCAL_VARIABLE LOCAL_VARIABLE}, + * {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE}, + * {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER}, + * {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW}, + * {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE}, + * {@link #METHOD_REFERENCE METHOD_REFERENCE}, {@link #CAST CAST}, + * {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT + * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, + * {@link #METHOD_INVOCATION_TYPE_ARGUMENT + * METHOD_INVOCATION_TYPE_ARGUMENT}, + * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT + * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or + * {@link #METHOD_REFERENCE_TYPE_ARGUMENT + * METHOD_REFERENCE_TYPE_ARGUMENT}. + */ + public int getSort() { + return value >>> 24; + } + + /** + * Returns the index of the type parameter referenced by this type + * reference. This method must only be used for type references whose sort + * is {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER}, + * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}, + * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or + * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}. + * + * @return a type parameter index. + */ + public int getTypeParameterIndex() { + return (value & 0x00FF0000) >> 16; + } + + /** + * Returns the index of the type parameter bound, within the type parameter + * {@link #getTypeParameterIndex}, referenced by this type reference. This + * method must only be used for type references whose sort is + * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or + * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}. + * + * @return a type parameter bound index. + */ + public int getTypeParameterBoundIndex() { + return (value & 0x0000FF00) >> 8; + } + + /** + * Returns the index of the "super type" of a class that is referenced by + * this type reference. This method must only be used for type references + * whose sort is {@link #CLASS_EXTENDS CLASS_EXTENDS}. + * + * @return the index of an interface in the 'implements' clause of a class, + * or -1 if this type reference references the type of the super + * class. + */ + public int getSuperTypeIndex() { + return (short) ((value & 0x00FFFF00) >> 8); + } + + /** + * Returns the index of the formal parameter whose type is referenced by + * this type reference. This method must only be used for type references + * whose sort is {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER}. + * + * @return a formal parameter index. + */ + public int getFormalParameterIndex() { + return (value & 0x00FF0000) >> 16; + } + + /** + * Returns the index of the exception, in a 'throws' clause of a method, + * whose type is referenced by this type reference. This method must only be + * used for type references whose sort is {@link #THROWS THROWS}. + * + * @return the index of an exception in the 'throws' clause of a method. + */ + public int getExceptionIndex() { + return (value & 0x00FFFF00) >> 8; + } + + /** + * Returns the index of the try catch block (using the order in which they + * are visited with visitTryCatchBlock), whose 'catch' type is referenced by + * this type reference. This method must only be used for type references + * whose sort is {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER} . + * + * @return the index of an exception in the 'throws' clause of a method. + */ + public int getTryCatchBlockIndex() { + return (value & 0x00FFFF00) >> 8; + } + + /** + * Returns the index of the type argument referenced by this type reference. + * This method must only be used for type references whose sort is + * {@link #CAST CAST}, {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT + * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, + * {@link #METHOD_INVOCATION_TYPE_ARGUMENT METHOD_INVOCATION_TYPE_ARGUMENT}, + * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT + * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or + * {@link #METHOD_REFERENCE_TYPE_ARGUMENT METHOD_REFERENCE_TYPE_ARGUMENT}. + * + * @return a type parameter index. + */ + public int getTypeArgumentIndex() { + return value & 0xFF; + } + + /** + * Returns the int encoded value of this type reference, suitable for use in + * visit methods related to type annotations, like visitTypeAnnotation. + * + * @return the int encoded value of this type reference. + */ + public int getValue() { + return value; + } +}