parent
							
								
									ac9cfefaff
								
							
						
					
					
						commit
						185c2bf5b6
					
				|  | @ -41,7 +41,7 @@ public abstract class AnnotationVisitor { | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * The ASM API version implemented by this visitor. The value of this field |      * 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; |     protected final int api; | ||||||
| 
 | 
 | ||||||
|  | @ -56,7 +56,7 @@ public abstract class AnnotationVisitor { | ||||||
|      *  |      *  | ||||||
|      * @param api |      * @param api | ||||||
|      *            the ASM API version implemented by this visitor. Must be one |      *            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) { |     public AnnotationVisitor(final int api) { | ||||||
|         this(api, null); |         this(api, null); | ||||||
|  | @ -67,13 +67,13 @@ public abstract class AnnotationVisitor { | ||||||
|      *  |      *  | ||||||
|      * @param api |      * @param api | ||||||
|      *            the ASM API version implemented by this visitor. Must be one |      *            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 |      * @param av | ||||||
|      *            the annotation visitor to which this visitor must delegate |      *            the annotation visitor to which this visitor must delegate | ||||||
|      *            method calls. May be null. |      *            method calls. May be null. | ||||||
|      */ |      */ | ||||||
|     public AnnotationVisitor(final int api, final AnnotationVisitor av) { |     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(); |             throw new IllegalArgumentException(); | ||||||
|         } |         } | ||||||
|         this.api = api; |         this.api = api; | ||||||
|  |  | ||||||
|  | @ -104,7 +104,7 @@ final class AnnotationWriter extends AnnotationVisitor { | ||||||
|      */ |      */ | ||||||
|     AnnotationWriter(final ClassWriter cw, final boolean named, |     AnnotationWriter(final ClassWriter cw, final boolean named, | ||||||
|             final ByteVector bv, final ByteVector parent, final int offset) { |             final ByteVector bv, final ByteVector parent, final int offset) { | ||||||
|         super(Opcodes.ASM5); |         super(Opcodes.ASM6); | ||||||
|         this.cw = cw; |         this.cw = cw; | ||||||
|         this.named = named; |         this.named = named; | ||||||
|         this.bv = bv; |         this.bv = bv; | ||||||
|  |  | ||||||
|  | @ -222,6 +222,8 @@ public class ClassReader { | ||||||
|             // case ClassWriter.CLASS: |             // case ClassWriter.CLASS: | ||||||
|             // case ClassWriter.STR: |             // case ClassWriter.STR: | ||||||
|             // case ClassWriter.MTYPE |             // case ClassWriter.MTYPE | ||||||
|  |             // case ClassWriter.PACKAGE: | ||||||
|  |             // case ClassWriter.MODULE: | ||||||
|             default: |             default: | ||||||
|                 size = 3; |                 size = 3; | ||||||
|                 break; |                 break; | ||||||
|  | @ -365,7 +367,9 @@ public class ClassReader { | ||||||
|                 break; |                 break; | ||||||
|             // case ClassWriter.STR: |             // case ClassWriter.STR: | ||||||
|             // case ClassWriter.CLASS: |             // case ClassWriter.CLASS: | ||||||
|             // case ClassWriter.MTYPE |             // case ClassWriter.MTYPE: | ||||||
|  |             // case ClassWriter.MODULE: | ||||||
|  |             // case ClassWriter.PACKAGE: | ||||||
|             default: |             default: | ||||||
|                 item.set(tag, readUTF8(index, buf), null, null); |                 item.set(tag, readUTF8(index, buf), null, null); | ||||||
|                 break; |                 break; | ||||||
|  | @ -572,11 +576,14 @@ public class ClassReader { | ||||||
|         String enclosingOwner = null; |         String enclosingOwner = null; | ||||||
|         String enclosingName = null; |         String enclosingName = null; | ||||||
|         String enclosingDesc = null; |         String enclosingDesc = null; | ||||||
|  |         String moduleMainClass = null; | ||||||
|         int anns = 0; |         int anns = 0; | ||||||
|         int ianns = 0; |         int ianns = 0; | ||||||
|         int tanns = 0; |         int tanns = 0; | ||||||
|         int itanns = 0; |         int itanns = 0; | ||||||
|         int innerClasses = 0; |         int innerClasses = 0; | ||||||
|  |         int module = 0; | ||||||
|  |         int packages = 0; | ||||||
|         Attribute attributes = null; |         Attribute attributes = null; | ||||||
| 
 | 
 | ||||||
|         u = getAttributes(); |         u = getAttributes(); | ||||||
|  | @ -617,6 +624,12 @@ public class ClassReader { | ||||||
|             } else if (ANNOTATIONS |             } else if (ANNOTATIONS | ||||||
|                     && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { |                     && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { | ||||||
|                 itanns = u + 8; |                 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)) { |             } else if ("BootstrapMethods".equals(attrName)) { | ||||||
|                 int[] bootstrapMethods = new int[readUnsignedShort(u + 8)]; |                 int[] bootstrapMethods = new int[readUnsignedShort(u + 8)]; | ||||||
|                 for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) { |                 for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) { | ||||||
|  | @ -645,6 +658,12 @@ public class ClassReader { | ||||||
|             classVisitor.visitSource(sourceFile, sourceDebug); |             classVisitor.visitSource(sourceFile, sourceDebug); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         // visits the module info and associated attributes | ||||||
|  |         if (module != 0) { | ||||||
|  |             readModule(classVisitor, context, module, | ||||||
|  |                     moduleMainClass, packages); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         // visits the outer class |         // visits the outer class | ||||||
|         if (enclosingOwner != null) { |         if (enclosingOwner != null) { | ||||||
|             classVisitor.visitOuterClass(enclosingOwner, enclosingName, |             classVisitor.visitOuterClass(enclosingOwner, enclosingName, | ||||||
|  | @ -714,6 +733,120 @@ public class ClassReader { | ||||||
|         classVisitor.visitEnd(); |         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. |      * Reads a field and makes the given visitor visit it. | ||||||
|      *  |      *  | ||||||
|  | @ -1082,6 +1215,7 @@ public class ClassReader { | ||||||
|                 u += 3; |                 u += 3; | ||||||
|                 break; |                 break; | ||||||
|             case ClassWriter.LABELW_INSN: |             case ClassWriter.LABELW_INSN: | ||||||
|  |             case ClassWriter.ASM_LABELW_INSN: | ||||||
|                 readLabel(offset + readInt(u + 1), labels); |                 readLabel(offset + readInt(u + 1), labels); | ||||||
|                 u += 5; |                 u += 5; | ||||||
|                 break; |                 break; | ||||||
|  | @ -1305,7 +1439,8 @@ public class ClassReader { | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         if ((context.flags & EXPAND_ASM_INSNS) != 0) { |         if ((context.flags & EXPAND_ASM_INSNS) != 0 | ||||||
|  |             && (context.flags & EXPAND_FRAMES) != 0) { | ||||||
|             // Expanding the ASM pseudo instructions can introduce F_INSERT |             // Expanding the ASM pseudo instructions can introduce F_INSERT | ||||||
|             // frames, even if the method does not currently have any frame. |             // frames, even if the method does not currently have any frame. | ||||||
|             // Also these inserted frames must be computed by simulating the |             // Also these inserted frames must be computed by simulating the | ||||||
|  | @ -1322,6 +1457,7 @@ public class ClassReader { | ||||||
| 
 | 
 | ||||||
|         // visits the instructions |         // visits the instructions | ||||||
|         int opcodeDelta = (context.flags & EXPAND_ASM_INSNS) == 0 ? -33 : 0; |         int opcodeDelta = (context.flags & EXPAND_ASM_INSNS) == 0 ? -33 : 0; | ||||||
|  |         boolean insertFrame = false; | ||||||
|         u = codeStart; |         u = codeStart; | ||||||
|         while (u < codeEnd) { |         while (u < codeEnd) { | ||||||
|             int offset = u - codeStart; |             int offset = u - codeStart; | ||||||
|  | @ -1354,6 +1490,9 @@ public class ClassReader { | ||||||
|                         mv.visitFrame(frame.mode, frame.localDiff, frame.local, |                         mv.visitFrame(frame.mode, frame.localDiff, frame.local, | ||||||
|                                 frame.stackCount, frame.stack); |                                 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) { |                 if (frameCount > 0) { | ||||||
|                     stackMap = readFrame(stackMap, zip, unzip, frame); |                     stackMap = readFrame(stackMap, zip, unzip, frame); | ||||||
|  | @ -1362,6 +1501,13 @@ public class ClassReader { | ||||||
|                     frame = null; |                     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 (FRAMES && insertFrame) { | ||||||
|  |                 mv.visitFrame(ClassWriter.F_INSERT, 0, null, 0, null); | ||||||
|  |                 insertFrame = false; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             // visits the instruction at this offset |             // visits the instruction at this offset | ||||||
|             int opcode = b[u] & 0xFF; |             int opcode = b[u] & 0xFF; | ||||||
|  | @ -1397,31 +1543,36 @@ public class ClassReader { | ||||||
|                 opcode = opcode < 218 ? opcode - 49 : opcode - 20; |                 opcode = opcode < 218 ? opcode - 49 : opcode - 20; | ||||||
|                 Label target = labels[offset + readUnsignedShort(u + 1)]; |                 Label target = labels[offset + readUnsignedShort(u + 1)]; | ||||||
|                 // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx |                 // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx | ||||||
|                 // <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is |                 // <l> with IFNOTxxx <L> GOTO_W <l> L:..., where IFNOTxxx is | ||||||
|                 // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) |                 // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) | ||||||
|                 // and where <l'> designates the instruction just after |                 // and where <L> designates the instruction just after | ||||||
|                 // the GOTO_W. |                 // the GOTO_W. | ||||||
|                 if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) { |                 if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) { | ||||||
|                     mv.visitJumpInsn(opcode + 33, target); |                     mv.visitJumpInsn(opcode + 33, target); | ||||||
|                 } else { |                 } else { | ||||||
|                     opcode = opcode <= 166 ? ((opcode + 1) ^ 1) - 1 |                     opcode = opcode <= 166 ? ((opcode + 1) ^ 1) - 1 | ||||||
|                             : opcode ^ 1; |                             : opcode ^ 1; | ||||||
|                     Label endif = new Label(); |                     Label endif = readLabel(offset + 3, labels); | ||||||
|                     mv.visitJumpInsn(opcode, endif); |                     mv.visitJumpInsn(opcode, endif); | ||||||
|                     mv.visitJumpInsn(200, target); // GOTO_W |                     mv.visitJumpInsn(200, target); // GOTO_W | ||||||
|                     mv.visitLabel(endif); |                     // endif designates the instruction just after GOTO_W, | ||||||
|                     // since we introduced an unconditional jump instruction we |                     // and is visited as part of the next instruction. Since | ||||||
|                     // also need to insert a stack map frame here, unless there |                     // it is a jump target, we need to insert a frame here. | ||||||
|                     // is already one. The actual frame content will be computed |                     insertFrame = true; | ||||||
|                     // in MethodWriter. |  | ||||||
|                     if (FRAMES && stackMap != 0 |  | ||||||
|                             && (frame == null || frame.offset != offset + 3)) { |  | ||||||
|                         mv.visitFrame(ClassWriter.F_INSERT, 0, null, 0, null); |  | ||||||
|                     } |  | ||||||
|                 } |                 } | ||||||
|                 u += 3; |                 u += 3; | ||||||
|                 break; |                 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 <L> GOTO_W <l> L:..., | ||||||
|  |                 // see MethodWriter), so we need to insert a frame here. | ||||||
|  |                 insertFrame = true; | ||||||
|  |                 u += 5; | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|             case ClassWriter.WIDE_INSN: |             case ClassWriter.WIDE_INSN: | ||||||
|                 opcode = b[u + 1] & 0xFF; |                 opcode = b[u + 1] & 0xFF; | ||||||
|                 if (opcode == Opcodes.IINC) { |                 if (opcode == Opcodes.IINC) { | ||||||
|  | @ -2516,6 +2667,20 @@ public class ClassReader { | ||||||
|         return new String(buf, 0, strLen); |         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}. <i>This method is |      * Reads a class constant pool item in {@link #b b}. <i>This method is | ||||||
|      * intended for {@link Attribute} sub classes, and is normally not needed by |      * intended for {@link Attribute} sub classes, and is normally not needed by | ||||||
|  | @ -2530,11 +2695,41 @@ public class ClassReader { | ||||||
|      * @return the String corresponding to the specified class item. |      * @return the String corresponding to the specified class item. | ||||||
|      */ |      */ | ||||||
|     public String readClass(final int index, final char[] buf) { |     public String readClass(final int index, final char[] buf) { | ||||||
|         // computes the start index of the CONSTANT_Class item in b |         return readStringish(index, buf); | ||||||
|         // and reads the CONSTANT_Utf8 item designated by |     } | ||||||
|         // the first two bytes of this CONSTANT_Class item | 
 | ||||||
|         String name = readUTF8(items[readUnsignedShort(index)], buf); |     /** | ||||||
|         return (name != null ? name.intern() : null); |      * Reads a module constant pool item in {@link #b b}. <i>This method is | ||||||
|  |      * intended for {@link Attribute} sub classes, and is normally not needed by | ||||||
|  |      * class generators or adapters.</i> | ||||||
|  |      * | ||||||
|  |      * @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}. <i>This method is | ||||||
|  |      * intended for {@link Attribute} sub classes, and is normally not needed by | ||||||
|  |      * class generators or adapters.</i> | ||||||
|  |      * | ||||||
|  |      * @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); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  |  | ||||||
|  | @ -32,7 +32,7 @@ package org.springframework.asm; | ||||||
| /** | /** | ||||||
|  * A visitor to visit a Java class. The methods of this class must be called in |  * A visitor to visit a Java class. The methods of this class must be called in | ||||||
|  * the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [ |  * the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [ | ||||||
|  * <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> | |  * <tt>visitModule</tt> ][ <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> | | ||||||
|  * <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* ( |  * <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* ( | ||||||
|  * <tt>visitInnerClass</tt> | <tt>visitField</tt> | <tt>visitMethod</tt> )* |  * <tt>visitInnerClass</tt> | <tt>visitField</tt> | <tt>visitMethod</tt> )* | ||||||
|  * <tt>visitEnd</tt>. |  * <tt>visitEnd</tt>. | ||||||
|  | @ -43,7 +43,7 @@ public abstract class ClassVisitor { | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * The ASM API version implemented by this visitor. The value of this field |      * 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; |     protected final int api; | ||||||
| 
 | 
 | ||||||
|  | @ -58,7 +58,7 @@ public abstract class ClassVisitor { | ||||||
|      *  |      *  | ||||||
|      * @param api |      * @param api | ||||||
|      *            the ASM API version implemented by this visitor. Must be one |      *            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) { |     public ClassVisitor(final int api) { | ||||||
|         this(api, null); |         this(api, null); | ||||||
|  | @ -69,13 +69,13 @@ public abstract class ClassVisitor { | ||||||
|      *  |      *  | ||||||
|      * @param api |      * @param api | ||||||
|      *            the ASM API version implemented by this visitor. Must be one |      *            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 |      * @param cv | ||||||
|      *            the class visitor to which this visitor must delegate method |      *            the class visitor to which this visitor must delegate method | ||||||
|      *            calls. May be null. |      *            calls. May be null. | ||||||
|      */ |      */ | ||||||
|     public ClassVisitor(final int api, final ClassVisitor cv) { |     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(); |             throw new IllegalArgumentException(); | ||||||
|         } |         } | ||||||
|         this.api = api; |         this.api = api; | ||||||
|  | @ -131,6 +131,28 @@ public abstract class ClassVisitor { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * 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 <tt>null</tt> 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 |      * Visits the enclosing class of the class. This method must be called only | ||||||
|      * if the class has an enclosing class. |      * if the class has an enclosing class. | ||||||
|  |  | ||||||
|  | @ -173,6 +173,11 @@ public class ClassWriter extends ClassVisitor { | ||||||
|      */ |      */ | ||||||
|     static final int ASM_LABEL_INSN = 18; |     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 |      * 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 |      * frame can only be used if the frame content can be computed from the | ||||||
|  | @ -258,10 +263,20 @@ public class ClassWriter extends ClassVisitor { | ||||||
|      */ |      */ | ||||||
|     static final int INDY = 18; |     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. |      * The base value for all CONSTANT_MethodHandle constant pool items. | ||||||
|      * Internally, ASM store the 9 variations of CONSTANT_MethodHandle into 9 |      * 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; |     static final int HANDLE_BASE = 20; | ||||||
| 
 | 
 | ||||||
|  | @ -410,6 +425,11 @@ public class ClassWriter extends ClassVisitor { | ||||||
|      */ |      */ | ||||||
|     private ByteVector sourceDebug; |     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 |      * The constant pool item that contains the name of the enclosing class of | ||||||
|      * this class. |      * this class. | ||||||
|  | @ -523,11 +543,11 @@ public class ClassWriter extends ClassVisitor { | ||||||
|      */ |      */ | ||||||
|     static { |     static { | ||||||
|         int i; |         int i; | ||||||
|         byte[] b = new byte[220]; |         byte[] b = new byte[221]; | ||||||
|         String s = "AAAAAAAAAAAAAAAABCLMMDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD" |         String s = "AAAAAAAAAAAAAAAABCLMMDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD" | ||||||
|                 + "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" |                 + "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" | ||||||
|                 + "AAAAAAAAAAAAAAAAANAAAAAAAAAAAAAAAAAAAAJJJJJJJJJJJJJJJJDOPAA" |                 + "AAAAAAAAAAAAAAAAANAAAAAAAAAAAAAAAAAAAAJJJJJJJJJJJJJJJJDOPAA" | ||||||
|                 + "AAAAGGGGGGGHIFBFAAFFAARQJJKKSSSSSSSSSSSSSSSSSS"; |                 + "AAAAGGGGGGGHIFBFAAFFAARQJJKKSSSSSSSSSSSSSSSSSST"; | ||||||
|         for (i = 0; i < b.length; ++i) { |         for (i = 0; i < b.length; ++i) { | ||||||
|             b[i] = (byte) (s.charAt(i) - 'A'); |             b[i] = (byte) (s.charAt(i) - 'A'); | ||||||
|         } |         } | ||||||
|  | @ -583,6 +603,7 @@ public class ClassWriter extends ClassVisitor { | ||||||
|         // for (i = 202; i < 220; ++i) { |         // for (i = 202; i < 220; ++i) { | ||||||
|         // b[i] = ASM_LABEL_INSN; |         // b[i] = ASM_LABEL_INSN; | ||||||
|         // } |         // } | ||||||
|  |         // b[220] = ASM_LABELW_INSN; | ||||||
|         // |         // | ||||||
|         // // LDC(_W) instructions |         // // LDC(_W) instructions | ||||||
|         // b[Constants.LDC] = LDC_INSN; |         // b[Constants.LDC] = LDC_INSN; | ||||||
|  | @ -615,7 +636,7 @@ public class ClassWriter extends ClassVisitor { | ||||||
|      *            {@link #COMPUTE_FRAMES}. |      *            {@link #COMPUTE_FRAMES}. | ||||||
|      */ |      */ | ||||||
|     public ClassWriter(final int flags) { |     public ClassWriter(final int flags) { | ||||||
|         super(Opcodes.ASM5); |         super(Opcodes.ASM6); | ||||||
|         index = 1; |         index = 1; | ||||||
|         pool = new ByteVector(); |         pool = new ByteVector(); | ||||||
|         items = new Item[256]; |         items = new Item[256]; | ||||||
|  | @ -703,6 +724,14 @@ public class ClassWriter extends ClassVisitor { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     @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 |     @Override | ||||||
|     public final void visitOuterClass(final String owner, final String name, |     public final void visitOuterClass(final String owner, final String name, | ||||||
|             final String desc) { |             final String desc) { | ||||||
|  | @ -777,7 +806,7 @@ public class ClassWriter extends ClassVisitor { | ||||||
|         // and equality tests). If so we store the index of this inner class |         // and equality tests). If so we store the index of this inner class | ||||||
|         // entry (plus one) in intVal. This hack allows duplicate detection in |         // entry (plus one) in intVal. This hack allows duplicate detection in | ||||||
|         // O(1) time. |         // O(1) time. | ||||||
|         Item nameItem = newClassItem(name); |         Item nameItem = newStringishItem(CLASS, name); | ||||||
|         if (nameItem.intVal == 0) { |         if (nameItem.intVal == 0) { | ||||||
|             ++innerClassesCount; |             ++innerClassesCount; | ||||||
|             innerClasses.putShort(nameItem.index); |             innerClasses.putShort(nameItem.index); | ||||||
|  | @ -904,6 +933,11 @@ public class ClassWriter extends ClassVisitor { | ||||||
|             size += 8 + itanns.getSize(); |             size += 8 + itanns.getSize(); | ||||||
|             newUTF8("RuntimeInvisibleTypeAnnotations"); |             newUTF8("RuntimeInvisibleTypeAnnotations"); | ||||||
|         } |         } | ||||||
|  |         if (moduleWriter != null) { | ||||||
|  |             attributeCount += 1 + moduleWriter.attributeCount; | ||||||
|  |             size += 6 + moduleWriter.size + moduleWriter.attributesSize; | ||||||
|  |             newUTF8("Module"); | ||||||
|  |         } | ||||||
|         if (attrs != null) { |         if (attrs != null) { | ||||||
|             attributeCount += attrs.getCount(); |             attributeCount += attrs.getCount(); | ||||||
|             size += attrs.getSize(this, null, 0, -1, -1); |             size += attrs.getSize(this, null, 0, -1, -1); | ||||||
|  | @ -951,6 +985,11 @@ public class ClassWriter extends ClassVisitor { | ||||||
|             out.putShort(newUTF8("SourceDebugExtension")).putInt(len); |             out.putShort(newUTF8("SourceDebugExtension")).putInt(len); | ||||||
|             out.putByteArray(sourceDebug.data, 0, len); |             out.putByteArray(sourceDebug.data, 0, len); | ||||||
|         } |         } | ||||||
|  |         if (moduleWriter != null) { | ||||||
|  |             out.putShort(newUTF8("Module")); | ||||||
|  |             moduleWriter.put(out); | ||||||
|  |             moduleWriter.putAttributes(out); | ||||||
|  |         } | ||||||
|         if (enclosingMethodOwner != 0) { |         if (enclosingMethodOwner != 0) { | ||||||
|             out.putShort(newUTF8("EnclosingMethod")).putInt(4); |             out.putShort(newUTF8("EnclosingMethod")).putInt(4); | ||||||
|             out.putShort(enclosingMethodOwner).putShort(enclosingMethod); |             out.putShort(enclosingMethodOwner).putShort(enclosingMethod); | ||||||
|  | @ -989,18 +1028,26 @@ public class ClassWriter extends ClassVisitor { | ||||||
|             attrs.put(this, null, 0, -1, -1, out); |             attrs.put(this, null, 0, -1, -1, out); | ||||||
|         } |         } | ||||||
|         if (hasAsmInsns) { |         if (hasAsmInsns) { | ||||||
|  |             boolean hasFrames = false; | ||||||
|  |             mb = firstMethod; | ||||||
|  |             while (mb != null) { | ||||||
|  |                 hasFrames |= mb.frameCount > 0; | ||||||
|  |                 mb = (MethodWriter) mb.mv; | ||||||
|  |             } | ||||||
|             anns = null; |             anns = null; | ||||||
|             ianns = null; |             ianns = null; | ||||||
|             attrs = null; |             attrs = null; | ||||||
|  |             moduleWriter = null; | ||||||
|             innerClassesCount = 0; |             innerClassesCount = 0; | ||||||
|             innerClasses = null; |             innerClasses = null; | ||||||
|             firstField = null; |             firstField = null; | ||||||
|             lastField = null; |             lastField = null; | ||||||
|             firstMethod = null; |             firstMethod = null; | ||||||
|             lastMethod = null; |             lastMethod = null; | ||||||
|             compute = MethodWriter.INSERTED_FRAMES; |             compute = hasFrames ? MethodWriter.INSERTED_FRAMES : 0; | ||||||
|             hasAsmInsns = false; |             hasAsmInsns = false; | ||||||
|             new ClassReader(out.data).accept(this, ClassReader.EXPAND_FRAMES |             new ClassReader(out.data).accept(this, | ||||||
|  |                     (hasFrames ? ClassReader.EXPAND_FRAMES : 0) | ||||||
|                     | ClassReader.EXPAND_ASM_INSNS); |                     | ClassReader.EXPAND_ASM_INSNS); | ||||||
|             return toByteArray(); |             return toByteArray(); | ||||||
|         } |         } | ||||||
|  | @ -1048,16 +1095,16 @@ public class ClassWriter extends ClassVisitor { | ||||||
|             double val = ((Double) cst).doubleValue(); |             double val = ((Double) cst).doubleValue(); | ||||||
|             return newDouble(val); |             return newDouble(val); | ||||||
|         } else if (cst instanceof String) { |         } else if (cst instanceof String) { | ||||||
|             return newString((String) cst); |             return newStringishItem(STR, (String) cst); | ||||||
|         } else if (cst instanceof Type) { |         } else if (cst instanceof Type) { | ||||||
|             Type t = (Type) cst; |             Type t = (Type) cst; | ||||||
|             int s = t.getSort(); |             int s = t.getSort(); | ||||||
|             if (s == Type.OBJECT) { |             if (s == Type.OBJECT) { | ||||||
|                 return newClassItem(t.getInternalName()); |                 return newStringishItem(CLASS, t.getInternalName()); | ||||||
|             } else if (s == Type.METHOD) { |             } else if (s == Type.METHOD) { | ||||||
|                 return newMethodTypeItem(t.getDescriptor()); |                 return newStringishItem(MTYPE, t.getDescriptor()); | ||||||
|             } else { // s == primitive type or array |             } else { // s == primitive type or array | ||||||
|                 return newClassItem(t.getDescriptor()); |                 return newStringishItem(CLASS, t.getDescriptor()); | ||||||
|             } |             } | ||||||
|         } else if (cst instanceof Handle) { |         } else if (cst instanceof Handle) { | ||||||
|             Handle h = (Handle) cst; |             Handle h = (Handle) cst; | ||||||
|  | @ -1106,20 +1153,21 @@ public class ClassWriter extends ClassVisitor { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * 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. |      * Does nothing if the constant pool already contains a similar item. | ||||||
|      * <i>This method is intended for {@link Attribute} sub classes, and is |  | ||||||
|      * normally not needed by class generators or adapters.</i> |  | ||||||
|      *  |      *  | ||||||
|  |      * @param type | ||||||
|  |      *            a type among STR, CLASS, MTYPE, MODULE or PACKAGE | ||||||
|      * @param value |      * @param value | ||||||
|      *            the internal name of the class. |      *            string value of the reference. | ||||||
|      * @return a new or already existing class reference item. |      * @return a new or already existing reference item. | ||||||
|      */ |      */ | ||||||
|     Item newClassItem(final String value) { |     Item newStringishItem(final int type, final String value) { | ||||||
|         key2.set(CLASS, value, null, null); |         key2.set(type, value, null, null); | ||||||
|         Item result = get(key2); |         Item result = get(key2); | ||||||
|         if (result == null) { |         if (result == null) { | ||||||
|             pool.put12(CLASS, newUTF8(value)); |             pool.put12(type, newUTF8(value)); | ||||||
|             result = new Item(index++, key2); |             result = new Item(index++, key2); | ||||||
|             put(result); |             put(result); | ||||||
|         } |         } | ||||||
|  | @ -1137,28 +1185,7 @@ public class ClassWriter extends ClassVisitor { | ||||||
|      * @return the index of a new or already existing class reference item. |      * @return the index of a new or already existing class reference item. | ||||||
|      */ |      */ | ||||||
|     public int newClass(final String value) { |     public int newClass(final String value) { | ||||||
|         return newClassItem(value).index; |         return newStringishItem(CLASS, value).index; | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Adds a method type reference to the constant pool of the class being |  | ||||||
|      * build. Does nothing if the constant pool already contains a similar item. |  | ||||||
|      * <i>This method is intended for {@link Attribute} sub classes, and is |  | ||||||
|      * normally not needed by class generators or adapters.</i> |  | ||||||
|      *  |  | ||||||
|      * @param methodDesc |  | ||||||
|      *            method descriptor of the method type. |  | ||||||
|      * @return 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; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | @ -1173,7 +1200,37 @@ public class ClassWriter extends ClassVisitor { | ||||||
|      *         item. |      *         item. | ||||||
|      */ |      */ | ||||||
|     public int newMethodType(final String methodDesc) { |     public int newMethodType(final String methodDesc) { | ||||||
|         return newMethodTypeItem(methodDesc).index; |         return newStringishItem(MTYPE, methodDesc).index; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Adds a module reference to the constant pool of the class being | ||||||
|  |      * build. Does nothing if the constant pool already contains a similar item. | ||||||
|  |      * <i>This method is intended for {@link Attribute} sub classes, and is | ||||||
|  |      * normally not needed by class generators or adapters.</i> | ||||||
|  |      *  | ||||||
|  |      * @param moduleName | ||||||
|  |      *            name of the module. | ||||||
|  |      * @return the index of a new or already existing module reference | ||||||
|  |      *         item. | ||||||
|  |      */ | ||||||
|  |     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. | ||||||
|  |      * <i>This method is intended for {@link Attribute} sub classes, and is | ||||||
|  |      * normally not needed by class generators or adapters.</i> | ||||||
|  |      * | ||||||
|  |      * @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; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | @ -1554,25 +1611,6 @@ public class ClassWriter extends ClassVisitor { | ||||||
|         return result; |         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 |      * 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. <i>This |      * nothing if the constant pool already contains a similar item. <i>This | ||||||
|  |  | ||||||
|  | @ -40,7 +40,7 @@ public abstract class FieldVisitor { | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * The ASM API version implemented by this visitor. The value of this field |      * 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; |     protected final int api; | ||||||
| 
 | 
 | ||||||
|  | @ -55,7 +55,7 @@ public abstract class FieldVisitor { | ||||||
|      *  |      *  | ||||||
|      * @param api |      * @param api | ||||||
|      *            the ASM API version implemented by this visitor. Must be one |      *            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) { |     public FieldVisitor(final int api) { | ||||||
|         this(api, null); |         this(api, null); | ||||||
|  | @ -66,13 +66,13 @@ public abstract class FieldVisitor { | ||||||
|      *  |      *  | ||||||
|      * @param api |      * @param api | ||||||
|      *            the ASM API version implemented by this visitor. Must be one |      *            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 |      * @param fv | ||||||
|      *            the field visitor to which this visitor must delegate method |      *            the field visitor to which this visitor must delegate method | ||||||
|      *            calls. May be null. |      *            calls. May be null. | ||||||
|      */ |      */ | ||||||
|     public FieldVisitor(final int api, final FieldVisitor fv) { |     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(); |             throw new IllegalArgumentException(); | ||||||
|         } |         } | ||||||
|         this.api = api; |         this.api = api; | ||||||
|  |  | ||||||
|  | @ -118,7 +118,7 @@ final class FieldWriter extends FieldVisitor { | ||||||
|      */ |      */ | ||||||
|     FieldWriter(final ClassWriter cw, final int access, final String name, |     FieldWriter(final ClassWriter cw, final int access, final String name, | ||||||
|             final String desc, final String signature, final Object value) { |             final String desc, final String signature, final Object value) { | ||||||
|         super(Opcodes.ASM5); |         super(Opcodes.ASM6); | ||||||
|         if (cw.firstField == null) { |         if (cw.firstField == null) { | ||||||
|             cw.firstField = this; |             cw.firstField = this; | ||||||
|         } else { |         } else { | ||||||
|  |  | ||||||
|  | @ -51,6 +51,7 @@ final class Item { | ||||||
|      * {@link ClassWriter#STR}, {@link ClassWriter#CLASS}, |      * {@link ClassWriter#STR}, {@link ClassWriter#CLASS}, | ||||||
|      * {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD}, |      * {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD}, | ||||||
|      * {@link ClassWriter#METH}, {@link ClassWriter#IMETH}, |      * {@link ClassWriter#METH}, {@link ClassWriter#IMETH}, | ||||||
|  |      * {@link ClassWriter#MODULE}, {@link ClassWriter#PACKAGE}, | ||||||
|      * {@link ClassWriter#MTYPE}, {@link ClassWriter#INDY}. |      * {@link ClassWriter#MTYPE}, {@link ClassWriter#INDY}. | ||||||
|      *  |      *  | ||||||
|      * MethodHandle constant 9 variations are stored using a range of 9 values |      * MethodHandle constant 9 variations are stored using a range of 9 values | ||||||
|  | @ -214,6 +215,8 @@ final class Item { | ||||||
|         case ClassWriter.UTF8: |         case ClassWriter.UTF8: | ||||||
|         case ClassWriter.STR: |         case ClassWriter.STR: | ||||||
|         case ClassWriter.MTYPE: |         case ClassWriter.MTYPE: | ||||||
|  |         case ClassWriter.MODULE: | ||||||
|  |         case ClassWriter.PACKAGE: | ||||||
|         case ClassWriter.TYPE_NORMAL: |         case ClassWriter.TYPE_NORMAL: | ||||||
|             hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()); |             hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()); | ||||||
|             return; |             return; | ||||||
|  | @ -282,6 +285,8 @@ final class Item { | ||||||
|         case ClassWriter.UTF8: |         case ClassWriter.UTF8: | ||||||
|         case ClassWriter.STR: |         case ClassWriter.STR: | ||||||
|         case ClassWriter.CLASS: |         case ClassWriter.CLASS: | ||||||
|  |         case ClassWriter.MODULE: | ||||||
|  |         case ClassWriter.PACKAGE: | ||||||
|         case ClassWriter.MTYPE: |         case ClassWriter.MTYPE: | ||||||
|         case ClassWriter.TYPE_NORMAL: |         case ClassWriter.TYPE_NORMAL: | ||||||
|             return i.strVal1.equals(strVal1); |             return i.strVal1.equals(strVal1); | ||||||
|  |  | ||||||
|  | @ -57,7 +57,7 @@ public abstract class MethodVisitor { | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * The ASM API version implemented by this visitor. The value of this field |      * 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; |     protected final int api; | ||||||
| 
 | 
 | ||||||
|  | @ -72,7 +72,7 @@ public abstract class MethodVisitor { | ||||||
|      *  |      *  | ||||||
|      * @param api |      * @param api | ||||||
|      *            the ASM API version implemented by this visitor. Must be one |      *            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) { |     public MethodVisitor(final int api) { | ||||||
|         this(api, null); |         this(api, null); | ||||||
|  | @ -83,13 +83,13 @@ public abstract class MethodVisitor { | ||||||
|      *  |      *  | ||||||
|      * @param api |      * @param api | ||||||
|      *            the ASM API version implemented by this visitor. Must be one |      *            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 |      * @param mv | ||||||
|      *            the method visitor to which this visitor must delegate method |      *            the method visitor to which this visitor must delegate method | ||||||
|      *            calls. May be null. |      *            calls. May be null. | ||||||
|      */ |      */ | ||||||
|     public MethodVisitor(final int api, final MethodVisitor mv) { |     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(); |             throw new IllegalArgumentException(); | ||||||
|         } |         } | ||||||
|         this.api = api; |         this.api = api; | ||||||
|  |  | ||||||
|  | @ -260,7 +260,7 @@ class MethodWriter extends MethodVisitor { | ||||||
|     /** |     /** | ||||||
|      * Number of stack map frames in the StackMapTable attribute. |      * Number of stack map frames in the StackMapTable attribute. | ||||||
|      */ |      */ | ||||||
|     private int frameCount; |     int frameCount; | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * The StackMapTable attribute. |      * The StackMapTable attribute. | ||||||
|  | @ -456,7 +456,7 @@ class MethodWriter extends MethodVisitor { | ||||||
|     MethodWriter(final ClassWriter cw, final int access, final String name, |     MethodWriter(final ClassWriter cw, final int access, final String name, | ||||||
|             final String desc, final String signature, |             final String desc, final String signature, | ||||||
|             final String[] exceptions, final int compute) { |             final String[] exceptions, final int compute) { | ||||||
|         super(Opcodes.ASM5); |         super(Opcodes.ASM6); | ||||||
|         if (cw.firstMethod == null) { |         if (cw.firstMethod == null) { | ||||||
|             cw.firstMethod = this; |             cw.firstMethod = this; | ||||||
|         } else { |         } else { | ||||||
|  | @ -848,7 +848,7 @@ class MethodWriter extends MethodVisitor { | ||||||
|     @Override |     @Override | ||||||
|     public void visitTypeInsn(final int opcode, final String type) { |     public void visitTypeInsn(final int opcode, final String type) { | ||||||
|         lastCodeOffset = code.length; |         lastCodeOffset = code.length; | ||||||
|         Item i = cw.newClassItem(type); |         Item i = cw.newStringishItem(ClassWriter.CLASS, type); | ||||||
|         // Label currentBlock = this.currentBlock; |         // Label currentBlock = this.currentBlock; | ||||||
|         if (currentBlock != null) { |         if (currentBlock != null) { | ||||||
|             if (compute == FRAMES || compute == INSERTED_FRAMES) { |             if (compute == FRAMES || compute == INSERTED_FRAMES) { | ||||||
|  | @ -1050,8 +1050,8 @@ class MethodWriter extends MethodVisitor { | ||||||
|             /* |             /* | ||||||
|              * case of a backward jump with an offset < -32768. In this case we |              * 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 |              * automatically replace GOTO with GOTO_W, JSR with JSR_W and IFxxx | ||||||
|              * <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is the |              * <l> with IFNOTxxx <L> GOTO_W <l> L:..., where IFNOTxxx is the | ||||||
|              * "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) and where <l'> |              * "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) and where <L> | ||||||
|              * designates the instruction just after the GOTO_W. |              * designates the instruction just after the GOTO_W. | ||||||
|              */ |              */ | ||||||
|             if (opcode == Opcodes.GOTO) { |             if (opcode == Opcodes.GOTO) { | ||||||
|  | @ -1067,7 +1067,11 @@ class MethodWriter extends MethodVisitor { | ||||||
|                 code.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1 |                 code.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1 | ||||||
|                         : opcode ^ 1); |                         : opcode ^ 1); | ||||||
|                 code.putShort(8); // jump offset |                 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); |             label.put(this, code, code.length - 1, true); | ||||||
|         } else if (isWide) { |         } else if (isWide) { | ||||||
|  | @ -1291,7 +1295,7 @@ class MethodWriter extends MethodVisitor { | ||||||
|     @Override |     @Override | ||||||
|     public void visitMultiANewArrayInsn(final String desc, final int dims) { |     public void visitMultiANewArrayInsn(final String desc, final int dims) { | ||||||
|         lastCodeOffset = code.length; |         lastCodeOffset = code.length; | ||||||
|         Item i = cw.newClassItem(desc); |         Item i = cw.newStringishItem(ClassWriter.CLASS, desc); | ||||||
|         // Label currentBlock = this.currentBlock; |         // Label currentBlock = this.currentBlock; | ||||||
|         if (currentBlock != null) { |         if (currentBlock != null) { | ||||||
|             if (compute == FRAMES || compute == INSERTED_FRAMES) { |             if (compute == FRAMES || compute == INSERTED_FRAMES) { | ||||||
|  |  | ||||||
|  | @ -0,0 +1,178 @@ | ||||||
|  | /*** | ||||||
|  |  * 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 org.springframework.asm; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A visitor to visit a Java module. The methods of this class must be called in | ||||||
|  |  * the following order: <tt>visitVersion</tt> | <tt>visitMainClass</tt> | | ||||||
|  |  * <tt>visitTargetPlatform</tt> | ( <tt>visitConcealedPackage</tt> | <tt>visitRequire</tt> | | ||||||
|  |  * <tt>visitExport</tt> | <tt>visitUse</tt> | <tt>visitProvide</tt> )* <tt>visitEnd</tt>. | ||||||
|  |  *  | ||||||
|  |  * @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; | ||||||
|  |      | ||||||
|  |      | ||||||
|  |     public ModuleVisitor(final int api) { | ||||||
|  |         this(api, null); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new {@link MethodVisitor}. | ||||||
|  |      *  | ||||||
|  |      * @param api | ||||||
|  |      *            the ASM API version implemented by this visitor. Must be {@link Opcodes#ASM6}. | ||||||
|  |      * @param mv | ||||||
|  |      *            the method 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 main class of the current module. | ||||||
|  |      */ | ||||||
|  |     public void visitMainClass(String mainClass) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitMainClass(mainClass); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     /** | ||||||
|  |      * Visit a concealed package of the current module. | ||||||
|  |      *  | ||||||
|  |      * @param packaze name of a concealed package | ||||||
|  |      */ | ||||||
|  |     public void visitPackage(String packaze) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitPackage(packaze); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     /** | ||||||
|  |      * Visits a dependence of the current module. | ||||||
|  |      *  | ||||||
|  |      * @param module the module 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 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 names of the modules that can access to | ||||||
|  |      *        the public classes of the exported package or | ||||||
|  |      *        <tt>null</tt>. | ||||||
|  |      */ | ||||||
|  |     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 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 names of the modules that can use deep | ||||||
|  |      *        reflection to the classes of the open package or | ||||||
|  |      *        <tt>null</tt>. | ||||||
|  |      */ | ||||||
|  |     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 name of an interface or an | ||||||
|  |      * abstract 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); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     public void visitEnd() { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitEnd(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -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 org.springframework.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); | ||||||
|  |         } | ||||||
|  |     }     | ||||||
|  | } | ||||||
|  | @ -47,6 +47,7 @@ public interface Opcodes { | ||||||
| 
 | 
 | ||||||
|     int ASM4 = 4 << 16 | 0 << 8 | 0; |     int ASM4 = 4 << 16 | 0 << 8 | 0; | ||||||
|     int ASM5 = 5 << 16 | 0 << 8 | 0; |     int ASM5 = 5 << 16 | 0 << 8 | 0; | ||||||
|  |     int ASM6 = 6 << 16 | 0 << 8 | 0; | ||||||
| 
 | 
 | ||||||
|     // versions |     // versions | ||||||
| 
 | 
 | ||||||
|  | @ -58,6 +59,7 @@ public interface Opcodes { | ||||||
|     int V1_6 = 0 << 16 | 50; |     int V1_6 = 0 << 16 | 50; | ||||||
|     int V1_7 = 0 << 16 | 51; |     int V1_7 = 0 << 16 | 51; | ||||||
|     int V1_8 = 0 << 16 | 52; |     int V1_8 = 0 << 16 | 52; | ||||||
|  |     int V1_9 = 0 << 16 | 53; | ||||||
| 
 | 
 | ||||||
|     // access flags |     // access flags | ||||||
| 
 | 
 | ||||||
|  | @ -68,18 +70,23 @@ public interface Opcodes { | ||||||
|     int ACC_FINAL = 0x0010; // class, field, method, parameter |     int ACC_FINAL = 0x0010; // class, field, method, parameter | ||||||
|     int ACC_SUPER = 0x0020; // class |     int ACC_SUPER = 0x0020; // class | ||||||
|     int ACC_SYNCHRONIZED = 0x0020; // method |     int ACC_SYNCHRONIZED = 0x0020; // method | ||||||
|  |     int ACC_OPEN = 0x0020; // module | ||||||
|  |     int ACC_TRANSITIVE = 0x0020; // module requires | ||||||
|     int ACC_VOLATILE = 0x0040; // field |     int ACC_VOLATILE = 0x0040; // field | ||||||
|     int ACC_BRIDGE = 0x0040; // method |     int ACC_BRIDGE = 0x0040; // method | ||||||
|  |     int ACC_STATIC_PHASE = 0x0040; // module requires | ||||||
|     int ACC_VARARGS = 0x0080; // method |     int ACC_VARARGS = 0x0080; // method | ||||||
|     int ACC_TRANSIENT = 0x0080; // field |     int ACC_TRANSIENT = 0x0080; // field | ||||||
|     int ACC_NATIVE = 0x0100; // method |     int ACC_NATIVE = 0x0100; // method | ||||||
|     int ACC_INTERFACE = 0x0200; // class |     int ACC_INTERFACE = 0x0200; // class | ||||||
|     int ACC_ABSTRACT = 0x0400; // class, method |     int ACC_ABSTRACT = 0x0400; // class, method | ||||||
|     int ACC_STRICT = 0x0800; // 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_ANNOTATION = 0x2000; // class | ||||||
|     int ACC_ENUM = 0x4000; // class(?) field inner |     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 |     // ASM specific pseudo access flags | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| /* | /* | ||||||
|  * Copyright 2002-2014 the original author or authors. |  * Copyright 2002-2017 the original author or authors. | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
|  | @ -30,8 +30,8 @@ public final class SpringAsmInfo { | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * The ASM compatibility version for Spring's ASM visitor implementations: | 	 * The ASM compatibility version for Spring's ASM visitor implementations: | ||||||
| 	 * currently {@link Opcodes#ASM5}. | 	 * currently {@link Opcodes#ASM6}. | ||||||
| 	 */ | 	 */ | ||||||
| 	public static final int ASM_VERSION = Opcodes.ASM5; | 	public static final int ASM_VERSION = Opcodes.ASM6; | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue