Browse Source

[j9] Basic read/write of Module attribute

tags/V1_9_0_BETA4
Andy Clement 8 years ago
parent
commit
f8b86ff2c0
37 changed files with 652 additions and 4 deletions
  1. 9
    1
      bcel-builder/src/org/aspectj/apache/bcel/Constants.java
  2. 432
    0
      bcel-builder/src/org/aspectj/apache/bcel/classfile/Module.java
  3. 24
    0
      bcel-builder/testdata/modules/cpl.sh
  4. BIN
      bcel-builder/testdata/modules/one/module-info.class
  5. 1
    0
      bcel-builder/testdata/modules/one/module-info.java
  6. BIN
      bcel-builder/testdata/modules/two/a/module-info.class
  7. 2
    0
      bcel-builder/testdata/modules/two/a/module-info.java
  8. BIN
      bcel-builder/testdata/modules/two/b/module-info.class
  9. 2
    0
      bcel-builder/testdata/modules/two/b/module-info.java
  10. BIN
      bcel-builder/testdata/modules/two/c/module-info.class
  11. 2
    0
      bcel-builder/testdata/modules/two/c/module-info.java
  12. BIN
      bcel-builder/testdata/modules/two/d/module-info.class
  13. 4
    0
      bcel-builder/testdata/modules/two/d/module-info.java
  14. 3
    0
      bcel-builder/testdata/modules/two/e/C1.java
  15. 3
    0
      bcel-builder/testdata/modules/two/e/C2.java
  16. 3
    0
      bcel-builder/testdata/modules/two/e/C3.java
  17. BIN
      bcel-builder/testdata/modules/two/e/com/foo1/C1.class
  18. BIN
      bcel-builder/testdata/modules/two/e/com/foo2/C2.class
  19. BIN
      bcel-builder/testdata/modules/two/e/com/foo3/C3.class
  20. BIN
      bcel-builder/testdata/modules/two/e/module-info.class
  21. 5
    0
      bcel-builder/testdata/modules/two/e/module-info.java
  22. 3
    0
      bcel-builder/testdata/modules/two/f/I1.java
  23. BIN
      bcel-builder/testdata/modules/two/f/com/foo1/I1.class
  24. BIN
      bcel-builder/testdata/modules/two/f/module-info.class
  25. 3
    0
      bcel-builder/testdata/modules/two/f/module-info.java
  26. 3
    0
      bcel-builder/testdata/modules/two/g/C1.java
  27. 3
    0
      bcel-builder/testdata/modules/two/g/C2.java
  28. 3
    0
      bcel-builder/testdata/modules/two/g/I1.java
  29. 3
    0
      bcel-builder/testdata/modules/two/g/I2.java
  30. BIN
      bcel-builder/testdata/modules/two/g/com/foo1/C1.class
  31. BIN
      bcel-builder/testdata/modules/two/g/com/foo1/I1.class
  32. BIN
      bcel-builder/testdata/modules/two/g/com/foo2/C2.class
  33. BIN
      bcel-builder/testdata/modules/two/g/com/foo2/I2.class
  34. BIN
      bcel-builder/testdata/modules/two/g/module-info.class
  35. 4
    0
      bcel-builder/testdata/modules/two/g/module-info.java
  36. 11
    3
      bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/BcelTestCase.java
  37. 129
    0
      bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/ModuleTest.java

+ 9
- 1
bcel-builder/src/org/aspectj/apache/bcel/Constants.java View File

@@ -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;


+ 432
- 0
bcel-builder/src/org/aspectj/apache/bcel/classfile/Module.java View File

@@ -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
* <http://www.apache.org/>.
*/
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 <em>Attribute</em> 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;i<toModuleNameIndices.length;i++) {
toModuleNames[i] = cpool.getConstantUtf8(toModuleNameIndices[i]).getStringValue();
}
return toModuleNames;
}
public String toString() {
StringBuilder s =new StringBuilder();
s.append("exports ").append(getExportedPackage().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 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;i<requires.length;i++) {
results[i] = cpool.getConstantUtf8(requires[i].moduleNameIndex).getStringValue();
}
return results;
}
public byte[] getBytes() {
return moduleInfo;
}

public Export[] getExports() {
ensureUnpacked();
return exports;
}

public Uses[] getUses() {
ensureUnpacked();
return uses;
}

public Provide[] getProvides() {
ensureUnpacked();
return provides;
}
}

+ 24
- 0
bcel-builder/testdata/modules/cpl.sh View File

@@ -0,0 +1,24 @@
cd one
javac module-info.java
cd ..
cd two/a
javac module-info.java
cd ../..
cd two/b
javac module-info.java
cd ../..
cd two/c
javac module-info.java
cd ../..
cd two/d
javac module-info.java -modulepath ../a:../b
cd ../..
cd two/e
javac module-info.java C1.java C2.java C3.java -d . -modulepath ../a:../b
cd ../..
cd two/f
javac module-info.java I1.java -d .
cd ../..
cd two/g
javac module-info.java I1.java I2.java C1.java C2.java -d .
cd ../..

BIN
bcel-builder/testdata/modules/one/module-info.class View File


+ 1
- 0
bcel-builder/testdata/modules/one/module-info.java View File

@@ -0,0 +1 @@
module one {}

BIN
bcel-builder/testdata/modules/two/a/module-info.class View File


+ 2
- 0
bcel-builder/testdata/modules/two/a/module-info.java View File

@@ -0,0 +1,2 @@
module a.b.c {
}

BIN
bcel-builder/testdata/modules/two/b/module-info.class View File


+ 2
- 0
bcel-builder/testdata/modules/two/b/module-info.java View File

@@ -0,0 +1,2 @@
module b.c.d {
}

BIN
bcel-builder/testdata/modules/two/c/module-info.class View File


+ 2
- 0
bcel-builder/testdata/modules/two/c/module-info.java View File

@@ -0,0 +1,2 @@
module c.d.e {
}

BIN
bcel-builder/testdata/modules/two/d/module-info.class View File


+ 4
- 0
bcel-builder/testdata/modules/two/d/module-info.java View File

@@ -0,0 +1,4 @@
module d.e.f {
requires a.b.c;
requires public b.c.d;
}

+ 3
- 0
bcel-builder/testdata/modules/two/e/C1.java View File

@@ -0,0 +1,3 @@
package com.foo1;

public class C1 {}

+ 3
- 0
bcel-builder/testdata/modules/two/e/C2.java View File

@@ -0,0 +1,3 @@
package com.foo2;

public class C2 {}

+ 3
- 0
bcel-builder/testdata/modules/two/e/C3.java View File

@@ -0,0 +1,3 @@
package com.foo3;

public class C3 {}

BIN
bcel-builder/testdata/modules/two/e/com/foo1/C1.class View File


BIN
bcel-builder/testdata/modules/two/e/com/foo2/C2.class View File


BIN
bcel-builder/testdata/modules/two/e/com/foo3/C3.class View File


BIN
bcel-builder/testdata/modules/two/e/module-info.class View File


+ 5
- 0
bcel-builder/testdata/modules/two/e/module-info.java View File

@@ -0,0 +1,5 @@
module e.f.g {
exports com.foo1;
exports com.foo2 to a.b.c;
exports com.foo3 to a.b.c, b.c.d;
}

+ 3
- 0
bcel-builder/testdata/modules/two/f/I1.java View File

@@ -0,0 +1,3 @@
package com.foo1;

public interface I1 {}

BIN
bcel-builder/testdata/modules/two/f/com/foo1/I1.class View File


BIN
bcel-builder/testdata/modules/two/f/module-info.class View File


+ 3
- 0
bcel-builder/testdata/modules/two/f/module-info.java View File

@@ -0,0 +1,3 @@
module f.g.h {
uses com.foo1.I1;
}

+ 3
- 0
bcel-builder/testdata/modules/two/g/C1.java View File

@@ -0,0 +1,3 @@
package com.foo1;

public class C1 implements I1 {}

+ 3
- 0
bcel-builder/testdata/modules/two/g/C2.java View File

@@ -0,0 +1,3 @@
package com.foo2;

public class C2 implements I2 {}

+ 3
- 0
bcel-builder/testdata/modules/two/g/I1.java View File

@@ -0,0 +1,3 @@
package com.foo1;

public interface I1 {}

+ 3
- 0
bcel-builder/testdata/modules/two/g/I2.java View File

@@ -0,0 +1,3 @@
package com.foo2;

public interface I2 {}

BIN
bcel-builder/testdata/modules/two/g/com/foo1/C1.class View File


BIN
bcel-builder/testdata/modules/two/g/com/foo1/I1.class View File


BIN
bcel-builder/testdata/modules/two/g/com/foo2/C2.class View File


BIN
bcel-builder/testdata/modules/two/g/com/foo2/I2.class View File


BIN
bcel-builder/testdata/modules/two/g/module-info.class View File


+ 4
- 0
bcel-builder/testdata/modules/two/g/module-info.java View File

@@ -0,0 +1,4 @@
module g.h.i {
provides com.foo1.I1 with com.foo1.C1;
provides com.foo2.I2 with com.foo2.C2;
}

+ 11
- 3
bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/BcelTestCase.java View File

@@ -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;
}

}

+ 129
- 0
bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/ModuleTest.java View File

@@ -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<originalData.length;i++) {
if (originalData[i]!=newData[i+6]) {
fail("byte mismatch at position "+i+" of "+newData.length);
}
}
}

public void testRequires() throws Exception {
Module moduleAttr = getModuleAttribute("testdata/modules/two/d/module-info.class");
Require[] requires = moduleAttr.getRequires();
assertEquals(3,requires.length);
assertEquals("requires mandated java.base",requires[0].toString());
assertEquals("requires a.b.c",requires[1].toString());
assertEquals("requires public b.c.d",requires[2].toString());
assertEquals("java.base",requires[0].getModuleName());
assertEquals("a.b.c",requires[1].getModuleName());
assertEquals("b.c.d",requires[2].getModuleName());
}
public void testExports() throws Exception {
Module moduleAttr = getModuleAttribute("testdata/modules/two/e/module-info.class");
Export[] exports = moduleAttr.getExports();
assertEquals(3,exports.length);
assertEquals("exports com.foo1",exports[0].toString());
assertEquals("exports com.foo2 to a.b.c",exports[1].toString());
assertEquals("exports com.foo3 to b.c.d, a.b.c",exports[2].toString());
assertEquals("com/foo1",exports[0].getExportedPackage());
assertEquals("com/foo2",exports[1].getExportedPackage());
assertEquals("com/foo3",exports[2].getExportedPackage());
assertEquals("a.b.c",exports[1].getToModuleNames()[0]);
assertEquals("b.c.d",exports[2].getToModuleNames()[0]);
assertEquals("a.b.c",exports[2].getToModuleNames()[1]);
}
public void testUses() throws Exception {
Module moduleAttr = getModuleAttribute("testdata/modules/two/f/module-info.class");
Uses[] uses = moduleAttr.getUses();
assertEquals(1,uses.length);
assertEquals("com/foo1/I1",uses[0].getTypeName());
assertEquals("uses com.foo1.I1",uses[0].toString());
}
public void testProvides() throws Exception {
Module moduleAttr = getModuleAttribute("testdata/modules/two/g/module-info.class");
Provide[] provides = moduleAttr.getProvides();
assertEquals(2,provides.length);
assertEquals("provides com.foo1.I1 with com.foo1.C1",provides[0].toString());
assertEquals("provides com.foo2.I2 with com.foo2.C2",provides[1].toString());
assertEquals("com/foo1/I1",provides[0].getProvidedType());
assertEquals("com/foo1/C1",provides[0].getWithType());
assertEquals("com/foo2/I2",provides[1].getProvidedType());
assertEquals("com/foo2/C2",provides[1].getWithType());
}

// ---
private Module getModuleAttribute(String moduleInfoClass) throws Exception {
ClassParser classParser = new ClassParser(moduleInfoClass);
JavaClass javaClass = classParser.parse();
Module moduleAttr = new Module((Unknown)getAttribute(javaClass.getAttributes(),Constants.ATTR_UNKNOWN));
return moduleAttr;
}
}

Loading…
Cancel
Save