--- a/jdk/src/java.base/share/classes/jdk/internal/module/ClassFileAttributes.java Wed Nov 23 16:16:35 2016 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ClassFileAttributes.java Thu Dec 01 08:57:53 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,17 +27,20 @@
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleDescriptor.Requires;
-import java.lang.module.ModuleDescriptor.Requires.Modifier;
import java.lang.module.ModuleDescriptor.Exports;
+import java.lang.module.ModuleDescriptor.Opens;
import java.lang.module.ModuleDescriptor.Provides;
import java.lang.module.ModuleDescriptor.Version;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.LinkedHashSet;
+import java.util.List;
import java.util.Map;
import java.util.Set;
+import jdk.internal.misc.JavaLangModuleAccess;
+import jdk.internal.misc.SharedSecrets;
import jdk.internal.org.objectweb.asm.Attribute;
import jdk.internal.org.objectweb.asm.ByteVector;
import jdk.internal.org.objectweb.asm.ClassReader;
@@ -51,7 +54,7 @@
* class file attributes in a module-info class file.
*/
-class ClassFileAttributes {
+public final class ClassFileAttributes {
private ClassFileAttributes() { }
@@ -60,16 +63,18 @@
* // See lang-vm.html for details.
* }
*/
- static class ModuleAttribute extends Attribute {
+ public static class ModuleAttribute extends Attribute {
+ private static final JavaLangModuleAccess JLMA
+ = SharedSecrets.getJavaLangModuleAccess();
private ModuleDescriptor descriptor;
- ModuleAttribute(ModuleDescriptor descriptor) {
+ public ModuleAttribute(ModuleDescriptor descriptor) {
super(MODULE);
this.descriptor = descriptor;
}
- ModuleAttribute() {
+ public ModuleAttribute() {
super(MODULE);
}
@@ -81,27 +86,43 @@
int codeOff,
Label[] labels)
{
- ModuleDescriptor.Builder builder
- = new ModuleDescriptor.Builder("xyzzy"); // Name never used
ModuleAttribute attr = new ModuleAttribute();
+ // module_name
+ String mn = cr.readUTF8(off, buf).replace('/', '.');
+ off += 2;
+
+ // module_flags
+ int module_flags = cr.readUnsignedShort(off);
+ boolean open = ((module_flags & ACC_OPEN) != 0);
+ off += 2;
+
+ ModuleDescriptor.Builder builder;
+ if (open) {
+ builder = JLMA.newOpenModuleBuilder(mn, false);
+ } else {
+ builder = JLMA.newModuleBuilder(mn, false);
+ }
+
// requires_count and requires[requires_count]
int requires_count = cr.readUnsignedShort(off);
off += 2;
for (int i=0; i<requires_count; i++) {
- String dn = cr.readUTF8(off, buf);
+ String dn = cr.readUTF8(off, buf).replace('/', '.');
int flags = cr.readUnsignedShort(off + 2);
- Set<Modifier> mods;
+ Set<Requires.Modifier> mods;
if (flags == 0) {
mods = Collections.emptySet();
} else {
mods = new HashSet<>();
- if ((flags & ACC_PUBLIC) != 0)
- mods.add(Modifier.PUBLIC);
+ if ((flags & ACC_TRANSITIVE) != 0)
+ mods.add(Requires.Modifier.TRANSITIVE);
+ if ((flags & ACC_STATIC_PHASE) != 0)
+ mods.add(Requires.Modifier.STATIC);
if ((flags & ACC_SYNTHETIC) != 0)
- mods.add(Modifier.SYNTHETIC);
+ mods.add(Requires.Modifier.SYNTHETIC);
if ((flags & ACC_MANDATED) != 0)
- mods.add(Modifier.MANDATED);
+ mods.add(Requires.Modifier.MANDATED);
}
builder.requires(mods, dn);
off += 4;
@@ -113,18 +134,70 @@
if (exports_count > 0) {
for (int i=0; i<exports_count; i++) {
String pkg = cr.readUTF8(off, buf).replace('/', '.');
- int exports_to_count = cr.readUnsignedShort(off+2);
- off += 4;
+ off += 2;
+
+ int flags = cr.readUnsignedShort(off);
+ off += 2;
+ Set<Exports.Modifier> mods;
+ if (flags == 0) {
+ mods = Collections.emptySet();
+ } else {
+ mods = new HashSet<>();
+ if ((flags & ACC_SYNTHETIC) != 0)
+ mods.add(Exports.Modifier.SYNTHETIC);
+ if ((flags & ACC_MANDATED) != 0)
+ mods.add(Exports.Modifier.MANDATED);
+ }
+
+ int exports_to_count = cr.readUnsignedShort(off);
+ off += 2;
if (exports_to_count > 0) {
Set<String> targets = new HashSet<>();
for (int j=0; j<exports_to_count; j++) {
- String t = cr.readUTF8(off, buf);
+ String t = cr.readUTF8(off, buf).replace('/', '.');
off += 2;
targets.add(t);
}
- builder.exports(pkg, targets);
+ builder.exports(mods, pkg, targets);
} else {
- builder.exports(pkg);
+ builder.exports(mods, pkg);
+ }
+ }
+ }
+
+ // opens_count and opens[opens_count]
+ int open_count = cr.readUnsignedShort(off);
+ off += 2;
+ if (open_count > 0) {
+ for (int i=0; i<open_count; i++) {
+ String pkg = cr.readUTF8(off, buf).replace('/', '.');
+ off += 2;
+
+ int flags = cr.readUnsignedShort(off);
+ off += 2;
+ Set<Opens.Modifier> mods;
+ if (flags == 0) {
+ mods = Collections.emptySet();
+ } else {
+ mods = new HashSet<>();
+ if ((flags & ACC_SYNTHETIC) != 0)
+ mods.add(Opens.Modifier.SYNTHETIC);
+ if ((flags & ACC_MANDATED) != 0)
+ mods.add(Opens.Modifier.MANDATED);
+ }
+
+ int opens_to_count = cr.readUnsignedShort(off);
+ off += 2;
+ if (opens_to_count > 0) {
+ Set<String> targets = new HashSet<>();
+ for (int j=0; j<opens_to_count; j++) {
+ String t = cr.readUTF8(off, buf).replace('/', '.');
+ off += 2;
+ targets.add(t);
+ }
+ builder.opens(mods, pkg, targets);
+ } else {
+ builder.opens(mods, pkg);
}
}
}
@@ -144,15 +217,19 @@
int provides_count = cr.readUnsignedShort(off);
off += 2;
if (provides_count > 0) {
- Map<String, Set<String>> provides = new HashMap<>();
for (int i=0; i<provides_count; i++) {
- String sn = cr.readClass(off, buf).replace('/', '.');
- String cn = cr.readClass(off + 2, buf).replace('/', '.');
- provides.computeIfAbsent(sn, k -> new LinkedHashSet<>()).add(cn);
- off += 4;
+ String service = cr.readClass(off, buf).replace('/', '.');
+ off += 2;
+ int with_count = cr.readUnsignedShort(off);
+ off += 2;
+ List<String> providers = new ArrayList<>();
+ for (int j=0; j<with_count; j++) {
+ String cn = cr.readClass(off, buf).replace('/', '.');
+ off += 2;
+ providers.add(cn);
+ }
+ builder.provides(service, providers);
}
- provides.entrySet().forEach(e -> builder.provides(e.getKey(),
- e.getValue()));
}
attr.descriptor = builder.build();
@@ -169,6 +246,19 @@
assert descriptor != null;
ByteVector attr = new ByteVector();
+ // module_name
+ String mn = descriptor.name();
+ int module_name_index = cw.newUTF8(mn.replace('.', '/'));
+ attr.putShort(module_name_index);
+
+ // module_flags
+ int module_flags = 0;
+ if (descriptor.isOpen())
+ module_flags |= ACC_OPEN;
+ if (descriptor.isSynthetic())
+ module_flags |= ACC_SYNTHETIC;
+ attr.putShort(module_flags);
+
// requires_count
attr.putShort(descriptor.requires().size());
@@ -176,32 +266,61 @@
for (Requires md : descriptor.requires()) {
String dn = md.name();
int flags = 0;
- if (md.modifiers().contains(Modifier.PUBLIC))
- flags |= ACC_PUBLIC;
- if (md.modifiers().contains(Modifier.SYNTHETIC))
+ if (md.modifiers().contains(Requires.Modifier.TRANSITIVE))
+ flags |= ACC_TRANSITIVE;
+ if (md.modifiers().contains(Requires.Modifier.STATIC))
+ flags |= ACC_STATIC_PHASE;
+ if (md.modifiers().contains(Requires.Modifier.SYNTHETIC))
flags |= ACC_SYNTHETIC;
- if (md.modifiers().contains(Modifier.MANDATED))
+ if (md.modifiers().contains(Requires.Modifier.MANDATED))
flags |= ACC_MANDATED;
- int index = cw.newUTF8(dn);
+ int index = cw.newUTF8(dn.replace('.', '/'));
attr.putShort(index);
attr.putShort(flags);
}
// exports_count and exports[exports_count];
- if (descriptor.exports().isEmpty()) {
- attr.putShort(0);
- } else {
- attr.putShort(descriptor.exports().size());
- for (Exports e : descriptor.exports()) {
- String pkg = e.source().replace('.', '/');
- attr.putShort(cw.newUTF8(pkg));
- if (e.isQualified()) {
- Set<String> ts = e.targets();
- attr.putShort(ts.size());
- ts.forEach(t -> attr.putShort(cw.newUTF8(t)));
- } else {
- attr.putShort(0);
- }
+ attr.putShort(descriptor.exports().size());
+ for (Exports e : descriptor.exports()) {
+ String pkg = e.source().replace('.', '/');
+ attr.putShort(cw.newUTF8(pkg));
+
+ int flags = 0;
+ if (e.modifiers().contains(Exports.Modifier.SYNTHETIC))
+ flags |= ACC_SYNTHETIC;
+ if (e.modifiers().contains(Exports.Modifier.MANDATED))
+ flags |= ACC_MANDATED;
+ attr.putShort(flags);
+
+ if (e.isQualified()) {
+ Set<String> ts = e.targets();
+ attr.putShort(ts.size());
+ ts.forEach(t -> attr.putShort(cw.newUTF8(t.replace('.', '/'))));
+ } else {
+ attr.putShort(0);
+ }
+ }
+
+
+ // opens_counts and opens[opens_counts]
+ attr.putShort(descriptor.opens().size());
+ for (Opens obj : descriptor.opens()) {
+ String pkg = obj.source().replace('.', '/');
+ attr.putShort(cw.newUTF8(pkg));
+
+ int flags = 0;
+ if (obj.modifiers().contains(Opens.Modifier.SYNTHETIC))
+ flags |= ACC_SYNTHETIC;
+ if (obj.modifiers().contains(Opens.Modifier.MANDATED))
+ flags |= ACC_MANDATED;
+ attr.putShort(flags);
+
+ if (obj.isQualified()) {
+ Set<String> ts = obj.targets();
+ attr.putShort(ts.size());
+ ts.forEach(t -> attr.putShort(cw.newUTF8(t.replace('.', '/'))));
+ } else {
+ attr.putShort(0);
}
}
@@ -221,14 +340,13 @@
if (descriptor.provides().isEmpty()) {
attr.putShort(0);
} else {
- int count = descriptor.provides().values()
- .stream().mapToInt(ps -> ps.providers().size()).sum();
- attr.putShort(count);
- for (Provides p : descriptor.provides().values()) {
+ attr.putShort(descriptor.provides().size());
+ for (Provides p : descriptor.provides()) {
String service = p.service().replace('.', '/');
- int index = cw.newClass(service);
+ attr.putShort(cw.newClass(service));
+ int with_count = p.providers().size();
+ attr.putShort(with_count);
for (String provider : p.providers()) {
- attr.putShort(index);
attr.putShort(cw.newClass(provider.replace('.', '/')));
}
}
@@ -239,44 +357,13 @@
}
/**
- * Synthetic attribute.
- */
- static class SyntheticAttribute extends Attribute {
- SyntheticAttribute() {
- super(SYNTHETIC);
- }
-
- @Override
- protected Attribute read(ClassReader cr,
- int off,
- int len,
- char[] buf,
- int codeOff,
- Label[] labels)
- {
- return new SyntheticAttribute();
- }
-
- @Override
- protected ByteVector write(ClassWriter cw,
- byte[] code,
- int len,
- int maxStack,
- int maxLocals)
- {
- ByteVector attr = new ByteVector();
- return attr;
- }
- }
-
- /**
- * ConcealedPackages attribute.
+ * ModulePackages attribute.
*
* <pre> {@code
*
- * ConcealedPackages_attribute {
+ * ModulePackages_attribute {
* // index to CONSTANT_utf8_info structure in constant pool representing
- * // the string "ConcealedPackages"
+ * // the string "ModulePackages"
* u2 attribute_name_index;
* u4 attribute_length;
*
@@ -288,15 +375,15 @@
*
* }</pre>
*/
- static class ConcealedPackagesAttribute extends Attribute {
+ public static class ModulePackagesAttribute extends Attribute {
private final Set<String> packages;
- ConcealedPackagesAttribute(Set<String> packages) {
- super(CONCEALED_PACKAGES);
+ public ModulePackagesAttribute(Set<String> packages) {
+ super(MODULE_PACKAGES);
this.packages = packages;
}
- ConcealedPackagesAttribute() {
+ public ModulePackagesAttribute() {
this(null);
}
@@ -320,7 +407,7 @@
off += 2;
}
- return new ConcealedPackagesAttribute(packages);
+ return new ModulePackagesAttribute(packages);
}
@Override
@@ -348,13 +435,13 @@
}
/**
- * Version attribute.
+ * ModuleVersion attribute.
*
* <pre> {@code
*
- * Version_attribute {
+ * ModuleVersion_attribute {
* // index to CONSTANT_utf8_info structure in constant pool representing
- * // the string "Version"
+ * // the string "ModuleVersion"
* u2 attribute_name_index;
* u4 attribute_length;
*
@@ -364,15 +451,15 @@
*
* } </pre>
*/
- static class VersionAttribute extends Attribute {
+ public static class ModuleVersionAttribute extends Attribute {
private final Version version;
- VersionAttribute(Version version) {
- super(VERSION);
+ public ModuleVersionAttribute(Version version) {
+ super(MODULE_VERSION);
this.version = version;
}
- VersionAttribute() {
+ public ModuleVersionAttribute() {
this(null);
}
@@ -385,7 +472,7 @@
Label[] labels)
{
String value = cr.readUTF8(off, buf);
- return new VersionAttribute(Version.parse(value));
+ return new ModuleVersionAttribute(Version.parse(value));
}
@Override
@@ -403,13 +490,13 @@
}
/**
- * MainClass attribute.
+ * ModuleMainClass attribute.
*
* <pre> {@code
*
* MainClass_attribute {
* // index to CONSTANT_utf8_info structure in constant pool representing
- * // the string "MainClass"
+ * // the string "ModuleMainClass"
* u2 attribute_name_index;
* u4 attribute_length;
*
@@ -419,15 +506,15 @@
*
* } </pre>
*/
- static class MainClassAttribute extends Attribute {
+ public static class ModuleMainClassAttribute extends Attribute {
private final String mainClass;
- MainClassAttribute(String mainClass) {
- super(MAIN_CLASS);
+ public ModuleMainClassAttribute(String mainClass) {
+ super(MODULE_MAIN_CLASS);
this.mainClass = mainClass;
}
- MainClassAttribute() {
+ public ModuleMainClassAttribute() {
this(null);
}
@@ -440,7 +527,7 @@
Label[] labels)
{
String value = cr.readClass(off, buf);
- return new MainClassAttribute(value);
+ return new ModuleMainClassAttribute(value);
}
@Override
@@ -458,13 +545,13 @@
}
/**
- * TargetPlatform attribute.
+ * ModuleTarget attribute.
*
* <pre> {@code
*
* TargetPlatform_attribute {
* // index to CONSTANT_utf8_info structure in constant pool representing
- * // the string "TargetPlatform"
+ * // the string "ModuleTarget"
* u2 attribute_name_index;
* u4 attribute_length;
*
@@ -478,19 +565,19 @@
*
* } </pre>
*/
- static class TargetPlatformAttribute extends Attribute {
+ public static class ModuleTargetAttribute extends Attribute {
private final String osName;
private final String osArch;
private final String osVersion;
- TargetPlatformAttribute(String osName, String osArch, String osVersion) {
- super(TARGET_PLATFORM);
+ public ModuleTargetAttribute(String osName, String osArch, String osVersion) {
+ super(MODULE_TARGET);
this.osName = osName;
this.osArch = osArch;
this.osVersion = osVersion;
}
- TargetPlatformAttribute() {
+ public ModuleTargetAttribute() {
this(null, null, null);
}
@@ -522,7 +609,7 @@
osVersion = cr.readUTF8(off, buf);
off += 2;
- return new TargetPlatformAttribute(osName, osArch, osVersion);
+ return new ModuleTargetAttribute(osName, osArch, osVersion);
}
@Override
@@ -554,39 +641,37 @@
}
/**
- * Hashes attribute.
+ * ModuleHashes attribute.
*
* <pre> {@code
*
- * Hashes_attribute {
+ * ModuleHashes_attribute {
* // index to CONSTANT_utf8_info structure in constant pool representing
- * // the string "Hashes"
+ * // the string "ModuleHashes"
* u2 attribute_name_index;
* u4 attribute_length;
*
- * // index to CONSTANT_CONSTANT_utf8_info structure with algorithm name
+ * // index to CONSTANT_utf8_info structure with algorithm name
* u2 algorithm_index;
*
* // the number of entries in the hashes table
- * u2 hash_count;
- * { u2 requires_index
- * u2 hash_index;
- * } hashes[hash_count];
+ * u2 hashes_count;
+ * { u2 module_name_index
+ * u2 hash_length;
+ * u1 hash[hash_length];
+ * } hashes[hashes_count];
*
* } </pre>
- *
- * @apiNote For now the hash is stored in base64 as a UTF-8 string, an
- * alternative is to store it as an array of u1.
*/
- static class HashesAttribute extends Attribute {
+ static class ModuleHashesAttribute extends Attribute {
private final ModuleHashes hashes;
- HashesAttribute(ModuleHashes hashes) {
- super(HASHES);
+ ModuleHashesAttribute(ModuleHashes hashes) {
+ super(MODULE_HASHES);
this.hashes = hashes;
}
- HashesAttribute() {
+ ModuleHashesAttribute() {
this(null);
}
@@ -601,21 +686,28 @@
String algorithm = cr.readUTF8(off, buf);
off += 2;
- int hash_count = cr.readUnsignedShort(off);
+ int hashes_count = cr.readUnsignedShort(off);
off += 2;
- Map<String, String> map = new HashMap<>();
- for (int i=0; i<hash_count; i++) {
- String dn = cr.readUTF8(off, buf);
+ Map<String, byte[]> map = new HashMap<>();
+ for (int i=0; i<hashes_count; i++) {
+ String mn = cr.readUTF8(off, buf).replace('/', '.');
+ off += 2;
+
+ int hash_length = cr.readUnsignedShort(off);
off += 2;
- String hash = cr.readUTF8(off, buf);
- off += 2;
- map.put(dn, hash);
+ byte[] hash = new byte[hash_length];
+ for (int j=0; j<hash_length; j++) {
+ hash[j] = (byte) (0xff & cr.readByte(off+j));
+ }
+ off += hash_length;
+
+ map.put(mn, hash);
}
ModuleHashes hashes = new ModuleHashes(algorithm, map);
- return new HashesAttribute(hashes);
+ return new ModuleHashesAttribute(hashes);
}
@Override
@@ -633,11 +725,15 @@
Set<String> names = hashes.names();
attr.putShort(names.size());
- for (String dn : names) {
- String hash = hashes.hashFor(dn);
+ for (String mn : names) {
+ byte[] hash = hashes.hashFor(mn);
assert hash != null;
- attr.putShort(cw.newUTF8(dn));
- attr.putShort(cw.newUTF8(hash));
+ attr.putShort(cw.newUTF8(mn.replace('.', '/')));
+
+ attr.putShort(hash.length);
+ for (byte b: hash) {
+ attr.putByte(b);
+ }
}
return attr;