From f8b86ff2c03a77e47e87573b59bc43c57cfdee38 Mon Sep 17 00:00:00 2001 From: Andy Clement Date: Mon, 6 Jun 2016 12:00:12 -0700 Subject: [PATCH] [j9] Basic read/write of Module attribute --- .../org/aspectj/apache/bcel/Constants.java | 10 +- .../aspectj/apache/bcel/classfile/Module.java | 432 ++++++++++++++++++ bcel-builder/testdata/modules/cpl.sh | 24 + .../testdata/modules/one/module-info.class | Bin 0 -> 124 bytes .../testdata/modules/one/module-info.java | 1 + .../testdata/modules/two/a/module-info.class | Bin 0 -> 126 bytes .../testdata/modules/two/a/module-info.java | 2 + .../testdata/modules/two/b/module-info.class | Bin 0 -> 126 bytes .../testdata/modules/two/b/module-info.java | 2 + .../testdata/modules/two/c/module-info.class | Bin 0 -> 126 bytes .../testdata/modules/two/c/module-info.java | 2 + .../testdata/modules/two/d/module-info.class | Bin 0 -> 150 bytes .../testdata/modules/two/d/module-info.java | 4 + bcel-builder/testdata/modules/two/e/C1.java | 3 + bcel-builder/testdata/modules/two/e/C2.java | 3 + bcel-builder/testdata/modules/two/e/C3.java | 3 + .../testdata/modules/two/e/com/foo1/C1.class | Bin 0 -> 187 bytes .../testdata/modules/two/e/com/foo2/C2.class | Bin 0 -> 187 bytes .../testdata/modules/two/e/com/foo3/C3.class | Bin 0 -> 187 bytes .../testdata/modules/two/e/module-info.class | Bin 0 -> 193 bytes .../testdata/modules/two/e/module-info.java | 5 + bcel-builder/testdata/modules/two/f/I1.java | 3 + .../testdata/modules/two/f/com/foo1/I1.class | Bin 0 -> 94 bytes .../testdata/modules/two/f/module-info.class | Bin 0 -> 145 bytes .../testdata/modules/two/f/module-info.java | 3 + bcel-builder/testdata/modules/two/g/C1.java | 3 + bcel-builder/testdata/modules/two/g/C2.java | 3 + bcel-builder/testdata/modules/two/g/I1.java | 3 + bcel-builder/testdata/modules/two/g/I2.java | 3 + .../testdata/modules/two/g/com/foo1/C1.class | Bin 0 -> 206 bytes .../testdata/modules/two/g/com/foo1/I1.class | Bin 0 -> 94 bytes .../testdata/modules/two/g/com/foo2/C2.class | Bin 0 -> 206 bytes .../testdata/modules/two/g/com/foo2/I2.class | Bin 0 -> 94 bytes .../testdata/modules/two/g/module-info.class | Bin 0 -> 202 bytes .../testdata/modules/two/g/module-info.java | 4 + .../bcel/classfile/tests/BcelTestCase.java | 14 +- .../bcel/classfile/tests/ModuleTest.java | 129 ++++++ 37 files changed, 652 insertions(+), 4 deletions(-) create mode 100644 bcel-builder/src/org/aspectj/apache/bcel/classfile/Module.java create mode 100755 bcel-builder/testdata/modules/cpl.sh create mode 100644 bcel-builder/testdata/modules/one/module-info.class create mode 100644 bcel-builder/testdata/modules/one/module-info.java create mode 100644 bcel-builder/testdata/modules/two/a/module-info.class create mode 100644 bcel-builder/testdata/modules/two/a/module-info.java create mode 100644 bcel-builder/testdata/modules/two/b/module-info.class create mode 100644 bcel-builder/testdata/modules/two/b/module-info.java create mode 100644 bcel-builder/testdata/modules/two/c/module-info.class create mode 100644 bcel-builder/testdata/modules/two/c/module-info.java create mode 100644 bcel-builder/testdata/modules/two/d/module-info.class create mode 100644 bcel-builder/testdata/modules/two/d/module-info.java create mode 100644 bcel-builder/testdata/modules/two/e/C1.java create mode 100644 bcel-builder/testdata/modules/two/e/C2.java create mode 100644 bcel-builder/testdata/modules/two/e/C3.java create mode 100644 bcel-builder/testdata/modules/two/e/com/foo1/C1.class create mode 100644 bcel-builder/testdata/modules/two/e/com/foo2/C2.class create mode 100644 bcel-builder/testdata/modules/two/e/com/foo3/C3.class create mode 100644 bcel-builder/testdata/modules/two/e/module-info.class create mode 100644 bcel-builder/testdata/modules/two/e/module-info.java create mode 100644 bcel-builder/testdata/modules/two/f/I1.java create mode 100644 bcel-builder/testdata/modules/two/f/com/foo1/I1.class create mode 100644 bcel-builder/testdata/modules/two/f/module-info.class create mode 100644 bcel-builder/testdata/modules/two/f/module-info.java create mode 100644 bcel-builder/testdata/modules/two/g/C1.java create mode 100644 bcel-builder/testdata/modules/two/g/C2.java create mode 100644 bcel-builder/testdata/modules/two/g/I1.java create mode 100644 bcel-builder/testdata/modules/two/g/I2.java create mode 100644 bcel-builder/testdata/modules/two/g/com/foo1/C1.class create mode 100644 bcel-builder/testdata/modules/two/g/com/foo1/I1.class create mode 100644 bcel-builder/testdata/modules/two/g/com/foo2/C2.class create mode 100644 bcel-builder/testdata/modules/two/g/com/foo2/I2.class create mode 100644 bcel-builder/testdata/modules/two/g/module-info.class create mode 100644 bcel-builder/testdata/modules/two/g/module-info.java create mode 100644 bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/ModuleTest.java diff --git a/bcel-builder/src/org/aspectj/apache/bcel/Constants.java b/bcel-builder/src/org/aspectj/apache/bcel/Constants.java index 4499284c2..8d8427006 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; @@ -105,12 +107,18 @@ public interface Constants { public final static short ACC_INTERFACE = 0x0200; public final static short ACC_ABSTRACT = 0x0400; public final static short ACC_STRICT = 0x0800; - + 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 + public final static int MODULE_ACC_PUBLIC = 0x0020; + public final static int MODULE_ACC_SYNTHETIC = 0x1000; + public final static int MODULE_ACC_MANDATED = 0x8000; + // Applies to classes compiled by new compilers only public final static short ACC_SUPER = 0x0020; 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..217f5fbd0 --- /dev/null +++ b/bcel-builder/src/org/aspectj/apache/bcel/classfile/Module.java @@ -0,0 +1,432 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 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 + * . + */ +package org.aspectj.apache.bcel.classfile; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.Module.Export; + +/** + * This class is derived from Attribute and represents the module + * information captured in a class file. + * http://cr.openjdk.java.net/~mr/jigsaw/spec/lang-vm.html + * + * @author Andy Clement + */ +public final class Module extends Attribute { + + private static final String[] NO_MODULE_NAMES = {}; + + private byte[] moduleInfo; + private int ptr; + private boolean unpacked = false; + private Require[] requires; + private Export[] exports; + private Uses[] uses; + private Provide[] provides; + + /** + * Build a Module attribute from a previously Unknown attribute. + */ + public Module(Unknown unknown) { + super(unknown.getTag(), unknown.getNameIndex(), unknown.getLength(), unknown.getConstantPool()); + moduleInfo = unknown.getBytes(); + } + + public class Require { + + private final int moduleNameIndex; + private final int requiresFlags; + + public Require(int moduleNameIndex, int requiresFlags) { + this.moduleNameIndex = moduleNameIndex; + this.requiresFlags = requiresFlags; + } + + public String getModuleName() { + return cpool.getConstantUtf8(moduleNameIndex).getStringValue(); + } + + public int getRequiresFlags() { + return requiresFlags; + } + + public String getRequiresFlagsAsString() { + StringBuilder s = new StringBuilder(); + if ((requiresFlags & Constants.MODULE_ACC_PUBLIC)!=0) { + s.append("public "); + } + if ((requiresFlags & Constants.MODULE_ACC_SYNTHETIC)!=0) { + s.append("synthetic "); + } + if ((requiresFlags & Constants.MODULE_ACC_MANDATED)!=0) { + s.append("mandated "); + } + return s.toString(); + } + + public String toString() { + return "requires "+getRequiresFlagsAsString()+getModuleName(); + } + + } + + + public class Export { + + private final int exportedPackageNameIndex; + private final int[] toModuleNameIndices; + + public Export(int exportedPackageNameIndex, int[] toModuleNameIndices) { + this.exportedPackageNameIndex = exportedPackageNameIndex; + this.toModuleNameIndices = toModuleNameIndices; + } + + public String getExportedPackage() { + return cpool.getConstantUtf8(exportedPackageNameIndex).getStringValue(); + } + + public String[] getToModuleNames() { + if (toModuleNameIndices==null) { + return NO_MODULE_NAMES; + } + String[] toModuleNames = new String[toModuleNameIndices.length]; + for (int i=0;i0) { + s.append(", "); + } + s.append(toModules[i]); + } + } + return s.toString().trim(); + } + } + + public class Provide { + private final int providedTypeIndex; + private final int withTypeIndex; + + public Provide(int providedTypeIndex, int withTypeIndex) { + this.providedTypeIndex = providedTypeIndex; + this.withTypeIndex = withTypeIndex; + } + + public String getProvidedType() { + return cpool.getConstantString_CONSTANTClass(providedTypeIndex); + } + + public int getProvidedTypeIndex() { + return providedTypeIndex; + } + + public String getWithType() { + return cpool.getConstantString_CONSTANTClass(withTypeIndex); + } + + public int getWithTypeIndex() { + return withTypeIndex; + } + + public String toString() { + StringBuilder s =new StringBuilder(); + s.append("provides ").append(getProvidedType().replace('/', '.')); + s.append(" with ").append(getWithType().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); + } + + private void ensureUnpacked() { + if (!unpacked) { + ptr = 0; + int count = readUnsignedShort(); + requires = new Require[count]; + for (int i = 0; i < count; i++) { + requires[i] = new Require(readUnsignedShort(), readUnsignedShort()); + } + count = readUnsignedShort(); + exports = new Export[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(); + } + exports[i] = new Export(index, 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++) { + provides[i] = new Provide(readUnsignedShort(), readUnsignedShort()); + } + unpacked = true; + } + } + + @Override + public final void dump(DataOutputStream file) throws IOException { + super.dump(file); + if (!unpacked) { + file.write(moduleInfo); + } else { + file.writeShort(requires.length); + for (int i = 0; i < requires.length; i++) { + file.writeShort(requires[i].moduleNameIndex); + file.writeShort(requires[i].requiresFlags); + } + file.writeShort(exports.length); + for (Export export : exports) { + file.writeShort(export.exportedPackageNameIndex); + int[] toIndices = export.toModuleNameIndices; + 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); + file.writeShort(provide.withTypeIndex); + } + } + } + + 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.moduleNameIndex).append(':').append(require.requiresFlags); + } + } + 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.exportedPackageNameIndex).append(":["); + int[] toIndices = export.toModuleNameIndices; + 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(':').append(provide.withTypeIndex); + } + } + 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 (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 (SourceFile) clone(); + // } + @Override + public void accept(ClassVisitor v) { + v.visitSourceFile(this); + } + + public Require[] getRequires() { + ensureUnpacked(); + return requires; + } + + public String[] getRequiredModuleNames() { + ensureUnpacked(); + String[] results = new String[requires.length]; + for (int i=0;iKfq`HBDfe~mb1TZl$0U1mT%nU3*ng=Mu+5nMZ003$3 B8t(uA literal 0 HcmV?d00001 diff --git a/bcel-builder/testdata/modules/two/b/module-info.java b/bcel-builder/testdata/modules/two/b/module-info.java new file mode 100644 index 000000000..308ba05bb --- /dev/null +++ b/bcel-builder/testdata/modules/two/b/module-info.java @@ -0,0 +1,2 @@ +module b.c.d { +} diff --git a/bcel-builder/testdata/modules/two/c/module-info.class b/bcel-builder/testdata/modules/two/c/module-info.class new file mode 100644 index 0000000000000000000000000000000000000000..0c81601d50e6b38d79ec5620937f7c305608dfc7 GIT binary patch literal 126 zcmX^0Z`VEs1_o0Gc6J6fMh33n{L-T2RJY8WR7M7Y-29Z%oK)S+ytI71ti-ZJMg}%t zun;2yCy1|?lvoT@Cz!0CqMxddq`HBDfe~mb1TZl$0U1mT%nU3*ng=Mu+5nMZ003%} B8u9=D literal 0 HcmV?d00001 diff --git a/bcel-builder/testdata/modules/two/c/module-info.java b/bcel-builder/testdata/modules/two/c/module-info.java new file mode 100644 index 000000000..501d75a06 --- /dev/null +++ b/bcel-builder/testdata/modules/two/c/module-info.java @@ -0,0 +1,2 @@ +module c.d.e { +} diff --git a/bcel-builder/testdata/modules/two/d/module-info.class b/bcel-builder/testdata/modules/two/d/module-info.class new file mode 100644 index 0000000000000000000000000000000000000000..358624633050f635dde98ed7fdb3b8a366da5f4d GIT binary patch literal 150 zcmX^0Z`VEs1_o0GPId+kMh33n{L-T2RJY8WR7M7Y-29Z%oK)S+ytI71ti-ZJMg}%t zun;2yCy1|?lvoT@#|mWVB?D<7sh7gYAef?`s-LEhq`QHEfe~m61TZl$0U1mT%nU3* US_DY5HZU--0om*f3P2JF0BD;YLjV8( literal 0 HcmV?d00001 diff --git a/bcel-builder/testdata/modules/two/d/module-info.java b/bcel-builder/testdata/modules/two/d/module-info.java new file mode 100644 index 000000000..5b9446eed --- /dev/null +++ b/bcel-builder/testdata/modules/two/d/module-info.java @@ -0,0 +1,4 @@ +module d.e.f { + requires a.b.c; + requires public b.c.d; +} diff --git a/bcel-builder/testdata/modules/two/e/C1.java b/bcel-builder/testdata/modules/two/e/C1.java new file mode 100644 index 000000000..eb087840d --- /dev/null +++ b/bcel-builder/testdata/modules/two/e/C1.java @@ -0,0 +1,3 @@ +package com.foo1; + +public class C1 {} diff --git a/bcel-builder/testdata/modules/two/e/C2.java b/bcel-builder/testdata/modules/two/e/C2.java new file mode 100644 index 000000000..528b87e02 --- /dev/null +++ b/bcel-builder/testdata/modules/two/e/C2.java @@ -0,0 +1,3 @@ +package com.foo2; + +public class C2 {} diff --git a/bcel-builder/testdata/modules/two/e/C3.java b/bcel-builder/testdata/modules/two/e/C3.java new file mode 100644 index 000000000..205f75fac --- /dev/null +++ b/bcel-builder/testdata/modules/two/e/C3.java @@ -0,0 +1,3 @@ +package com.foo3; + +public class C3 {} diff --git a/bcel-builder/testdata/modules/two/e/com/foo1/C1.class b/bcel-builder/testdata/modules/two/e/com/foo1/C1.class new file mode 100644 index 0000000000000000000000000000000000000000..6b5bb5fd4e4b3946e91cb1606e18fa25d29d2f7c GIT binary patch literal 187 zcmW-ay$ZrW5QJy*cbY`>1uX2;!jQsFYywuIg<^k+r(8&K5E9?ZO0e(&d?;~~U6|#Y zVc75Q{Q1uX2;!a%@IYywuIg<^k+r(8&K5E9?ZO0e(&d?;~~U6|#Y zVc75Q{Q1uX2;!W6+yYywuIg<^k+r(8&K5E9?ZO0e(&d?;~~U6|#Y zVc75Q{Q>jQF literal 0 HcmV?d00001 diff --git a/bcel-builder/testdata/modules/two/f/module-info.java b/bcel-builder/testdata/modules/two/f/module-info.java new file mode 100644 index 000000000..78978622c --- /dev/null +++ b/bcel-builder/testdata/modules/two/f/module-info.java @@ -0,0 +1,3 @@ +module f.g.h { + uses com.foo1.I1; +} diff --git a/bcel-builder/testdata/modules/two/g/C1.java b/bcel-builder/testdata/modules/two/g/C1.java new file mode 100644 index 000000000..e25a57ec8 --- /dev/null +++ b/bcel-builder/testdata/modules/two/g/C1.java @@ -0,0 +1,3 @@ +package com.foo1; + +public class C1 implements I1 {} diff --git a/bcel-builder/testdata/modules/two/g/C2.java b/bcel-builder/testdata/modules/two/g/C2.java new file mode 100644 index 000000000..100c37b18 --- /dev/null +++ b/bcel-builder/testdata/modules/two/g/C2.java @@ -0,0 +1,3 @@ +package com.foo2; + +public class C2 implements I2 {} diff --git a/bcel-builder/testdata/modules/two/g/I1.java b/bcel-builder/testdata/modules/two/g/I1.java new file mode 100644 index 000000000..88029d83c --- /dev/null +++ b/bcel-builder/testdata/modules/two/g/I1.java @@ -0,0 +1,3 @@ +package com.foo1; + +public interface I1 {} diff --git a/bcel-builder/testdata/modules/two/g/I2.java b/bcel-builder/testdata/modules/two/g/I2.java new file mode 100644 index 000000000..bd52da822 --- /dev/null +++ b/bcel-builder/testdata/modules/two/g/I2.java @@ -0,0 +1,3 @@ +package com.foo2; + +public interface I2 {} diff --git a/bcel-builder/testdata/modules/two/g/com/foo1/C1.class b/bcel-builder/testdata/modules/two/g/com/foo1/C1.class new file mode 100644 index 0000000000000000000000000000000000000000..dfc9448368185cfc64495af6683dee03c56a865d GIT binary patch literal 206 zcmX^0Z`VEs1_o0Gel7-P25xo+9(D#^b_PC11~!|_yv!0iMh0dL%`ip=7U%qwR7M7V zpUk{eztY^K)S{5Yq#U3KS8#r5QF5wVCWyoCY^ax&SeD4cz{B8%CI)TWY`$k88{d?0ZJ<=*Z=?k literal 0 HcmV?d00001 diff --git a/bcel-builder/testdata/modules/two/g/module-info.java b/bcel-builder/testdata/modules/two/g/module-info.java new file mode 100644 index 000000000..00633c573 --- /dev/null +++ b/bcel-builder/testdata/modules/two/g/module-info.java @@ -0,0 +1,4 @@ +module g.h.i { + provides com.foo1.I1 with com.foo1.C1; + provides com.foo2.I2 with com.foo2.C2; +} diff --git a/bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/BcelTestCase.java b/bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/BcelTestCase.java index 3311c5386..ef4b8a9a7 100644 --- a/bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/BcelTestCase.java +++ b/bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/BcelTestCase.java @@ -1,5 +1,5 @@ /* ******************************************************************* - * Copyright (c) 2004, 2013 IBM, VMware + * Copyright (c) 2004 - 2016 IBM, VMware, Contributors * All rights reserved. * This program and the accompanying materials are made available * under the terms of the Eclipse Public License v1.0 @@ -34,8 +34,7 @@ import org.aspectj.apache.bcel.util.SyntheticRepository; /** * Super class for the Java5 tests, includes various helper methods. */ - -public class BcelTestCase extends TestCase { +public abstract class BcelTestCase extends TestCase { private boolean verbose = false; @@ -175,4 +174,13 @@ public class BcelTestCase extends TestCase { return null; } + public Attribute getAttribute(Attribute[] attrs, String name) { + for (Attribute attr: attrs) { + if (attr.getName().equals(name)) { + return attr; + } + } + return null; + } + } diff --git a/bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/ModuleTest.java b/bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/ModuleTest.java new file mode 100644 index 000000000..d6e2b456b --- /dev/null +++ b/bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/ModuleTest.java @@ -0,0 +1,129 @@ +/* ******************************************************************* + * Copyright (c) 2016 Contributors + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement - initial implementation + * ******************************************************************/ + +package org.aspectj.apache.bcel.classfile.tests; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.Attribute; +import org.aspectj.apache.bcel.classfile.ClassParser; +import org.aspectj.apache.bcel.classfile.JavaClass; +import org.aspectj.apache.bcel.classfile.Module; +import org.aspectj.apache.bcel.classfile.Module.Export; +import org.aspectj.apache.bcel.classfile.Module.Provide; +import org.aspectj.apache.bcel.classfile.Module.Require; +import org.aspectj.apache.bcel.classfile.Module.Uses; +import org.aspectj.apache.bcel.classfile.SourceFile; +import org.aspectj.apache.bcel.classfile.Unknown; + +/** + * http://cr.openjdk.java.net/~mr/jigsaw/spec/lang-vm.html + * + * @author Andy Clement + */ +public class ModuleTest extends BcelTestCase { + + public void testLoadSimpleModuleClass() throws Exception { + String moduleFilename = "testdata/modules/one/module-info.class"; + ClassParser classParser = new ClassParser(moduleFilename); + JavaClass javaClass = classParser.parse(); + assertNotNull(javaClass); + assertEquals(Constants.MAJOR_1_9,javaClass.getMajor()); + assertEquals(Constants.MINOR_1_9,javaClass.getMinor()); + assertEquals(Constants.ACC_MODULE,javaClass.getModifiers()); + assertEquals(0,javaClass.getSuperclassNameIndex()); + assertEquals(0,javaClass.getInterfaceIndices().length); + assertEquals(0,javaClass.getFields().length); + assertEquals(0,javaClass.getMethods().length); + Attribute[] attrs = javaClass.getAttributes(); + assertEquals(2,attrs.length); + SourceFile sourceFile = (SourceFile) getAttribute(attrs,Constants.ATTR_SOURCE_FILE); + Module moduleAttr = new Module((Unknown)getAttribute(attrs,Constants.ATTR_UNKNOWN)); + byte[] originalData = moduleAttr.getBytes(); + String[] requiredModuleNames = moduleAttr.getRequiredModuleNames(); + assertEquals(1,requiredModuleNames.length); + assertEquals("java.base",requiredModuleNames[0]); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + moduleAttr.dump(new DataOutputStream(baos)); + byte[] newData = baos.toByteArray(); + // The 6 offset here is because the newdata includes the 2byte cpool pointer for the name 'Module' + // and the 4byte int length field for the attribute data + if (newData.length!=originalData.length+6) { + fail("Expected the length of the original attribute ("+originalData.length+") to match the new written length ("+newData.length+")"); + } + for (int i=0;i