aboutsummaryrefslogtreecommitdiffstats
path: root/bcel-builder/src
diff options
context:
space:
mode:
Diffstat (limited to 'bcel-builder/src')
-rw-r--r--bcel-builder/src/org/aspectj/apache/bcel/Constants.java34
-rw-r--r--bcel-builder/src/org/aspectj/apache/bcel/classfile/Attribute.java6
-rw-r--r--bcel-builder/src/org/aspectj/apache/bcel/classfile/ClassParser.java1
-rw-r--r--bcel-builder/src/org/aspectj/apache/bcel/classfile/ClassVisitor.java9
-rw-r--r--bcel-builder/src/org/aspectj/apache/bcel/classfile/Constant.java2
-rw-r--r--bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantModule.java111
-rw-r--r--bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantPackage.java111
-rw-r--r--bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantPool.java22
-rw-r--r--bcel-builder/src/org/aspectj/apache/bcel/classfile/Module.java664
-rw-r--r--bcel-builder/src/org/aspectj/apache/bcel/classfile/ModuleMainClass.java106
-rw-r--r--bcel-builder/src/org/aspectj/apache/bcel/classfile/ModulePackages.java126
-rw-r--r--bcel-builder/src/org/aspectj/apache/bcel/util/ClassPath.java759
12 files changed, 1649 insertions, 302 deletions
diff --git a/bcel-builder/src/org/aspectj/apache/bcel/Constants.java b/bcel-builder/src/org/aspectj/apache/bcel/Constants.java
index 0bba78fc4..5f37d106a 100644
--- a/bcel-builder/src/org/aspectj/apache/bcel/Constants.java
+++ b/bcel-builder/src/org/aspectj/apache/bcel/Constants.java
@@ -80,6 +80,8 @@ public interface Constants {
public final static short MINOR_1_7 = 0;
public final static short MAJOR_1_8 = 52;
public final static short MINOR_1_8 = 0;
+ public final static short MAJOR_1_9 = 53;
+ public final static short MINOR_1_9 = 0;
// Defaults
public final static short MAJOR = MAJOR_1_1;
public final static short MINOR = MINOR_1_1;
@@ -107,11 +109,27 @@ public interface Constants {
public final static short ACC_STRICT = 0x0800;
public final static short ACC_SYNTHETIC = 0x1000;
+
public final static short ACC_ANNOTATION = 0x2000;
public final static short ACC_ENUM = 0x4000;
+ public final static int ACC_MODULE = 0x8000;
public final static short ACC_BRIDGE = 0x0040;
public final static short ACC_VARARGS = 0x0080;
+ // Module related
+ // Indicates that any module which depends on the current module,
+ // implicitly declares a dependence on the module indicated by this entry.
+ public final static int MODULE_ACC_TRANSITIVE = 0x0020;
+ // Indicates that this dependence is mandatory in the static phase, i.e., at
+ // compile time, but is optional in the dynamic phase, i.e., at run time.
+ public final static int MODULE_ACC_STATIC_PHASE = 0x0040;
+ // Indicates that this dependence was not explicitly or implicitly declared
+ // in the source of the module declaration.
+ public final static int MODULE_ACC_SYNTHETIC = 0x1000;
+ // Indicates that this dependence was implicitly declared in the source of
+ // the module declaration
+ public final static int MODULE_ACC_MANDATED = 0x8000;
+
// Applies to classes compiled by new compilers only
public final static short ACC_SUPER = 0x0020;
@@ -136,6 +154,11 @@ public interface Constants {
public final static byte CONSTANT_MethodHandle = 15;
public final static byte CONSTANT_MethodType = 16;
public final static byte CONSTANT_InvokeDynamic = 18;
+
+ // Java 9
+ public final static byte CONSTANT_Module = 19;
+ public final static byte CONSTANT_Package = 20;
+
public final static String[] CONSTANT_NAMES = { "", "CONSTANT_Utf8", "", "CONSTANT_Integer", "CONSTANT_Float", "CONSTANT_Long",
"CONSTANT_Double", "CONSTANT_Class", "CONSTANT_String", "CONSTANT_Fieldref", "CONSTANT_Methodref",
@@ -617,8 +640,13 @@ public interface Constants {
public static final byte ATTR_RUNTIME_VISIBLE_TYPE_ANNOTATIONS = 20;
public static final byte ATTR_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS = 21;
public static final byte ATTR_METHOD_PARAMETERS = 22;
-
- public static final short KNOWN_ATTRIBUTES = 23;
+
+ // J9:
+ public static final byte ATTR_MODULE = 23;
+ public static final byte ATTR_MODULE_PACKAGES = 24;
+ public static final byte ATTR_MODULE_MAIN_CLASS = 25;
+
+ public static final short KNOWN_ATTRIBUTES = 26;
public static final String[] ATTRIBUTE_NAMES = {
"SourceFile", "ConstantValue", "Code", "Exceptions", "LineNumberTable", "LocalVariableTable",
@@ -626,7 +654,7 @@ public interface Constants {
"RuntimeVisibleAnnotations", "RuntimeInvisibleAnnotations", "RuntimeVisibleParameterAnnotations",
"RuntimeInvisibleParameterAnnotations", "LocalVariableTypeTable", "EnclosingMethod",
"AnnotationDefault","BootstrapMethods", "RuntimeVisibleTypeAnnotations", "RuntimeInvisibleTypeAnnotations",
- "MethodParameters"
+ "MethodParameters", "Module", "ModulePackages", "ModuleMainClass"
};
/**
diff --git a/bcel-builder/src/org/aspectj/apache/bcel/classfile/Attribute.java b/bcel-builder/src/org/aspectj/apache/bcel/classfile/Attribute.java
index 34ed08f5e..edc8d22c9 100644
--- a/bcel-builder/src/org/aspectj/apache/bcel/classfile/Attribute.java
+++ b/bcel-builder/src/org/aspectj/apache/bcel/classfile/Attribute.java
@@ -167,6 +167,12 @@ public abstract class Attribute implements Cloneable, Node, Serializable {
return new RuntimeInvisTypeAnnos(idx, len, file, cpool);
case Constants.ATTR_METHOD_PARAMETERS:
return new MethodParameters(idx, len, file, cpool);
+ case Constants.ATTR_MODULE:
+ return new Module(idx, len, file, cpool);
+ case Constants.ATTR_MODULE_PACKAGES:
+ return new ModulePackages(idx, len, file, cpool);
+ case Constants.ATTR_MODULE_MAIN_CLASS:
+ return new ModuleMainClass(idx, len, file, cpool);
default:
throw new IllegalStateException();
}
diff --git a/bcel-builder/src/org/aspectj/apache/bcel/classfile/ClassParser.java b/bcel-builder/src/org/aspectj/apache/bcel/classfile/ClassParser.java
index f7e794c8c..54882beee 100644
--- a/bcel-builder/src/org/aspectj/apache/bcel/classfile/ClassParser.java
+++ b/bcel-builder/src/org/aspectj/apache/bcel/classfile/ClassParser.java
@@ -180,7 +180,6 @@ public final class ClassParser {
superclassnameIndex = file.readUnsignedShort();
}
- /** Read constant pool entries */
private final void readConstantPool() throws IOException {
try {
cpool = new ConstantPool(file);
diff --git a/bcel-builder/src/org/aspectj/apache/bcel/classfile/ClassVisitor.java b/bcel-builder/src/org/aspectj/apache/bcel/classfile/ClassVisitor.java
index 9280083a8..0a9340649 100644
--- a/bcel-builder/src/org/aspectj/apache/bcel/classfile/ClassVisitor.java
+++ b/bcel-builder/src/org/aspectj/apache/bcel/classfile/ClassVisitor.java
@@ -103,6 +103,10 @@ public interface ClassVisitor {
public void visitConstantString(ConstantString obj);
+ public void visitConstantModule(ConstantModule obj);
+
+ public void visitConstantPackage(ConstantPackage obj);
+
public void visitConstantUtf8(ConstantUtf8 obj);
public void visitConstantValue(ConstantValue obj);
@@ -162,4 +166,9 @@ public interface ClassVisitor {
public void visitLocalVariableTypeTable(LocalVariableTypeTable obj);
public void visitMethodParameters(MethodParameters methodParameters);
+
+ // J9:
+ public void visitModule(Module module);
+ public void visitModulePackages(ModulePackages modulePackage);
+ public void visitModuleMainClass(ModuleMainClass moduleMainClass);
}
diff --git a/bcel-builder/src/org/aspectj/apache/bcel/classfile/Constant.java b/bcel-builder/src/org/aspectj/apache/bcel/classfile/Constant.java
index 2110bdc08..6fbbff3a3 100644
--- a/bcel-builder/src/org/aspectj/apache/bcel/classfile/Constant.java
+++ b/bcel-builder/src/org/aspectj/apache/bcel/classfile/Constant.java
@@ -135,6 +135,8 @@ public abstract class Constant implements Cloneable, Node {
return new ConstantMethodType(dis);
case Constants.CONSTANT_InvokeDynamic:
return new ConstantInvokeDynamic(dis);
+ case Constants.CONSTANT_Module: return new ConstantModule(dis);
+ case Constants.CONSTANT_Package: return new ConstantPackage(dis);
default:
throw new ClassFormatException("Invalid byte tag in constant pool: " + b);
}
diff --git a/bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantModule.java b/bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantModule.java
new file mode 100644
index 000000000..efe4d3a1b
--- /dev/null
+++ b/bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantModule.java
@@ -0,0 +1,111 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2017 The Apache Software Foundation. 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. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache BCEL" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache BCEL", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
+ * ITS 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+package org.aspectj.apache.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.aspectj.apache.bcel.Constants;
+
+/**
+ * Represents a module.
+ *
+ * See http://cr.openjdk.java.net/~mr/jigsaw/spec/java-se-9-jvms-diffs.pdf 4.4.11
+ *
+ * @author Andy Clement
+ */
+public final class ConstantModule extends Constant {
+
+ private int nameIndex;
+
+ ConstantModule(DataInputStream file) throws IOException {
+ this(file.readUnsignedShort());
+ }
+
+ public ConstantModule(int nameIndex) {
+ super(Constants.CONSTANT_Module);
+ this.nameIndex = nameIndex;
+ }
+
+ @Override
+ public void accept(ClassVisitor v) {
+ v.visitConstantModule(this);
+ }
+
+ @Override
+ public final void dump(DataOutputStream file) throws IOException {
+ file.writeByte(tag);
+ file.writeShort(nameIndex);
+ }
+
+ @Override
+ public Integer getValue() {
+ return nameIndex;
+ }
+
+ public final int getNameIndex() {
+ return nameIndex;
+ }
+
+ @Override
+ public final String toString() {
+ return super.toString() + "(name_index = " + nameIndex + ")";
+ }
+
+ public String getModuleName(ConstantPool cpool) {
+ Constant c = cpool.getConstant(nameIndex, Constants.CONSTANT_Utf8);
+ return ((ConstantUtf8) c).getValue();
+ }
+}
diff --git a/bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantPackage.java b/bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantPackage.java
new file mode 100644
index 000000000..70f22c749
--- /dev/null
+++ b/bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantPackage.java
@@ -0,0 +1,111 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2017 The Apache Software Foundation. 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. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache BCEL" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache BCEL", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
+ * ITS 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+package org.aspectj.apache.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.aspectj.apache.bcel.Constants;
+
+/**
+ * Represents a module.
+ *
+ * See http://cr.openjdk.java.net/~mr/jigsaw/spec/java-se-9-jvms-diffs.pdf 4.4.12
+ *
+ * @author Andy Clement
+ */
+public final class ConstantPackage extends Constant {
+
+ private int nameIndex;
+
+ ConstantPackage(DataInputStream file) throws IOException {
+ this(file.readUnsignedShort());
+ }
+
+ public ConstantPackage(int nameIndex) {
+ super(Constants.CONSTANT_Package);
+ this.nameIndex = nameIndex;
+ }
+
+ @Override
+ public void accept(ClassVisitor v) {
+ v.visitConstantPackage(this);
+ }
+
+ @Override
+ public final void dump(DataOutputStream file) throws IOException {
+ file.writeByte(tag);
+ file.writeShort(nameIndex);
+ }
+
+ @Override
+ public Integer getValue() {
+ return nameIndex;
+ }
+
+ public final int getNameIndex() {
+ return nameIndex;
+ }
+
+ @Override
+ public final String toString() {
+ return super.toString() + "(name_index = " + nameIndex + ")";
+ }
+
+ public String getPackageName(ConstantPool cpool) {
+ Constant c = cpool.getConstant(nameIndex, Constants.CONSTANT_Utf8);
+ return ((ConstantUtf8) c).getValue();
+ }
+}
diff --git a/bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantPool.java b/bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantPool.java
index 4e160ba3d..be5b84564 100644
--- a/bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantPool.java
+++ b/bcel-builder/src/org/aspectj/apache/bcel/classfile/ConstantPool.java
@@ -275,6 +275,20 @@ public class ConstantPool implements Node {
assert c.tag == Constants.CONSTANT_Utf8;
return (ConstantUtf8) c;
}
+
+ public ConstantModule getConstantModule(int index) {
+ Constant c = getConstant(index);
+ assert c != null;
+ assert c.tag == Constants.CONSTANT_Module;
+ return (ConstantModule)c;
+ }
+
+ public ConstantPackage getConstantPackage(int index) {
+ Constant c = getConstant(index);
+ assert c != null;
+ assert c.tag == Constants.CONSTANT_Package;
+ return (ConstantPackage)c;
+ }
public String getConstantString_CONSTANTClass(int index) {
ConstantClass c = (ConstantClass) getConstant(index, Constants.CONSTANT_Class);
@@ -770,4 +784,12 @@ public class ConstantPool implements Node {
System.arraycopy(pool, 0, cs, 0, poolSize);
return new ConstantPool(cs);
}
+
+ public String getModuleName(int moduleIndex) {
+ return getConstantModule(moduleIndex).getModuleName(this);
+ }
+
+ public String getPackageName(int packageIndex) {
+ return getConstantPackage(packageIndex).getPackageName(this);
+ }
} \ No newline at end of file
diff --git a/bcel-builder/src/org/aspectj/apache/bcel/classfile/Module.java b/bcel-builder/src/org/aspectj/apache/bcel/classfile/Module.java
new file mode 100644
index 000000000..5eef18cde
--- /dev/null
+++ b/bcel-builder/src/org/aspectj/apache/bcel/classfile/Module.java
@@ -0,0 +1,664 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2016-17 The Apache Software Foundation. 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. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache BCEL" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache BCEL", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
+ * ITS 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+package org.aspectj.apache.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.aspectj.apache.bcel.Constants;
+
+/**
+ * This class is derived from <em>Attribute</em> and represents the module
+ * information captured in a class file.
+ * http://cr.openjdk.java.net/~mr/jigsaw/spec/lang-vm.html
+ * http://cr.openjdk.java.net/~mr/jigsaw/spec/java-se-9-jvms-diffs.pdf 4.7.25
+ *
+ * @author Andy Clement
+ */
+public final class Module extends Attribute {
+
+ private static final String[] NO_MODULE_NAMES = {};
+
+ private int moduleNameIndex; // u2 module_name_index
+ private int moduleFlags; // u2 module_flags
+ private int moduleVersionIndex; // u2 module_version_index
+ private Require[] requires;
+ private Export[] exports;
+ private Open[] opens;
+ private Uses[] uses;
+ private Provide[] provides;
+
+ private byte[] moduleInfo;
+ private int ptr;
+ private boolean unpacked = false;
+
+ public Module(Module module) {
+ super(module.getTag(), module.getNameIndex(), module.getLength(), module.getConstantPool());
+ moduleInfo = module.getBytes();
+ }
+
+ public Module(int nameIndex, int length, byte[] data, ConstantPool cp) {
+ super(Constants.ATTR_MODULE, nameIndex, length, cp);
+ }
+
+ Module(int nameIndex, int length, DataInputStream stream, ConstantPool cp) throws IOException {
+ this(nameIndex, length, (byte[])null, cp);
+ moduleInfo = new byte[length];
+ stream.read(moduleInfo);
+ unpacked = false;
+ }
+
+ public class Require {
+
+ private final int moduleIndex;
+ private final int flags;
+ private final int versionIndex;
+
+ public Require(int moduleIndex, int flags, int versionIndex) {
+ this.moduleIndex = moduleIndex;
+ this.flags = flags;
+ this.versionIndex = versionIndex;
+ }
+
+ public String getModuleName() {
+ return cpool.getModuleName(moduleIndex);
+ }
+
+ public int getFlags() {
+ return flags;
+ }
+
+ public int getVersionIndex() {
+ return versionIndex;
+ }
+
+ public String getVersionString() {
+ if (versionIndex == 0) {
+ return null;
+ } else {
+ return cpool.getConstantUtf8(versionIndex).getValue();
+ }
+ }
+
+ public String getFlagsAsString() {
+ StringBuilder s = new StringBuilder();
+ if ((flags & Constants.MODULE_ACC_TRANSITIVE)!=0) {
+ s.append(" transitive");
+ }
+ if ((flags & Constants.MODULE_ACC_STATIC_PHASE)!=0) {
+ s.append(" static");
+ }
+ if ((flags & Constants.MODULE_ACC_SYNTHETIC)!=0) {
+ s.append(" synthetic");
+ }
+ if ((flags & Constants.MODULE_ACC_MANDATED)!=0) {
+ s.append(" mandated");
+ }
+ return s.toString();
+ }
+
+ public String toString() {
+ return "requires"+getFlagsAsString()+" "+getModuleName()+(versionIndex==0?"":" "+getVersionString());
+ }
+ }
+
+
+ public class Export {
+
+ private final int packageIndex;
+ private final int flags;
+ private final int[] toModuleIndices;
+
+ public Export(int packageIndex, int flags, int[] toModuleIndices) {
+ this.packageIndex = packageIndex;
+ this.flags = flags;
+ this.toModuleIndices = toModuleIndices;
+ }
+
+ public int getPackageIndex() {
+ return packageIndex;
+ }
+
+ public int getFlags() {
+ return flags;
+ }
+
+ public int[] getToModuleIndices() {
+ return toModuleIndices;
+ }
+
+ public String getPackage() {
+ return cpool.getPackageName(packageIndex);
+ }
+
+ public String getFlagsAsString() {
+ StringBuilder s = new StringBuilder();
+ if ((flags & Constants.MODULE_ACC_SYNTHETIC)!=0) {
+ s.append(" synthetic");
+ }
+ if ((flags & Constants.MODULE_ACC_MANDATED)!=0) {
+ s.append(" synthetic");
+ }
+ return s.toString();
+ }
+
+ public String[] getToModuleNames() {
+ if (toModuleIndices==null) {
+ return NO_MODULE_NAMES;
+ }
+ String[] toModuleNames = new String[toModuleIndices.length];
+ for (int i=0;i<toModuleIndices.length;i++) {
+ toModuleNames[i] = cpool.getModuleName(toModuleIndices[i]);
+ }
+ return toModuleNames;
+ }
+
+ public String toString() {
+ StringBuilder s =new StringBuilder();
+ s.append("exports").append(getFlagsAsString()).append(" ").append(getPackage().replace('/', '.'));
+ String[] toModules = getToModuleNames();
+ if (toModules.length!=0) {
+ s.append(" to ");
+ for (int i=0;i<toModules.length;i++) {
+ if (i>0) {
+ s.append(", ");
+ }
+ s.append(toModules[i]);
+ }
+ }
+ return s.toString().trim();
+ }
+ }
+
+
+ public class Open {
+
+ private final int packageIndex;
+ private final int flags;
+ private final int[] toModuleIndices;
+
+ public Open(int packageIndex, int flags, int[] toModuleIndices) {
+ this.packageIndex = packageIndex;
+ this.flags = flags;
+ this.toModuleIndices = toModuleIndices;
+ }
+
+ public int getPackageIndex() {
+ return packageIndex;
+ }
+
+ public int getFlags() {
+ return flags;
+ }
+
+ public int[] getToModuleIndices() {
+ return toModuleIndices;
+ }
+
+ public String getPackage() {
+ return cpool.getPackageName(packageIndex);
+ }
+
+ public String getFlagsAsString() {
+ StringBuilder s = new StringBuilder();
+ if ((flags & Constants.MODULE_ACC_SYNTHETIC)!=0) {
+ s.append(" synthetic");
+ }
+ if ((flags & Constants.MODULE_ACC_MANDATED)!=0) {
+ s.append(" synthetic");
+ }
+ return s.toString();
+ }
+
+ public String[] getToModuleNames() {
+ if (toModuleIndices==null) {
+ return NO_MODULE_NAMES;
+ }
+ String[] toModuleNames = new String[toModuleIndices.length];
+ for (int i=0;i<toModuleIndices.length;i++) {
+ toModuleNames[i] = cpool.getModuleName(toModuleIndices[i]);
+ }
+ return toModuleNames;
+ }
+
+ public String toString() {
+ StringBuilder s =new StringBuilder();
+ s.append("opens").append(getFlagsAsString()).append(" ").append(getPackage().replace('/', '.'));
+ String[] toModules = getToModuleNames();
+ if (toModules.length!=0) {
+ s.append(" to ");
+ for (int i=0;i<toModules.length;i++) {
+ if (i>0) {
+ s.append(", ");
+ }
+ s.append(toModules[i]);
+ }
+ }
+ return s.toString().trim();
+ }
+ }
+
+ public class Provide {
+ private final int providedTypeIndex;
+ private final int[] withTypeIndices;
+
+ public Provide(int providedTypeIndex, int[] withTypeIndices) {
+ this.providedTypeIndex = providedTypeIndex;
+ this.withTypeIndices = withTypeIndices;
+ }
+
+ public String getProvidedType() {
+ return cpool.getConstantString_CONSTANTClass(providedTypeIndex);
+ }
+
+ public int getProvidedTypeIndex() {
+ return providedTypeIndex;
+ }
+
+ public String[] getWithTypeStrings() {
+ String[] result = new String[withTypeIndices.length];
+ for (int i=0;i<withTypeIndices.length;i++) {
+ result[i] = cpool.getConstantString_CONSTANTClass(withTypeIndices[i]);
+ }
+ return result;
+ }
+
+ public int[] getWithTypeIndices() {
+ return withTypeIndices;
+ }
+
+ public String toString() {
+ StringBuilder s =new StringBuilder();
+ s.append("provides ").append(getProvidedType().replace('/', '.'));
+ s.append(" with ");
+ String[] withtypes = getWithTypeStrings();
+ for (int i=0;i< withtypes.length;i++) {
+ if (i>0) s.append(",");
+ s.append(withtypes[i].replace('/','.'));
+ }
+ return s.toString();
+ }
+ }
+
+ public class Uses {
+ private final int typeNameIndex;
+
+ public Uses(int typeNameIndex) {
+ this.typeNameIndex = typeNameIndex;
+ }
+
+ public String getTypeName() {
+ return cpool.getConstantString_CONSTANTClass(typeNameIndex);
+ }
+
+ public int getTypeNameIndex() {
+ return typeNameIndex;
+ }
+
+ public String toString() {
+ StringBuilder s =new StringBuilder();
+ s.append("uses ").append(getTypeName().replace('/', '.'));
+ return s.toString().trim();
+ }
+ }
+
+ private final int readInt() {
+ return ((moduleInfo[ptr++] & 0xFF) << 24) + ((moduleInfo[ptr++] & 0xFF) << 16)
+ + ((moduleInfo[ptr++] & 0xFF) << 8) + (moduleInfo[ptr++] & 0xFF);
+ }
+
+ private final int readUnsignedShort() {
+ return ((moduleInfo[ptr++] & 0xff) << 8) + (moduleInfo[ptr++] & 0xff);
+ }
+
+ private final int readUnsignedShort(int offset) {
+ return ((moduleInfo[offset++] & 0xff) << 8) + (moduleInfo[offset] & 0xff);
+ }
+
+ // Format: http://cr.openjdk.java.net/~mr/jigsaw/spec/java-se-9-jvms-diffs.pdf 4.7.25
+ private void ensureUnpacked() {
+ if (!unpacked) {
+ ptr = 0;
+ moduleNameIndex = readUnsignedShort();
+ moduleFlags = readUnsignedShort();
+ moduleVersionIndex = readUnsignedShort();
+
+ int count = readUnsignedShort();
+ requires = new Require[count];
+ for (int i = 0; i < count; i++) {
+ requires[i] = new Require(readUnsignedShort(), readUnsignedShort(), readUnsignedShort());
+ }
+
+ count = readUnsignedShort();
+ exports = new Export[count];
+ for (int i = 0; i < count; i++) {
+ int index = readUnsignedShort();
+ int flags = readUnsignedShort();
+ int toCount = readUnsignedShort();
+ int[] to = new int[toCount];
+ for (int j = 0; j < toCount; j++) {
+ to[j] = readUnsignedShort();
+ }
+ exports[i] = new Export(index, flags, to);
+ }
+
+ count = readUnsignedShort();
+ opens = new Open[count];
+ for (int i = 0; i < count; i++) {
+ int index = readUnsignedShort();
+ int flags = readUnsignedShort();
+ int toCount = readUnsignedShort();
+ int[] to = new int[toCount];
+ for (int j = 0; j < toCount; j++) {
+ to[j] = readUnsignedShort();
+ }
+ opens[i] = new Open(index, flags, to);
+ }
+ count = readUnsignedShort();
+ uses = new Uses[count];
+ for (int i = 0; i < count; i++) {
+ uses[i] = new Uses(readUnsignedShort());
+ }
+ count = readUnsignedShort();
+ provides = new Provide[count];
+ for (int i = 0; i < count; i++) {
+ int index = readUnsignedShort();
+ int toCount = readUnsignedShort();
+ int[] to = new int[toCount];
+ for (int j = 0; j < toCount; j++) {
+ to[j] = readUnsignedShort();
+ }
+ provides[i] = new Provide(index, to);
+ }
+ unpacked = true;
+ }
+ }
+
+ @Override
+ public final void dump(DataOutputStream file) throws IOException {
+ super.dump(file);
+ if (!unpacked) {
+ file.write(moduleInfo);
+ } else {
+
+ file.writeShort(moduleNameIndex);
+ file.writeShort(moduleFlags);
+ file.writeShort(moduleVersionIndex);
+
+ file.writeShort(requires.length);
+ for (int i = 0; i < requires.length; i++) {
+ file.writeShort(requires[i].moduleIndex);
+ file.writeShort(requires[i].flags);
+ file.writeShort(requires[i].versionIndex);
+ }
+ file.writeShort(exports.length);
+ for (Export export : exports) {
+ file.writeShort(export.packageIndex);
+ int[] toIndices = export.toModuleIndices;
+ file.writeShort(toIndices.length);
+ for (int index : toIndices) {
+ file.writeShort(index);
+ }
+ }
+ file.writeShort(opens.length);
+ for (Open open : opens) {
+ file.writeShort(open.packageIndex);
+ int[] toIndices = open.toModuleIndices;
+ file.writeShort(toIndices.length);
+ for (int index : toIndices) {
+ file.writeShort(index);
+ }
+ }
+ file.writeShort(uses.length);
+ for (Uses use : uses) {
+ file.writeShort(use.getTypeNameIndex());
+ }
+ file.writeShort(provides.length);
+ for (Provide provide : provides) {
+ file.writeShort(provide.providedTypeIndex);
+ int[] toIndices = provide.withTypeIndices;
+ file.writeShort(toIndices.length);
+ for (int index : toIndices) {
+ file.writeShort(index);
+ }
+ }
+ }
+ }
+
+ public String toStringRequires() {
+ StringBuilder s = new StringBuilder();
+ s.append('#').append(requires.length);
+ if (requires.length > 0) {
+ for (Require require : requires) {
+ s.append(' ');
+ s.append(require.moduleIndex).append(':').append(require.flags);
+ }
+ }
+ return s.toString();
+ }
+
+ public String toStringExports() {
+ StringBuilder s = new StringBuilder();
+ s.append('#').append(exports.length);
+ if (exports.length > 0) {
+ for (Export export : exports) {
+ s.append(' ');
+ s.append(export.packageIndex).append(":[");
+ int[] toIndices = export.toModuleIndices;
+ for (int i = 0; i < toIndices.length; i++) {
+ if (i > 0)
+ s.append(',');
+ s.append(toIndices[i]);
+ }
+ s.append("]");
+ }
+ }
+ return s.toString();
+ }
+
+ public String toStringOpens() {
+ StringBuilder s = new StringBuilder();
+ s.append('#').append(opens.length);
+ if (opens.length > 0) {
+ for (Open open : opens) {
+ s.append(' ');
+ s.append(open.packageIndex).append(":[");
+ int[] toIndices = open.toModuleIndices;
+ for (int i = 0; i < toIndices.length; i++) {
+ if (i > 0)
+ s.append(',');
+ s.append(toIndices[i]);
+ }
+ s.append("]");
+ }
+ }
+ return s.toString();
+ }
+
+ public String toStringUses() {
+ StringBuilder s = new StringBuilder();
+ s.append('#').append(uses.length);
+ if (uses.length > 0) {
+ for (Uses use : uses) {
+ s.append(' ');
+ s.append(use.getTypeName());
+ }
+ }
+ return s.toString();
+ }
+
+ public String toStringProvides() {
+ StringBuilder s = new StringBuilder();
+ s.append('#').append(provides.length);
+ if (provides.length > 0) {
+ for (Provide provide : provides) {
+ s.append(' ');
+ s.append(provide.providedTypeIndex).append(":[");
+ int[] indices = provide.withTypeIndices;
+ for (int i = 0; i < indices.length; i++) {
+ if (i > 0)
+ s.append(',');
+ s.append(indices[i]);
+ }
+ s.append("]");
+ }
+ }
+ return s.toString();
+ }
+
+ @Override
+ public final String toString() {
+ StringBuilder s = new StringBuilder();
+ ensureUnpacked();
+ s.append("Module(");
+ if (requires.length != 0) {
+ s.append("requires=");
+ s.append(toStringRequires());
+ s.append(" ");
+ }
+ if (exports.length != 0) {
+ s.append("exports=");
+ s.append(toStringExports());
+ s.append(" ");
+ }
+ if (opens.length != 0) {
+ s.append("opens=");
+ s.append(toStringOpens());
+ s.append(" ");
+ }
+ if (uses.length != 0) {
+ s.append("uses=");
+ s.append(toStringUses());
+ s.append(" ");
+ }
+ if (provides.length != 0) {
+ s.append("provides=");
+ s.append(toStringProvides());
+ s.append(" ");
+ }
+ return s.toString().trim()+")";
+ }
+
+ /**
+ * @return deep copy of this attribute //
+ */
+// @Override
+// public Attribute copy(ConstantPool constant_pool) {
+// return (Module) clone();
+// }
+
+ @Override
+ public void accept(ClassVisitor v) {
+ v.visitModule(this);
+ }
+
+ public Require[] getRequires() {
+ ensureUnpacked();
+ return requires;
+ }
+
+ public String[] getRequiredModuleNames() {
+ ensureUnpacked();
+ String[] results = new String[requires.length];
+ for (int i=0;i<requires.length;i++) {
+ results[i] = cpool.getModuleName(requires[i].moduleIndex);
+ }
+ return results;
+ }
+
+ public byte[] getBytes() {
+ return moduleInfo;
+ }
+
+ public Export[] getExports() {
+ ensureUnpacked();
+ return exports;
+ }
+
+ public Open[] getOpens() {
+ ensureUnpacked();
+ return opens;
+ }
+
+ public Uses[] getUses() {
+ ensureUnpacked();
+ return uses;
+ }
+
+ public Provide[] getProvides() {
+ ensureUnpacked();
+ return provides;
+ }
+
+ public String getModuleName() {
+ return ((ConstantModule)cpool.getConstant(moduleNameIndex)).getModuleName(cpool);
+ }
+
+ public int getModuleFlags() {
+ // 0x0020 (ACC_OPEN) - Indicates that this module is open.
+ // 0x1000 (ACC_SYNTHETIC) - Indicates that this module was not explicitly or implicitly declared.
+ // 0x8000 (ACC_MANDATED) - Indicates that this module was implicitly declared
+ return moduleFlags;
+ }
+
+ /** @return the module version or null if no version information specified */
+ public String getModuleVersion() {
+ if (moduleVersionIndex == 0) {
+ return null;
+ } else {
+ return cpool.getConstantUtf8(moduleVersionIndex).getValue();
+ }
+ }
+}
diff --git a/bcel-builder/src/org/aspectj/apache/bcel/classfile/ModuleMainClass.java b/bcel-builder/src/org/aspectj/apache/bcel/classfile/ModuleMainClass.java
new file mode 100644
index 000000000..3fa500a8e
--- /dev/null
+++ b/bcel-builder/src/org/aspectj/apache/bcel/classfile/ModuleMainClass.java
@@ -0,0 +1,106 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2017 The Apache Software Foundation. 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. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache BCEL" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache BCEL", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
+ * ITS 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+package org.aspectj.apache.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.aspectj.apache.bcel.Constants;
+
+/**
+ * Indicates the main class of a module.
+ * http://cr.openjdk.java.net/~mr/jigsaw/spec/java-se-9-jvms-diffs.pdf 4.7.26
+ *
+ * @author Andy Clement
+ */
+public final class ModuleMainClass extends Attribute {
+
+ private int mainClassIndex;
+
+ public ModuleMainClass(ModuleMainClass c) {
+ this(c.getNameIndex(), c.getLength(), c.getMainClassIndex(), c.getConstantPool());
+ }
+
+ public ModuleMainClass(int nameIndex, int length, int mainClassIndex, ConstantPool cp) {
+ super(Constants.ATTR_MODULE_MAIN_CLASS, nameIndex, length, cp);
+ this.mainClassIndex = mainClassIndex;
+ }
+
+ ModuleMainClass(int nameIndex, int length, DataInputStream stream, ConstantPool cp) throws IOException {
+ this(nameIndex, length, 0, cp);
+ this.mainClassIndex = stream.readUnsignedShort();
+ }
+
+ @Override
+ public void accept(ClassVisitor v) {
+ v.visitModuleMainClass(this);
+ }
+
+ @Override
+ public final void dump(DataOutputStream stream) throws IOException {
+ super.dump(stream);
+ stream.writeShort(mainClassIndex);
+ }
+
+ public final int getMainClassIndex() {
+ return mainClassIndex;
+ }
+
+ @Override
+ public final String toString() {
+ return cpool.getConstantString_CONSTANTClass(mainClassIndex);
+ }
+
+}
diff --git a/bcel-builder/src/org/aspectj/apache/bcel/classfile/ModulePackages.java b/bcel-builder/src/org/aspectj/apache/bcel/classfile/ModulePackages.java
new file mode 100644
index 000000000..37da4bc47
--- /dev/null
+++ b/bcel-builder/src/org/aspectj/apache/bcel/classfile/ModulePackages.java
@@ -0,0 +1,126 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2017 The Apache Software Foundation. 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. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache BCEL" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache BCEL", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
+ * ITS 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+package org.aspectj.apache.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.aspectj.apache.bcel.Constants;
+
+/**
+ * Indicates all the packages of a module that are exported or opened by the module attribute.
+ * http://cr.openjdk.java.net/~mr/jigsaw/spec/java-se-9-jvms-diffs.pdf 4.7.26
+ *
+ * @author Andy Clement
+ */
+public final class ModulePackages extends Attribute {
+
+ private static int[] NO_PACKAGES = new int[0];
+ private int[] packageIndices;
+
+ public ModulePackages(ModulePackages c) {
+ this(c.getNameIndex(), c.getLength(), c.getPackageIndices(), c.getConstantPool());
+ }
+
+ public ModulePackages(int nameIndex, int length, int[] packageIndices, ConstantPool cp) {
+ super(Constants.ATTR_MODULE_PACKAGES, nameIndex, length, cp);
+ setPackageIndices(packageIndices);
+ }
+
+ ModulePackages(int nameIndex, int length, DataInputStream stream, ConstantPool cp) throws IOException {
+ this(nameIndex, length, (int[]) null, cp);
+ int packageIndicesCount = stream.readUnsignedShort();
+ packageIndices = new int[packageIndicesCount];
+ for (int i = 0; i < packageIndicesCount; i++) {
+ packageIndices[i] = stream.readUnsignedShort();
+ }
+ }
+
+ @Override
+ public void accept(ClassVisitor v) {
+ v.visitModulePackages(this);
+ }
+
+ @Override
+ public final void dump(DataOutputStream stream) throws IOException {
+ super.dump(stream);
+ stream.writeShort(packageIndices.length);
+ for (int i = 0; i < packageIndices.length; i++) {
+ stream.writeShort(packageIndices[i]);
+ }
+ }
+
+ public final int[] getPackageIndices() {
+ return packageIndices;
+ }
+
+ public final void setPackageIndices(int[] packageIndices) {
+ if (packageIndices == null) {
+ this.packageIndices = NO_PACKAGES;
+ } else {
+ this.packageIndices = packageIndices;
+ }
+ }
+
+ @Override
+ public final String toString() {
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < packageIndices.length; i++) {
+ buf.append(cpool.getPackageName(packageIndices[i]) + "\n");
+ }
+ return buf.toString();
+ }
+
+}
diff --git a/bcel-builder/src/org/aspectj/apache/bcel/util/ClassPath.java b/bcel-builder/src/org/aspectj/apache/bcel/util/ClassPath.java
index d346256cb..6204a3384 100644
--- a/bcel-builder/src/org/aspectj/apache/bcel/util/ClassPath.java
+++ b/bcel-builder/src/org/aspectj/apache/bcel/util/ClassPath.java
@@ -56,323 +56,486 @@ package org.aspectj.apache.bcel.util;
import java.util.*;
import java.util.zip.*;
+
import java.io.*;
+import java.net.URI;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.Path;
+import java.nio.file.attribute.BasicFileAttributeView;
+import java.nio.file.attribute.BasicFileAttributes;
/**
* Responsible for loading (class) files from the CLASSPATH. Inspired by
* sun.tools.ClassPath.
*
* @version $Id: ClassPath.java,v 1.5 2009/09/09 19:56:20 aclement Exp $
- * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
+ * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
*/
public class ClassPath implements Serializable {
- private static ClassPath SYSTEM_CLASS_PATH = null;
-
- private PathEntry[] paths;
- private String class_path;
-
- public static ClassPath getSystemClassPath() {
- if (SYSTEM_CLASS_PATH == null) {
- SYSTEM_CLASS_PATH = new ClassPath();
- }
- return SYSTEM_CLASS_PATH;
- }
- /**
- * Search for classes in given path.
- */
- public ClassPath(String class_path) {
- this.class_path = class_path;
-
- ArrayList<PathEntry> vec = new ArrayList<PathEntry>();
-
- for(StringTokenizer tok=new StringTokenizer(class_path,
- System.getProperty("path.separator"));
- tok.hasMoreTokens();)
- {
- String path = tok.nextToken();
-
- if(!path.equals("")) {
- File file = new File(path);
-
- try {
- if(file.exists()) {
- if(file.isDirectory())
- vec.add(new Dir(path));
- else
- vec.add(new Zip(new ZipFile(file)));
- }
- } catch(IOException e) {
- System.err.println("CLASSPATH component " + file + ": " + e);
+ private static ClassPath SYSTEM_CLASS_PATH = null;
+
+ private PathEntry[] paths;
+ private String class_path;
+
+ public static ClassPath getSystemClassPath() {
+ if (SYSTEM_CLASS_PATH == null) {
+ SYSTEM_CLASS_PATH = new ClassPath();
+ }
+ return SYSTEM_CLASS_PATH;
}
- }
- }
-
- paths = new PathEntry[vec.size()];
- vec.toArray(paths);
- }
-
- /**
- * Search for classes in CLASSPATH.
- * @deprecated Use SYSTEM_CLASS_PATH constant
- */
- public ClassPath() {
- this(getClassPath());
- }
-
- /** @return used class path string
- */
- public String toString() {
- return class_path;
- }
-
- public int hashCode() {
- return class_path.hashCode();
- }
-
- public boolean equals(Object o) {
- if(o instanceof ClassPath) {
- return class_path.equals(((ClassPath)o).class_path);
- }
-
- return false;
- }
-
- private static final void getPathComponents(String path, ArrayList<String> list) {
- if(path != null) {
- StringTokenizer tok = new StringTokenizer(path, File.pathSeparator);
-
- while(tok.hasMoreTokens()) {
- String name = tok.nextToken();
- File file = new File(name);
-
- if(file.exists())
- list.add(name);
- }
- }
- }
-
- /** Checks for class path components in the following properties:
- * "java.class.path", "sun.boot.class.path", "java.ext.dirs"
- *
- * @return class path as used by default by BCEL
- */
- public static final String getClassPath() {
- String class_path = System.getProperty("java.class.path");
- String boot_path = System.getProperty("sun.boot.class.path");
- String ext_path = System.getProperty("java.ext.dirs");
-
- ArrayList<String> list = new ArrayList<String>();
-
- getPathComponents(class_path, list);
- getPathComponents(boot_path, list);
-
- ArrayList<String> dirs = new ArrayList<String>();
- getPathComponents(ext_path, dirs);
-
- for(Iterator<String> e = dirs.iterator(); e.hasNext(); ) {
- File ext_dir = new File(e.next());
- String[] extensions = ext_dir.list(new FilenameFilter() {
- public boolean accept(File dir, String name) {
- name = name.toLowerCase();
- return name.endsWith(".zip") || name.endsWith(".jar");
+
+ /**
+ * Search for classes in given path.
+ */
+ public ClassPath(String class_path) {
+ this.class_path = class_path;
+
+ ArrayList<PathEntry> vec = new ArrayList<PathEntry>();
+
+ for (StringTokenizer tok = new StringTokenizer(class_path, System.getProperty("path.separator")); tok
+ .hasMoreTokens();) {
+ String path = tok.nextToken();
+
+ if (!path.equals("")) {
+ File file = new File(path);
+
+ try {
+ if (file.exists()) {
+ if (file.isDirectory())
+ vec.add(new Dir(path));
+ else if (file.getName().endsWith(".jimage")) {
+ vec.add(new JImage(file));
+ } else {
+ vec.add(new Zip(new ZipFile(file)));
+ }
+ }
+ } catch (IOException e) {
+ System.err.println("CLASSPATH component " + file + ": " + e);
+ }
+ }
+ }
+
+ paths = new PathEntry[vec.size()];
+ vec.toArray(paths);
}
- });
-
- if(extensions != null)
- for(int i=0; i < extensions.length; i++)
- list.add(ext_path + File.separatorChar + extensions[i]);
- }
-
- StringBuffer buf = new StringBuffer();
-
- for(Iterator<String> e = list.iterator(); e.hasNext(); ) {
- buf.append(e.next());
-
- if(e.hasNext())
- buf.append(File.pathSeparatorChar);
- }
-
- return buf.toString().intern();
- }
-
- /**
- * @param name fully qualified class name, e.g. java.lang.String
- * @return input stream for class
- */
- public InputStream getInputStream(String name) throws IOException {
- return getInputStream(name, ".class");
- }
-
- /**
- * Return stream for class or resource on CLASSPATH.
- *
- * @param name fully qualified file name, e.g. java/lang/String
- * @param suffix file name ends with suff, e.g. .java
- * @return input stream for file on class path
- */
- public InputStream getInputStream(String name, String suffix) throws IOException {
- InputStream is = null;
-
- try {
- is = getClass().getClassLoader().getResourceAsStream(name + suffix);
- } catch(Exception e) { }
-
- if(is != null)
- return is;
-
- return getClassFile(name, suffix).getInputStream();
- }
-
- /**
- * @param name fully qualified file name, e.g. java/lang/String
- * @param suffix file name ends with suff, e.g. .java
- * @return class file for the java class
- */
- public ClassFile getClassFile(String name, String suffix) throws IOException {
- for(int i=0; i < paths.length; i++) {
- ClassFile cf;
-
- if((cf = paths[i].getClassFile(name, suffix)) != null)
- return cf;
- }
-
- throw new IOException("Couldn't find: " + name + suffix);
- }
-
- /**
- * @param name fully qualified class name, e.g. java.lang.String
- * @return input stream for class
- */
- public ClassFile getClassFile(String name) throws IOException {
- return getClassFile(name, ".class");
- }
-
- /**
- * @param name fully qualified file name, e.g. java/lang/String
- * @param suffix file name ends with suffix, e.g. .java
- * @return byte array for file on class path
- */
- public byte[] getBytes(String name, String suffix) throws IOException {
- InputStream is = getInputStream(name, suffix);
-
- if(is == null)
- throw new IOException("Couldn't find: " + name + suffix);
-
- DataInputStream dis = new DataInputStream(is);
- byte[] bytes = new byte[is.available()];
- dis.readFully(bytes);
- dis.close(); is.close();
-
- return bytes;
- }
-
- /**
- * @return byte array for class
- */
- public byte[] getBytes(String name) throws IOException {
- return getBytes(name, ".class");
- }
-
- /**
- * @param name name of file to search for, e.g. java/lang/String.java
- * @return full (canonical) path for file
- */
- public String getPath(String name) throws IOException {
- int index = name.lastIndexOf('.');
- String suffix = "";
-
- if(index > 0) {
- suffix = name.substring(index);
- name = name.substring(0, index);
- }
-
- return getPath(name, suffix);
- }
-
- /**
- * @param name name of file to search for, e.g. java/lang/String
- * @param suffix file name suffix, e.g. .java
- * @return full (canonical) path for file, if it exists
- */
- public String getPath(String name, String suffix) throws IOException {
- return getClassFile(name, suffix).getPath();
- }
-
- private static abstract class PathEntry implements Serializable {
- abstract ClassFile getClassFile(String name, String suffix) throws IOException;
- }
-
- /** Contains information about file/ZIP entry of the Java class.
- */
- public interface ClassFile {
- /** @return input stream for class file.
- */
- public abstract InputStream getInputStream() throws IOException;
-
- /** @return canonical path to class file.
- */
- public abstract String getPath();
-
- /** @return base path of found class, i.e. class is contained relative
- * to that path, which may either denote a directory, or zip file
- */
- public abstract String getBase();
-
- /** @return modification time of class file.
- */
- public abstract long getTime();
-
- /** @return size of class file.
- */
- public abstract long getSize();
- }
-
- private static class Dir extends PathEntry {
- private String dir;
-
- Dir(String d) { dir = d; }
-
- ClassFile getClassFile(String name, String suffix) throws IOException {
- final File file = new File(dir + File.separatorChar +
- name.replace('.', File.separatorChar) + suffix);
-
- return file.exists()? new ClassFile() {
- public InputStream getInputStream() throws IOException { return new FileInputStream(file); }
-
- public String getPath() { try {
- return file.getCanonicalPath();
- } catch(IOException e) { return null; }
+ /**
+ * Search for classes in CLASSPATH.
+ *
+ * @deprecated Use SYSTEM_CLASS_PATH constant
+ */
+ public ClassPath() {
+ this(getClassPath());
}
- public long getTime() { return file.lastModified(); }
- public long getSize() { return file.length(); }
- public String getBase() { return dir; }
- } : null;
- }
+ /**
+ * @return used class path string
+ */
+ public String toString() {
+ return class_path;
+ }
- public String toString() { return dir; }
- }
+ public int hashCode() {
+ return class_path.hashCode();
+ }
- private static class Zip extends PathEntry {
- private ZipFile zip;
+ public boolean equals(Object o) {
+ if (o instanceof ClassPath) {
+ return class_path.equals(((ClassPath) o).class_path);
+ }
- Zip(ZipFile z) { zip = z; }
+ return false;
+ }
- ClassFile getClassFile(String name, String suffix) throws IOException {
- final ZipEntry entry = zip.getEntry(name.replace('.', '/') + suffix);
+ private static final void getPathComponents(String path, ArrayList<String> list) {
+ if (path != null) {
+ StringTokenizer tok = new StringTokenizer(path, File.pathSeparator);
- return (entry != null)? new ClassFile() {
- public InputStream getInputStream() throws IOException { return zip.getInputStream(entry); }
- public String getPath() { return entry.toString(); }
- public long getTime() { return entry.getTime(); }
- public long getSize() { return entry.getSize(); }
- public String getBase() {
- return zip.getName();
+ while (tok.hasMoreTokens()) {
+ String name = tok.nextToken();
+ File file = new File(name);
+
+ if (file.exists())
+ list.add(name);
+ }
+ }
}
- } : null;
- }
- }
-}
+ /**
+ * Checks for class path components in the following properties:
+ * "java.class.path", "sun.boot.class.path", "java.ext.dirs"
+ *
+ * @return class path as used by default by BCEL
+ */
+ public static final String getClassPath() {
+ String class_path = System.getProperty("java.class.path");
+ String boot_path = System.getProperty("sun.boot.class.path");
+ String ext_path = System.getProperty("java.ext.dirs");
+
+ ArrayList<String> list = new ArrayList<String>();
+
+ getPathComponents(class_path, list);
+ getPathComponents(boot_path, list);
+
+ ArrayList<String> dirs = new ArrayList<String>();
+ getPathComponents(ext_path, dirs);
+
+ for (Iterator<String> e = dirs.iterator(); e.hasNext();) {
+ File ext_dir = new File(e.next());
+ String[] extensions = ext_dir.list(new FilenameFilter() {
+ public boolean accept(File dir, String name) {
+ name = name.toLowerCase();
+ return name.endsWith(".zip") || name.endsWith(".jar");
+ }
+ });
+
+ if (extensions != null)
+ for (int i = 0; i < extensions.length; i++)
+ list.add(ext_path + File.separatorChar + extensions[i]);
+ }
+
+ StringBuffer buf = new StringBuffer();
+
+ for (Iterator<String> e = list.iterator(); e.hasNext();) {
+ buf.append(e.next());
+
+ if (e.hasNext())
+ buf.append(File.pathSeparatorChar);
+ }
+
+ return buf.toString().intern();
+ }
+
+ /**
+ * @param name
+ * fully qualified class name, e.g. java.lang.String
+ * @return input stream for class
+ */
+ public InputStream getInputStream(String name) throws IOException {
+ return getInputStream(name, ".class");
+ }
+
+ /**
+ * Return stream for class or resource on CLASSPATH.
+ *
+ * @param name
+ * fully qualified file name, e.g. java/lang/String
+ * @param suffix
+ * file name ends with suff, e.g. .java
+ * @return input stream for file on class path
+ */
+ public InputStream getInputStream(String name, String suffix) throws IOException {
+ InputStream is = null;
+
+ try {
+ is = getClass().getClassLoader().getResourceAsStream(name + suffix);
+ } catch (Exception e) {
+ }
+
+ if (is != null)
+ return is;
+
+ return getClassFile(name, suffix).getInputStream();
+ }
+
+ /**
+ * @param name
+ * fully qualified file name, e.g. java/lang/String
+ * @param suffix
+ * file name ends with suff, e.g. .java
+ * @return class file for the java class
+ */
+ public ClassFile getClassFile(String name, String suffix) throws IOException {
+ for (int i = 0; i < paths.length; i++) {
+ ClassFile cf;
+
+ if ((cf = paths[i].getClassFile(name, suffix)) != null)
+ return cf;
+ }
+
+ throw new IOException("Couldn't find: " + name + suffix);
+ }
+
+ /**
+ * @param name
+ * fully qualified class name, e.g. java.lang.String
+ * @return input stream for class
+ */
+ public ClassFile getClassFile(String name) throws IOException {
+ return getClassFile(name, ".class");
+ }
+
+ /**
+ * @param name
+ * fully qualified file name, e.g. java/lang/String
+ * @param suffix
+ * file name ends with suffix, e.g. .java
+ * @return byte array for file on class path
+ */
+ public byte[] getBytes(String name, String suffix) throws IOException {
+ InputStream is = getInputStream(name, suffix);
+
+ if (is == null)
+ throw new IOException("Couldn't find: " + name + suffix);
+
+ DataInputStream dis = new DataInputStream(is);
+ byte[] bytes = new byte[is.available()];
+ dis.readFully(bytes);
+ dis.close();
+ is.close();
+
+ return bytes;
+ }
+
+ /**
+ * @return byte array for class
+ */
+ public byte[] getBytes(String name) throws IOException {
+ return getBytes(name, ".class");
+ }
+
+ /**
+ * @param name
+ * name of file to search for, e.g. java/lang/String.java
+ * @return full (canonical) path for file
+ */
+ public String getPath(String name) throws IOException {
+ int index = name.lastIndexOf('.');
+ String suffix = "";
+
+ if (index > 0) {
+ suffix = name.substring(index);
+ name = name.substring(0, index);
+ }
+
+ return getPath(name, suffix);
+ }
+
+ /**
+ * @param name
+ * name of file to search for, e.g. java/lang/String
+ * @param suffix
+ * file name suffix, e.g. .java
+ * @return full (canonical) path for file, if it exists
+ */
+ public String getPath(String name, String suffix) throws IOException {
+ return getClassFile(name, suffix).getPath();
+ }
+
+ private static abstract class PathEntry implements Serializable {
+ abstract ClassFile getClassFile(String name, String suffix) throws IOException;
+ }
+
+ /**
+ * Contains information about file/ZIP entry of the Java class.
+ */
+ public interface ClassFile {
+ /**
+ * @return input stream for class file.
+ */
+ public abstract InputStream getInputStream() throws IOException;
+
+ /**
+ * @return canonical path to class file.
+ */
+ public abstract String getPath();
+
+ /**
+ * @return base path of found class, i.e. class is contained relative to
+ * that path, which may either denote a directory, or zip file
+ */
+ public abstract String getBase();
+
+ /**
+ * @return modification time of class file.
+ */
+ public abstract long getTime();
+
+ /**
+ * @return size of class file.
+ */
+ public abstract long getSize();
+ }
+
+ private static class Dir extends PathEntry {
+ private String dir;
+
+ Dir(String d) {
+ dir = d;
+ }
+
+ ClassFile getClassFile(String name, String suffix) throws IOException {
+ final File file = new File(dir + File.separatorChar + name.replace('.', File.separatorChar) + suffix);
+
+ return file.exists() ? new ClassFile() {
+ public InputStream getInputStream() throws IOException {
+ return new FileInputStream(file);
+ }
+
+ public String getPath() {
+ try {
+ return file.getCanonicalPath();
+ } catch (IOException e) {
+ return null;
+ }
+
+ }
+
+ public long getTime() {
+ return file.lastModified();
+ }
+
+ public long getSize() {
+ return file.length();
+ }
+
+ public String getBase() {
+ return dir;
+ }
+ } : null;
+ }
+
+ public String toString() {
+ return dir;
+ }
+ }
+
+ private static class JImage extends PathEntry {
+ private java.nio.file.FileSystem fs;
+
+ private static URI JRT_URI = URI.create("jrt:/"); //$NON-NLS-1$
+
+ private static String MODULES_PATH = "modules"; //$NON-NLS-1$
+ private static String JAVA_BASE_PATH = "java.base"; //$NON-NLS-1$
+
+
+ JImage(File jimage) {
+ // TODO bizarre that you use getFileSystem with just the jrt:/ and not the path !! What happens
+ // if there are two?
+ fs = FileSystems.getFileSystem(JRT_URI);//.create(jimage.getAbsolutePath()));
+ }
+
+ private static class ByteBasedClassFile implements ClassFile {
+
+ private byte[] bytes;
+ private ByteArrayInputStream bais;
+ private String path;
+ private String base;
+ private long time;
+ private long size;
+
+ public ByteBasedClassFile(byte[] bytes, String path, String base, long time, long size) {
+ this.bytes = bytes;
+ this.path = path;
+ this.base = base;
+ this.time = time;
+ this.size = size;
+ }
+
+ public InputStream getInputStream() throws IOException {
+ // TODO too costly to keep these in inflated form in memory?
+ this.bais = new ByteArrayInputStream(bytes);
+ return this.bais;
+ }
+
+ public String getPath() {
+ return this.path;
+ }
+
+ public String getBase() {
+ return this.base;
+ }
+
+ public long getTime() {
+ return this.time;
+ }
+
+ public long getSize() {
+ return this.size;
+ }
+
+ }
+
+ ClassFile getClassFile(String name, String suffix) throws IOException {
+ // Class files are in here under names like this:
+ // /modules/java.base/java/lang/Object.class (jdk9 b74)
+ // so within a modules top level qualifier and then the java.base module
+ String fileName = name + suffix;
+ try {
+ Path p = fs.getPath(MODULES_PATH,JAVA_BASE_PATH,fileName);
+ byte[] bs = Files.readAllBytes(p);
+ BasicFileAttributeView bfav = Files.getFileAttributeView(p, BasicFileAttributeView.class);
+ BasicFileAttributes bfas = bfav.readAttributes();
+ long time = bfas.lastModifiedTime().toMillis();
+ long size = bfas.size();
+ return new ByteBasedClassFile(bs, "jimage",fileName,time,size);
+ } catch (NoSuchFileException nsfe) {
+ // try other modules!
+ Iterable<java.nio.file.Path> roots = fs.getRootDirectories();
+ roots = fs.getRootDirectories();
+ for (java.nio.file.Path path : roots) {
+ DirectoryStream<java.nio.file.Path> stream = Files.newDirectoryStream(path);
+ try {
+ for (java.nio.file.Path module: stream) {
+ // module will be something like /packages or /modules
+ for (java.nio.file.Path submodule: Files.newDirectoryStream(module)) {
+ // submodule will be /modules/java.base or somesuch
+ try {
+ Path p = fs.getPath(submodule.toString(), fileName);
+ byte[] bs = Files.readAllBytes(p);
+ BasicFileAttributeView bfav = Files.getFileAttributeView(p, BasicFileAttributeView.class);
+ BasicFileAttributes bfas = bfav.readAttributes();
+ long time = bfas.lastModifiedTime().toMillis();
+ long size = bfas.size();
+ return new ByteBasedClassFile(bs, "jimage", fileName,time,size);
+ } catch (NoSuchFileException nsfe2) {
+ }
+ }
+ }
+ } finally {
+ stream.close();
+ }
+ }
+ return null;
+ }
+ }
+ }
+
+ private static class Zip extends PathEntry {
+ private ZipFile zip;
+
+ Zip(ZipFile z) {
+ zip = z;
+ }
+
+ ClassFile getClassFile(String name, String suffix) throws IOException {
+ final ZipEntry entry = zip.getEntry(name.replace('.', '/') + suffix);
+
+ return (entry != null) ? new ClassFile() {
+ public InputStream getInputStream() throws IOException {
+ return zip.getInputStream(entry);
+ }
+
+ public String getPath() {
+ return entry.toString();
+ }
+
+ public long getTime() {
+ return entry.getTime();
+ }
+
+ public long getSize() {
+ return entry.getSize();
+ }
+
+ public String getBase() {
+ return zip.getName();
+ }
+ } : null;
+ }
+ }
+}