summaryrefslogtreecommitdiff
path: root/spring-core/src/main/java
diff options
context:
space:
mode:
authorMarkus Koschany <apo@debian.org>2018-02-09 22:51:36 +0100
committerMarkus Koschany <apo@debian.org>2018-02-09 22:51:36 +0100
commit6dc3d6835b664af0d21e774a5342b90d4417f628 (patch)
treec9f61a10de6abdffba88c8ea6d1dcab09c96603a /spring-core/src/main/java
parent1cb0ad9c5dd218623094b3d6369be7a949094e8d (diff)
New upstream version 4.3.14
Diffstat (limited to 'spring-core/src/main/java')
-rw-r--r--spring-core/src/main/java/org/springframework/asm/AnnotationVisitor.java8
-rw-r--r--spring-core/src/main/java/org/springframework/asm/AnnotationWriter.java2
-rw-r--r--spring-core/src/main/java/org/springframework/asm/ClassReader.java233
-rw-r--r--spring-core/src/main/java/org/springframework/asm/ClassVisitor.java32
-rw-r--r--spring-core/src/main/java/org/springframework/asm/ClassWriter.java148
-rw-r--r--spring-core/src/main/java/org/springframework/asm/FieldVisitor.java8
-rw-r--r--spring-core/src/main/java/org/springframework/asm/FieldWriter.java2
-rw-r--r--spring-core/src/main/java/org/springframework/asm/Item.java5
-rw-r--r--spring-core/src/main/java/org/springframework/asm/MethodVisitor.java8
-rw-r--r--spring-core/src/main/java/org/springframework/asm/MethodWriter.java18
-rw-r--r--spring-core/src/main/java/org/springframework/asm/ModuleVisitor.java178
-rw-r--r--spring-core/src/main/java/org/springframework/asm/ModuleWriter.java293
-rw-r--r--spring-core/src/main/java/org/springframework/asm/Opcodes.java11
-rw-r--r--spring-core/src/main/java/org/springframework/asm/SpringAsmInfo.java6
-rw-r--r--spring-core/src/main/java/org/springframework/core/BridgeMethodResolver.java7
-rw-r--r--spring-core/src/main/java/org/springframework/core/convert/Property.java6
-rw-r--r--spring-core/src/main/java/org/springframework/core/env/JOptCommandLinePropertySource.java8
-rw-r--r--spring-core/src/main/java/org/springframework/core/io/support/PathMatchingResourcePatternResolver.java18
-rw-r--r--spring-core/src/main/java/org/springframework/core/type/classreading/SimpleMetadataReaderFactory.java18
19 files changed, 879 insertions, 130 deletions
diff --git a/spring-core/src/main/java/org/springframework/asm/AnnotationVisitor.java b/spring-core/src/main/java/org/springframework/asm/AnnotationVisitor.java
index c2d30f58..5300eb85 100644
--- a/spring-core/src/main/java/org/springframework/asm/AnnotationVisitor.java
+++ b/spring-core/src/main/java/org/springframework/asm/AnnotationVisitor.java
@@ -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;
@@ -56,7 +56,7 @@ public abstract class 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);
@@ -67,13 +67,13 @@ public abstract class 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;
diff --git a/spring-core/src/main/java/org/springframework/asm/AnnotationWriter.java b/spring-core/src/main/java/org/springframework/asm/AnnotationWriter.java
index dcd88357..c07a2b41 100644
--- a/spring-core/src/main/java/org/springframework/asm/AnnotationWriter.java
+++ b/spring-core/src/main/java/org/springframework/asm/AnnotationWriter.java
@@ -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;
diff --git a/spring-core/src/main/java/org/springframework/asm/ClassReader.java b/spring-core/src/main/java/org/springframework/asm/ClassReader.java
index 9cca0b5a..80eeb835 100644
--- a/spring-core/src/main/java/org/springframework/asm/ClassReader.java
+++ b/spring-core/src/main/java/org/springframework/asm/ClassReader.java
@@ -222,6 +222,8 @@ public class ClassReader {
// case ClassWriter.CLASS:
// case ClassWriter.STR:
// case ClassWriter.MTYPE
+ // case ClassWriter.PACKAGE:
+ // case ClassWriter.MODULE:
default:
size = 3;
break;
@@ -365,7 +367,9 @@ public class ClassReader {
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;
@@ -572,11 +576,14 @@ public class ClassReader {
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();
@@ -617,6 +624,12 @@ public class ClassReader {
} else if (ANNOTATIONS
&& "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++) {
@@ -645,6 +658,12 @@ public class ClassReader {
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,
@@ -715,6 +734,120 @@ public class ClassReader {
}
/**
+ * 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
@@ -1082,6 +1215,7 @@ public class ClassReader {
u += 3;
break;
case ClassWriter.LABELW_INSN:
+ case ClassWriter.ASM_LABELW_INSN:
readLabel(offset + readInt(u + 1), labels);
u += 5;
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
// frames, even if the method does not currently have any frame.
// Also these inserted frames must be computed by simulating the
@@ -1322,6 +1457,7 @@ public class ClassReader {
// 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;
@@ -1354,6 +1490,9 @@ public class ClassReader {
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);
@@ -1362,6 +1501,13 @@ public class ClassReader {
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
int opcode = b[u] & 0xFF;
@@ -1397,31 +1543,36 @@ public class ClassReader {
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
- // <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)
- // and where <l'> designates the instruction just after
+ // and where <L> 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 = new Label();
+ Label endif = readLabel(offset + 3, labels);
mv.visitJumpInsn(opcode, endif);
mv.visitJumpInsn(200, target); // GOTO_W
- mv.visitLabel(endif);
- // since we introduced an unconditional jump instruction we
- // also need to insert a stack map frame here, unless there
- // is already one. The actual frame content will be computed
- // in MethodWriter.
- if (FRAMES && stackMap != 0
- && (frame == null || frame.offset != offset + 3)) {
- mv.visitFrame(ClassWriter.F_INSERT, 0, null, 0, null);
- }
+ // 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 <L> GOTO_W <l> 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) {
@@ -2517,6 +2668,20 @@ public class ClassReader {
}
/**
+ * 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
* intended for {@link Attribute} sub classes, and is normally not needed by
* class generators or adapters.</i>
@@ -2530,11 +2695,41 @@ public class ClassReader {
* @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
- String name = readUTF8(items[readUnsignedShort(index)], buf);
- return (name != null ? name.intern() : null);
+ 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 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);
}
/**
diff --git a/spring-core/src/main/java/org/springframework/asm/ClassVisitor.java b/spring-core/src/main/java/org/springframework/asm/ClassVisitor.java
index ba58188a..a1b09f50 100644
--- a/spring-core/src/main/java/org/springframework/asm/ClassVisitor.java
+++ b/spring-core/src/main/java/org/springframework/asm/ClassVisitor.java
@@ -32,7 +32,7 @@ package org.springframework.asm;
/**
* 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> ] [
- * <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> |
+ * <tt>visitModule</tt> ][ <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> |
* <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* (
* <tt>visitInnerClass</tt> | <tt>visitField</tt> | <tt>visitMethod</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
- * 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;
@@ -58,7 +58,7 @@ public abstract class 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);
@@ -69,13 +69,13 @@ public abstract class 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;
@@ -132,6 +132,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
* if the class has an enclosing class.
*
diff --git a/spring-core/src/main/java/org/springframework/asm/ClassWriter.java b/spring-core/src/main/java/org/springframework/asm/ClassWriter.java
index 1393c78e..a024937d 100644
--- a/spring-core/src/main/java/org/springframework/asm/ClassWriter.java
+++ b/spring-core/src/main/java/org/springframework/asm/ClassWriter.java
@@ -174,6 +174,11 @@ public class ClassWriter extends ClassVisitor {
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
@@ -259,9 +264,19 @@ 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;
@@ -411,6 +426,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.
*/
@@ -523,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"
- + "AAAAGGGGGGGHIFBFAAFFAARQJJKKSSSSSSSSSSSSSSSSSS";
+ + "AAAAGGGGGGGHIFBFAAFFAARQJJKKSSSSSSSSSSSSSSSSSST";
for (i = 0; i < b.length; ++i) {
b[i] = (byte) (s.charAt(i) - 'A');
}
@@ -583,6 +603,7 @@ public class ClassWriter extends ClassVisitor {
// for (i = 202; i < 220; ++i) {
// b[i] = ASM_LABEL_INSN;
// }
+ // b[220] = ASM_LABELW_INSN;
//
// // LDC(_W) instructions
// b[Constants.LDC] = LDC_INSN;
@@ -615,7 +636,7 @@ public class ClassWriter extends ClassVisitor {
* {@link #COMPUTE_FRAMES}.
*/
public ClassWriter(final int flags) {
- super(Opcodes.ASM5);
+ super(Opcodes.ASM6);
index = 1;
pool = new ByteVector();
items = new Item[256];
@@ -704,6 +725,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
public final void visitOuterClass(final String owner, final String name,
final String desc) {
enclosingMethodOwner = newClass(owner);
@@ -777,7 +806,7 @@ public class ClassWriter extends ClassVisitor {
// 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);
@@ -904,6 +933,11 @@ public class ClassWriter extends ClassVisitor {
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);
@@ -951,6 +985,11 @@ public class ClassWriter extends ClassVisitor {
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);
@@ -989,18 +1028,26 @@ public class ClassWriter extends ClassVisitor {
attrs.put(this, null, 0, -1, -1, out);
}
if (hasAsmInsns) {
+ boolean hasFrames = false;
+ mb = firstMethod;
+ while (mb != null) {
+ hasFrames |= mb.frameCount > 0;
+ mb = (MethodWriter) mb.mv;
+ }
anns = null;
ianns = null;
attrs = null;
+ moduleWriter = null;
innerClassesCount = 0;
innerClasses = null;
firstField = null;
lastField = null;
firstMethod = null;
lastMethod = null;
- compute = MethodWriter.INSERTED_FRAMES;
+ compute = hasFrames ? MethodWriter.INSERTED_FRAMES : 0;
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);
return toByteArray();
}
@@ -1048,16 +1095,16 @@ public class ClassWriter extends ClassVisitor {
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;
@@ -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.
- * <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
- * 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);
}
@@ -1137,7 +1185,7 @@ public class ClassWriter extends ClassVisitor {
* @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;
}
/**
@@ -1148,32 +1196,41 @@ public class ClassWriter extends ClassVisitor {
*
* @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.
* <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 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.
+ * <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;
}
/**
@@ -1555,25 +1612,6 @@ public class ClassWriter extends ClassVisitor {
}
/**
- * 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. <i>This
* method is intended for {@link Attribute} sub classes, and is normally not
diff --git a/spring-core/src/main/java/org/springframework/asm/FieldVisitor.java b/spring-core/src/main/java/org/springframework/asm/FieldVisitor.java
index 2822f3b2..da3d54cb 100644
--- a/spring-core/src/main/java/org/springframework/asm/FieldVisitor.java
+++ b/spring-core/src/main/java/org/springframework/asm/FieldVisitor.java
@@ -40,7 +40,7 @@ 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;
@@ -55,7 +55,7 @@ public abstract class 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);
@@ -66,13 +66,13 @@ public abstract class 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;
diff --git a/spring-core/src/main/java/org/springframework/asm/FieldWriter.java b/spring-core/src/main/java/org/springframework/asm/FieldWriter.java
index f5a135e5..8157d9ad 100644
--- a/spring-core/src/main/java/org/springframework/asm/FieldWriter.java
+++ b/spring-core/src/main/java/org/springframework/asm/FieldWriter.java
@@ -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 {
diff --git a/spring-core/src/main/java/org/springframework/asm/Item.java b/spring-core/src/main/java/org/springframework/asm/Item.java
index 7bebf349..1519a91c 100644
--- a/spring-core/src/main/java/org/springframework/asm/Item.java
+++ b/spring-core/src/main/java/org/springframework/asm/Item.java
@@ -51,6 +51,7 @@ 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
@@ -214,6 +215,8 @@ final class Item {
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;
@@ -282,6 +285,8 @@ final class Item {
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/spring-core/src/main/java/org/springframework/asm/MethodVisitor.java b/spring-core/src/main/java/org/springframework/asm/MethodVisitor.java
index d512aed6..91f76fdc 100644
--- a/spring-core/src/main/java/org/springframework/asm/MethodVisitor.java
+++ b/spring-core/src/main/java/org/springframework/asm/MethodVisitor.java
@@ -57,7 +57,7 @@ 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;
@@ -72,7 +72,7 @@ public abstract class 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);
@@ -83,13 +83,13 @@ public abstract class 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;
diff --git a/spring-core/src/main/java/org/springframework/asm/MethodWriter.java b/spring-core/src/main/java/org/springframework/asm/MethodWriter.java
index c26e4166..e62abf67 100644
--- a/spring-core/src/main/java/org/springframework/asm/MethodWriter.java
+++ b/spring-core/src/main/java/org/springframework/asm/MethodWriter.java
@@ -260,7 +260,7 @@ class MethodWriter extends MethodVisitor {
/**
* Number of stack map frames in the StackMapTable attribute.
*/
- private int frameCount;
+ int frameCount;
/**
* The StackMapTable attribute.
@@ -456,7 +456,7 @@ class MethodWriter extends MethodVisitor {
MethodWriter(final ClassWriter cw, final int access, final String name,
final String desc, final String signature,
final String[] exceptions, final int compute) {
- super(Opcodes.ASM5);
+ super(Opcodes.ASM6);
if (cw.firstMethod == null) {
cw.firstMethod = this;
} else {
@@ -848,7 +848,7 @@ class MethodWriter extends MethodVisitor {
@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 || compute == INSERTED_FRAMES) {
@@ -1050,8 +1050,8 @@ class MethodWriter extends MethodVisitor {
/*
* 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
- * <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is the
- * "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) and where <l'>
+ * <l> with IFNOTxxx <L> GOTO_W <l> L:..., where IFNOTxxx is the
+ * "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) and where <L>
* designates the instruction just after the GOTO_W.
*/
if (opcode == Opcodes.GOTO) {
@@ -1067,7 +1067,11 @@ class MethodWriter extends MethodVisitor {
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) {
@@ -1291,7 +1295,7 @@ class MethodWriter extends MethodVisitor {
@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 || compute == INSERTED_FRAMES) {
diff --git a/spring-core/src/main/java/org/springframework/asm/ModuleVisitor.java b/spring-core/src/main/java/org/springframework/asm/ModuleVisitor.java
new file mode 100644
index 00000000..f6acaeec
--- /dev/null
+++ b/spring-core/src/main/java/org/springframework/asm/ModuleVisitor.java
@@ -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();
+ }
+ }
+}
diff --git a/spring-core/src/main/java/org/springframework/asm/ModuleWriter.java b/spring-core/src/main/java/org/springframework/asm/ModuleWriter.java
new file mode 100644
index 00000000..b4c07ef4
--- /dev/null
+++ b/spring-core/src/main/java/org/springframework/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 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);
+ }
+ }
+}
diff --git a/spring-core/src/main/java/org/springframework/asm/Opcodes.java b/spring-core/src/main/java/org/springframework/asm/Opcodes.java
index a84b300b..0d787996 100644
--- a/spring-core/src/main/java/org/springframework/asm/Opcodes.java
+++ b/spring-core/src/main/java/org/springframework/asm/Opcodes.java
@@ -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 V1_9 = 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
diff --git a/spring-core/src/main/java/org/springframework/asm/SpringAsmInfo.java b/spring-core/src/main/java/org/springframework/asm/SpringAsmInfo.java
index 2ee749a3..438bf394 100644
--- a/spring-core/src/main/java/org/springframework/asm/SpringAsmInfo.java
+++ b/spring-core/src/main/java/org/springframework/asm/SpringAsmInfo.java
@@ -18,7 +18,7 @@ package org.springframework.asm;
/**
* Utility class exposing constants related to Spring's internal repackaging
- * of the ASM bytecode manipulation library (currently based on version 5.2).
+ * of the ASM bytecode manipulation library (currently based on version 6.0).
*
* <p>See <a href="package-summary.html">package-level javadocs</a> for more
* information on {@code org.springframework.asm}.
@@ -30,8 +30,8 @@ public final class SpringAsmInfo {
/**
* 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;
}
diff --git a/spring-core/src/main/java/org/springframework/core/BridgeMethodResolver.java b/spring-core/src/main/java/org/springframework/core/BridgeMethodResolver.java
index 0427317d..45bd0de4 100644
--- a/spring-core/src/main/java/org/springframework/core/BridgeMethodResolver.java
+++ b/spring-core/src/main/java/org/springframework/core/BridgeMethodResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2017 the original author or authors.
+ * Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -192,7 +192,10 @@ public abstract class BridgeMethodResolver {
return method;
}
else {
- return searchInterfaces(ifc.getInterfaces(), bridgeMethod);
+ method = searchInterfaces(ifc.getInterfaces(), bridgeMethod);
+ if (method != null) {
+ return method;
+ }
}
}
return null;
diff --git a/spring-core/src/main/java/org/springframework/core/convert/Property.java b/spring-core/src/main/java/org/springframework/core/convert/Property.java
index e966e736..9c6db43c 100644
--- a/spring-core/src/main/java/org/springframework/core/convert/Property.java
+++ b/spring-core/src/main/java/org/springframework/core/convert/Property.java
@@ -225,11 +225,9 @@ public final class Property {
Field field = ReflectionUtils.findField(declaringClass, name);
if (field == null) {
// Same lenient fallback checking as in CachedIntrospectionResults...
- field = ReflectionUtils.findField(declaringClass,
- name.substring(0, 1).toLowerCase() + name.substring(1));
+ field = ReflectionUtils.findField(declaringClass, StringUtils.uncapitalize(name));
if (field == null) {
- field = ReflectionUtils.findField(declaringClass,
- name.substring(0, 1).toUpperCase() + name.substring(1));
+ field = ReflectionUtils.findField(declaringClass, StringUtils.capitalize(name));
}
}
return field;
diff --git a/spring-core/src/main/java/org/springframework/core/env/JOptCommandLinePropertySource.java b/spring-core/src/main/java/org/springframework/core/env/JOptCommandLinePropertySource.java
index a2ebe347..1dbe1916 100644
--- a/spring-core/src/main/java/org/springframework/core/env/JOptCommandLinePropertySource.java
+++ b/spring-core/src/main/java/org/springframework/core/env/JOptCommandLinePropertySource.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2017 the original author or authors.
+ * Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,6 +23,8 @@ import java.util.List;
import joptsimple.OptionSet;
import joptsimple.OptionSpec;
+import org.springframework.util.StringUtils;
+
/**
* {@link CommandLinePropertySource} implementation backed by a JOpt {@link OptionSet}.
*
@@ -84,13 +86,13 @@ public class JOptCommandLinePropertySource extends CommandLinePropertySource<Opt
public String[] getPropertyNames() {
List<String> names = new ArrayList<String>();
for (OptionSpec<?> spec : this.source.specs()) {
- List<String> aliases = new ArrayList<String>(spec.options());
+ List<String> aliases = spec.options();
if (!aliases.isEmpty()) {
// Only the longest name is used for enumerating
names.add(aliases.get(aliases.size() - 1));
}
}
- return names.toArray(new String[names.size()]);
+ return StringUtils.toStringArray(names);
}
@Override
diff --git a/spring-core/src/main/java/org/springframework/core/io/support/PathMatchingResourcePatternResolver.java b/spring-core/src/main/java/org/springframework/core/io/support/PathMatchingResourcePatternResolver.java
index 41d2da58..f9ae32cf 100644
--- a/spring-core/src/main/java/org/springframework/core/io/support/PathMatchingResourcePatternResolver.java
+++ b/spring-core/src/main/java/org/springframework/core/io/support/PathMatchingResourcePatternResolver.java
@@ -424,7 +424,7 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
int prefixIndex = filePath.indexOf(':');
if (prefixIndex == 1) {
// Possibly "c:" drive prefix on Windows, to be upper-cased for proper duplicate detection
- filePath = filePath.substring(0, 1).toUpperCase() + filePath.substring(1);
+ filePath = StringUtils.capitalize(filePath);
}
UrlResource jarResource = new UrlResource(ResourceUtils.JAR_URL_PREFIX +
ResourceUtils.FILE_URL_PREFIX + filePath + ResourceUtils.JAR_URL_SEPARATOR);
@@ -489,18 +489,18 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
Set<Resource> result = new LinkedHashSet<Resource>(16);
for (Resource rootDirResource : rootDirResources) {
rootDirResource = resolveRootDirResource(rootDirResource);
- URL rootDirURL = rootDirResource.getURL();
+ URL rootDirUrl = rootDirResource.getURL();
if (equinoxResolveMethod != null) {
- if (rootDirURL.getProtocol().startsWith("bundle")) {
- rootDirURL = (URL) ReflectionUtils.invokeMethod(equinoxResolveMethod, null, rootDirURL);
- rootDirResource = new UrlResource(rootDirURL);
+ if (rootDirUrl.getProtocol().startsWith("bundle")) {
+ rootDirUrl = (URL) ReflectionUtils.invokeMethod(equinoxResolveMethod, null, rootDirUrl);
+ rootDirResource = new UrlResource(rootDirUrl);
}
}
- if (rootDirURL.getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {
- result.addAll(VfsResourceMatchingDelegate.findMatchingResources(rootDirURL, subPattern, getPathMatcher()));
+ if (rootDirUrl.getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {
+ result.addAll(VfsResourceMatchingDelegate.findMatchingResources(rootDirUrl, subPattern, getPathMatcher()));
}
- else if (ResourceUtils.isJarURL(rootDirURL) || isJarResource(rootDirResource)) {
- result.addAll(doFindPathMatchingJarResources(rootDirResource, rootDirURL, subPattern));
+ else if (ResourceUtils.isJarURL(rootDirUrl) || isJarResource(rootDirResource)) {
+ result.addAll(doFindPathMatchingJarResources(rootDirResource, rootDirUrl, subPattern));
}
else {
result.addAll(doFindPathMatchingFileResources(rootDirResource, subPattern));
diff --git a/spring-core/src/main/java/org/springframework/core/type/classreading/SimpleMetadataReaderFactory.java b/spring-core/src/main/java/org/springframework/core/type/classreading/SimpleMetadataReaderFactory.java
index c4af4541..d305e22f 100644
--- a/spring-core/src/main/java/org/springframework/core/type/classreading/SimpleMetadataReaderFactory.java
+++ b/spring-core/src/main/java/org/springframework/core/type/classreading/SimpleMetadataReaderFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2014 the original author or authors.
+ * Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
package org.springframework.core.type.classreading;
+import java.io.FileNotFoundException;
import java.io.IOException;
import org.springframework.core.io.DefaultResourceLoader;
@@ -72,10 +73,13 @@ public class SimpleMetadataReaderFactory implements MetadataReaderFactory {
@Override
public MetadataReader getMetadataReader(String className) throws IOException {
- String resourcePath = ResourceLoader.CLASSPATH_URL_PREFIX +
- ClassUtils.convertClassNameToResourcePath(className) + ClassUtils.CLASS_FILE_SUFFIX;
- Resource resource = this.resourceLoader.getResource(resourcePath);
- if (!resource.exists()) {
+ try {
+ String resourcePath = ResourceLoader.CLASSPATH_URL_PREFIX +
+ ClassUtils.convertClassNameToResourcePath(className) + ClassUtils.CLASS_FILE_SUFFIX;
+ Resource resource = this.resourceLoader.getResource(resourcePath);
+ return getMetadataReader(resource);
+ }
+ catch (FileNotFoundException ex) {
// Maybe an inner class name using the dot name syntax? Need to use the dollar syntax here...
// ClassUtils.forName has an equivalent check for resolution into Class references later on.
int lastDotIndex = className.lastIndexOf('.');
@@ -86,11 +90,11 @@ public class SimpleMetadataReaderFactory implements MetadataReaderFactory {
ClassUtils.convertClassNameToResourcePath(innerClassName) + ClassUtils.CLASS_FILE_SUFFIX;
Resource innerClassResource = this.resourceLoader.getResource(innerClassResourcePath);
if (innerClassResource.exists()) {
- resource = innerClassResource;
+ return getMetadataReader(innerClassResource);
}
}
+ throw ex;
}
- return getMetadataReader(resource);
}
@Override