< prev index next >
src/java.base/share/classes/jdk/internal/module/ModuleInfo.java
Print this page
*** 21,42 ****
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
! package java.lang.module;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.lang.module.ModuleDescriptor.Builder;
import java.lang.module.ModuleDescriptor.Requires;
import java.lang.module.ModuleDescriptor.Exports;
import java.lang.module.ModuleDescriptor.Opens;
import java.nio.ByteBuffer;
import java.nio.BufferUnderflowException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
--- 21,45 ----
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
! package jdk.internal.module;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
+ import java.lang.module.InvalidModuleDescriptorException;
+ import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleDescriptor.Builder;
import java.lang.module.ModuleDescriptor.Requires;
import java.lang.module.ModuleDescriptor.Exports;
import java.lang.module.ModuleDescriptor.Opens;
+ import java.lang.module.ModuleDescriptor.Version;
import java.nio.ByteBuffer;
import java.nio.BufferUnderflowException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
*** 44,54 ****
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;
! import jdk.internal.module.ModuleHashes;
import static jdk.internal.module.ClassFileConstants.*;
/**
--- 47,59 ----
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;
! import jdk.internal.misc.JavaLangModuleAccess;
! import jdk.internal.misc.SharedSecrets;
! import jdk.internal.module.ModuleResolution;
import static jdk.internal.module.ClassFileConstants.*;
/**
*** 56,66 ****
*
* @implNote The rationale for the hand-coded reader is startup performance
* and fine control over the throwing of InvalidModuleDescriptorException.
*/
! final class ModuleInfo {
// supplies the set of packages when ModulePackages attribute not present
private final Supplier<Set<String>> packageFinder;
// indicates if the ModuleHashes attribute should be parsed
--- 61,74 ----
*
* @implNote The rationale for the hand-coded reader is startup performance
* and fine control over the throwing of InvalidModuleDescriptorException.
*/
! public final class ModuleInfo {
!
! private static final JavaLangModuleAccess JLMA
! = SharedSecrets.getJavaLangModuleAccess();
// supplies the set of packages when ModulePackages attribute not present
private final Supplier<Set<String>> packageFinder;
// indicates if the ModuleHashes attribute should be parsed
*** 74,90 ****
private ModuleInfo(Supplier<Set<String>> pf) {
this(pf, true);
}
/**
* Reads a {@code module-info.class} from the given input stream.
*
* @throws InvalidModuleDescriptorException
* @throws IOException
*/
! public static ModuleDescriptor read(InputStream in,
! Supplier<Set<String>> pf)
throws IOException
{
try {
return new ModuleInfo(pf).doRead(new DataInputStream(in));
} catch (IllegalArgumentException | IllegalStateException e) {
--- 82,126 ----
private ModuleInfo(Supplier<Set<String>> pf) {
this(pf, true);
}
/**
+ * A holder class for the ModuleDescriptor that is created by reading the
+ * Module and other standard class file attributes. It also holds the objects
+ * that represent the non-standard class file attributes that are read from
+ * the class file.
+ */
+ public static final class Attributes {
+ private final ModuleDescriptor descriptor;
+ private final ModuleHashes recordedHashes;
+ private final ModuleResolution moduleResolution;
+ Attributes(ModuleDescriptor descriptor,
+ ModuleHashes recordedHashes,
+ ModuleResolution moduleResolution) {
+ this.descriptor = descriptor;
+ this.recordedHashes = recordedHashes;
+ this.moduleResolution = moduleResolution;
+ }
+ public ModuleDescriptor descriptor() {
+ return descriptor;
+ }
+ public ModuleHashes recordedHashes() {
+ return recordedHashes;
+ }
+ public ModuleResolution moduleResolution() {
+ return moduleResolution;
+ }
+ }
+
+
+ /**
* Reads a {@code module-info.class} from the given input stream.
*
* @throws InvalidModuleDescriptorException
* @throws IOException
*/
! public static Attributes read(InputStream in, Supplier<Set<String>> pf)
throws IOException
{
try {
return new ModuleInfo(pf).doRead(new DataInputStream(in));
} catch (IllegalArgumentException | IllegalStateException e) {
*** 98,110 ****
* Reads a {@code module-info.class} from the given byte buffer.
*
* @throws InvalidModuleDescriptorException
* @throws UncheckedIOException
*/
! public static ModuleDescriptor read(ByteBuffer bb,
! Supplier<Set<String>> pf)
! {
try {
return new ModuleInfo(pf).doRead(new DataInputWrapper(bb));
} catch (IllegalArgumentException | IllegalStateException e) {
throw invalidModuleDescriptor(e.getMessage());
} catch (EOFException x) {
--- 134,144 ----
* Reads a {@code module-info.class} from the given byte buffer.
*
* @throws InvalidModuleDescriptorException
* @throws UncheckedIOException
*/
! public static Attributes read(ByteBuffer bb, Supplier<Set<String>> pf) {
try {
return new ModuleInfo(pf).doRead(new DataInputWrapper(bb));
} catch (IllegalArgumentException | IllegalStateException e) {
throw invalidModuleDescriptor(e.getMessage());
} catch (EOFException x) {
*** 119,131 ****
* but ignore the {@code ModuleHashes} attribute.
*
* @throws InvalidModuleDescriptorException
* @throws UncheckedIOException
*/
! static ModuleDescriptor readIgnoringHashes(ByteBuffer bb,
! Supplier<Set<String>> pf)
! {
try {
return new ModuleInfo(pf, false).doRead(new DataInputWrapper(bb));
} catch (IllegalArgumentException | IllegalStateException e) {
throw invalidModuleDescriptor(e.getMessage());
} catch (EOFException x) {
--- 153,163 ----
* but ignore the {@code ModuleHashes} attribute.
*
* @throws InvalidModuleDescriptorException
* @throws UncheckedIOException
*/
! public static Attributes readIgnoringHashes(ByteBuffer bb, Supplier<Set<String>> pf) {
try {
return new ModuleInfo(pf, false).doRead(new DataInputWrapper(bb));
} catch (IllegalArgumentException | IllegalStateException e) {
throw invalidModuleDescriptor(e.getMessage());
} catch (EOFException x) {
*** 142,152 ****
* @throws InvalidModuleDescriptorException
* @throws IllegalArgumentException if thrown by the ModuleDescriptor.Builder
* because an identifier is not a legal Java identifier, duplicate
* exports, and many other reasons
*/
! private ModuleDescriptor doRead(DataInput in) throws IOException {
int magic = in.readInt();
if (magic != 0xCAFEBABE)
throw invalidModuleDescriptor("Bad magic number");
--- 174,184 ----
* @throws InvalidModuleDescriptorException
* @throws IllegalArgumentException if thrown by the ModuleDescriptor.Builder
* because an identifier is not a legal Java identifier, duplicate
* exports, and many other reasons
*/
! private Attributes doRead(DataInput in) throws IOException {
int magic = in.readInt();
if (magic != 0xCAFEBABE)
throw invalidModuleDescriptor("Bad magic number");
*** 161,172 ****
int access_flags = in.readUnsignedShort();
if (access_flags != ACC_MODULE)
throw invalidModuleDescriptor("access_flags should be ACC_MODULE");
int this_class = in.readUnsignedShort();
! if (this_class != 0)
! throw invalidModuleDescriptor("this_class must be 0");
int super_class = in.readUnsignedShort();
if (super_class > 0)
throw invalidModuleDescriptor("bad #super_class");
--- 193,205 ----
int access_flags = in.readUnsignedShort();
if (access_flags != ACC_MODULE)
throw invalidModuleDescriptor("access_flags should be ACC_MODULE");
int this_class = in.readUnsignedShort();
! String mn = cpool.getClassName(this_class);
! if (!"module-info".equals(mn))
! throw invalidModuleDescriptor("this_class should be module-info");
int super_class = in.readUnsignedShort();
if (super_class > 0)
throw invalidModuleDescriptor("bad #super_class");
*** 187,200 ****
// the names of the attributes found in the class file
Set<String> attributes = new HashSet<>();
Builder builder = null;
Set<String> packages = null;
- String version = null;
String mainClass = null;
String[] osValues = null;
ModuleHashes hashes = null;
for (int i = 0; i < attributes_count ; i++) {
int name_index = in.readUnsignedShort();
String attribute_name = cpool.getUtf8(name_index);
int length = in.readInt();
--- 220,233 ----
// the names of the attributes found in the class file
Set<String> attributes = new HashSet<>();
Builder builder = null;
Set<String> packages = null;
String mainClass = null;
String[] osValues = null;
ModuleHashes hashes = null;
+ ModuleResolution moduleResolution = null;
for (int i = 0; i < attributes_count ; i++) {
int name_index = in.readUnsignedShort();
String attribute_name = cpool.getUtf8(name_index);
int length = in.readInt();
*** 213,226 ****
case MODULE_PACKAGES :
packages = readModulePackagesAttribute(in, cpool);
break;
- case MODULE_VERSION :
- version = readModuleVersionAttribute(in, cpool);
- break;
-
case MODULE_MAIN_CLASS :
mainClass = readModuleMainClassAttribute(in, cpool);
break;
case MODULE_TARGET :
--- 246,255 ----
*** 233,242 ****
--- 262,275 ----
} else {
in.skipBytes(length);
}
break;
+ case MODULE_RESOLUTION :
+ moduleResolution = readModuleResolution(in, cpool);
+ break;
+
default:
if (isAttributeDisallowed(attribute_name)) {
throw invalidModuleDescriptor(attribute_name
+ " attribute not allowed");
} else {
*** 261,298 ****
throw x.getCause();
}
usedPackageFinder = true;
}
if (packages != null) {
! for (String pn : builder.exportedAndOpenPackages()) {
if (!packages.contains(pn)) {
String tail;
if (usedPackageFinder) {
tail = " not found by package finder";
} else {
tail = " missing from ModulePackages attribute";
}
throw invalidModuleDescriptor("Package " + pn + tail);
}
! packages.remove(pn);
}
builder.contains(packages);
}
- if (version != null)
- builder.version(version);
if (mainClass != null)
builder.mainClass(mainClass);
if (osValues != null) {
if (osValues[0] != null) builder.osName(osValues[0]);
if (osValues[1] != null) builder.osArch(osValues[1]);
if (osValues[2] != null) builder.osVersion(osValues[2]);
}
- if (hashes != null)
- builder.hashes(hashes);
! return builder.build();
}
/**
* Reads the Module attribute, returning the ModuleDescriptor.Builder to
* build the corresponding ModuleDescriptor.
--- 294,340 ----
throw x.getCause();
}
usedPackageFinder = true;
}
if (packages != null) {
! Set<String> exportedPackages = JLMA.exportedPackages(builder);
! Set<String> openPackages = JLMA.openPackages(builder);
! if (packages.containsAll(exportedPackages)
! && packages.containsAll(openPackages)) {
! packages.removeAll(exportedPackages);
! packages.removeAll(openPackages);
! } else {
! // the set of packages is not complete
! Set<String> exportedAndOpenPackages = new HashSet<>();
! exportedAndOpenPackages.addAll(exportedPackages);
! exportedAndOpenPackages.addAll(openPackages);
! for (String pn : exportedAndOpenPackages) {
if (!packages.contains(pn)) {
String tail;
if (usedPackageFinder) {
tail = " not found by package finder";
} else {
tail = " missing from ModulePackages attribute";
}
throw invalidModuleDescriptor("Package " + pn + tail);
}
! }
! assert false; // should not get here
}
builder.contains(packages);
}
if (mainClass != null)
builder.mainClass(mainClass);
if (osValues != null) {
if (osValues[0] != null) builder.osName(osValues[0]);
if (osValues[1] != null) builder.osArch(osValues[1]);
if (osValues[2] != null) builder.osVersion(osValues[2]);
}
! ModuleDescriptor descriptor = builder.build();
! return new Attributes(descriptor, hashes, moduleResolution);
}
/**
* Reads the Module attribute, returning the ModuleDescriptor.Builder to
* build the corresponding ModuleDescriptor.
*** 300,341 ****
private Builder readModuleAttribute(DataInput in, ConstantPool cpool)
throws IOException
{
// module_name
int module_name_index = in.readUnsignedShort();
! String mn = cpool.getUtf8AsBinaryName(module_name_index);
!
! Builder builder = new ModuleDescriptor.Builder(mn, /*strict*/ false);
int module_flags = in.readUnsignedShort();
boolean open = ((module_flags & ACC_OPEN) != 0);
! if (open)
! builder.open(true);
! if ((module_flags & ACC_SYNTHETIC) != 0)
! builder.synthetic(true);
int requires_count = in.readUnsignedShort();
boolean requiresJavaBase = false;
for (int i=0; i<requires_count; i++) {
! int index = in.readUnsignedShort();
! int flags = in.readUnsignedShort();
! String dn = cpool.getUtf8AsBinaryName(index);
Set<Requires.Modifier> mods;
! if (flags == 0) {
mods = Collections.emptySet();
} else {
mods = new HashSet<>();
! 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(Requires.Modifier.SYNTHETIC);
! if ((flags & ACC_MANDATED) != 0)
mods.add(Requires.Modifier.MANDATED);
}
builder.requires(mods, dn);
if (dn.equals("java.base"))
requiresJavaBase = true;
}
if (mn.equals("java.base")) {
if (requires_count > 0) {
--- 342,400 ----
private Builder readModuleAttribute(DataInput in, ConstantPool cpool)
throws IOException
{
// module_name
int module_name_index = in.readUnsignedShort();
! String mn = cpool.getModuleName(module_name_index);
int module_flags = in.readUnsignedShort();
boolean open = ((module_flags & ACC_OPEN) != 0);
! boolean synthetic = ((module_flags & ACC_SYNTHETIC) != 0);
!
! Builder builder = JLMA.newModuleBuilder(mn, false, open, synthetic);
!
! int module_version_index = in.readUnsignedShort();
! if (module_version_index != 0) {
! String vs = cpool.getUtf8(module_version_index);
! builder.version(vs);
! }
int requires_count = in.readUnsignedShort();
boolean requiresJavaBase = false;
for (int i=0; i<requires_count; i++) {
! int requires_index = in.readUnsignedShort();
! String dn = cpool.getModuleName(requires_index);
!
! int requires_flags = in.readUnsignedShort();
Set<Requires.Modifier> mods;
! if (requires_flags == 0) {
mods = Collections.emptySet();
} else {
mods = new HashSet<>();
! if ((requires_flags & ACC_TRANSITIVE) != 0)
mods.add(Requires.Modifier.TRANSITIVE);
! if ((requires_flags & ACC_STATIC_PHASE) != 0)
mods.add(Requires.Modifier.STATIC);
! if ((requires_flags & ACC_SYNTHETIC) != 0)
mods.add(Requires.Modifier.SYNTHETIC);
! if ((requires_flags & ACC_MANDATED) != 0)
mods.add(Requires.Modifier.MANDATED);
}
+
+ int requires_version_index = in.readUnsignedShort();
+ Version compiledVersion = null;
+ if (requires_version_index != 0) {
+ String vs = cpool.getUtf8(requires_version_index);
+ compiledVersion = Version.parse(vs);
+ }
+
+ if (compiledVersion == null) {
builder.requires(mods, dn);
+ } else {
+ builder.requires(mods, dn, compiledVersion);
+ }
+
if (dn.equals("java.base"))
requiresJavaBase = true;
}
if (mn.equals("java.base")) {
if (requires_count > 0) {
*** 348,378 ****
}
int exports_count = in.readUnsignedShort();
if (exports_count > 0) {
for (int i=0; i<exports_count; i++) {
! int index = in.readUnsignedShort();
! String pkg = cpool.getUtf8AsBinaryName(index);
Set<Exports.Modifier> mods;
! int flags = in.readUnsignedShort();
! 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 = in.readUnsignedShort();
if (exports_to_count > 0) {
Set<String> targets = new HashSet<>(exports_to_count);
for (int j=0; j<exports_to_count; j++) {
int exports_to_index = in.readUnsignedShort();
! targets.add(cpool.getUtf8AsBinaryName(exports_to_index));
}
builder.exports(mods, pkg, targets);
} else {
builder.exports(mods, pkg);
}
--- 407,437 ----
}
int exports_count = in.readUnsignedShort();
if (exports_count > 0) {
for (int i=0; i<exports_count; i++) {
! int exports_index = in.readUnsignedShort();
! String pkg = cpool.getPackageName(exports_index);
Set<Exports.Modifier> mods;
! int exports_flags = in.readUnsignedShort();
! if (exports_flags == 0) {
mods = Collections.emptySet();
} else {
mods = new HashSet<>();
! if ((exports_flags & ACC_SYNTHETIC) != 0)
mods.add(Exports.Modifier.SYNTHETIC);
! if ((exports_flags & ACC_MANDATED) != 0)
mods.add(Exports.Modifier.MANDATED);
}
int exports_to_count = in.readUnsignedShort();
if (exports_to_count > 0) {
Set<String> targets = new HashSet<>(exports_to_count);
for (int j=0; j<exports_to_count; j++) {
int exports_to_index = in.readUnsignedShort();
! targets.add(cpool.getModuleName(exports_to_index));
}
builder.exports(mods, pkg, targets);
} else {
builder.exports(mods, pkg);
}
*** 384,414 ****
if (open) {
throw invalidModuleDescriptor("The opens table for an open"
+ " module must be 0 length");
}
for (int i=0; i<opens_count; i++) {
! int index = in.readUnsignedShort();
! String pkg = cpool.getUtf8AsBinaryName(index);
Set<Opens.Modifier> mods;
! int flags = in.readUnsignedShort();
! 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 open_to_count = in.readUnsignedShort();
if (open_to_count > 0) {
Set<String> targets = new HashSet<>(open_to_count);
for (int j=0; j<open_to_count; j++) {
int opens_to_index = in.readUnsignedShort();
! targets.add(cpool.getUtf8AsBinaryName(opens_to_index));
}
builder.opens(mods, pkg, targets);
} else {
builder.opens(mods, pkg);
}
--- 443,473 ----
if (open) {
throw invalidModuleDescriptor("The opens table for an open"
+ " module must be 0 length");
}
for (int i=0; i<opens_count; i++) {
! int opens_index = in.readUnsignedShort();
! String pkg = cpool.getPackageName(opens_index);
Set<Opens.Modifier> mods;
! int opens_flags = in.readUnsignedShort();
! if (opens_flags == 0) {
mods = Collections.emptySet();
} else {
mods = new HashSet<>();
! if ((opens_flags & ACC_SYNTHETIC) != 0)
mods.add(Opens.Modifier.SYNTHETIC);
! if ((opens_flags & ACC_MANDATED) != 0)
mods.add(Opens.Modifier.MANDATED);
}
int open_to_count = in.readUnsignedShort();
if (open_to_count > 0) {
Set<String> targets = new HashSet<>(open_to_count);
for (int j=0; j<open_to_count; j++) {
int opens_to_index = in.readUnsignedShort();
! targets.add(cpool.getModuleName(opens_to_index));
}
builder.opens(mods, pkg, targets);
} else {
builder.opens(mods, pkg);
}
*** 417,441 ****
int uses_count = in.readUnsignedShort();
if (uses_count > 0) {
for (int i=0; i<uses_count; i++) {
int index = in.readUnsignedShort();
! String sn = cpool.getClassNameAsBinaryName(index);
builder.uses(sn);
}
}
int provides_count = in.readUnsignedShort();
if (provides_count > 0) {
for (int i=0; i<provides_count; i++) {
int index = in.readUnsignedShort();
! String sn = cpool.getClassNameAsBinaryName(index);
int with_count = in.readUnsignedShort();
List<String> providers = new ArrayList<>(with_count);
for (int j=0; j<with_count; j++) {
index = in.readUnsignedShort();
! String pn = cpool.getClassNameAsBinaryName(index);
providers.add(pn);
}
builder.provides(sn, providers);
}
}
--- 476,500 ----
int uses_count = in.readUnsignedShort();
if (uses_count > 0) {
for (int i=0; i<uses_count; i++) {
int index = in.readUnsignedShort();
! String sn = cpool.getClassName(index);
builder.uses(sn);
}
}
int provides_count = in.readUnsignedShort();
if (provides_count > 0) {
for (int i=0; i<provides_count; i++) {
int index = in.readUnsignedShort();
! String sn = cpool.getClassName(index);
int with_count = in.readUnsignedShort();
List<String> providers = new ArrayList<>(with_count);
for (int j=0; j<with_count; j++) {
index = in.readUnsignedShort();
! String pn = cpool.getClassName(index);
providers.add(pn);
}
builder.provides(sn, providers);
}
}
*** 451,484 ****
{
int package_count = in.readUnsignedShort();
Set<String> packages = new HashSet<>(package_count);
for (int i=0; i<package_count; i++) {
int index = in.readUnsignedShort();
! String pn = cpool.getUtf8AsBinaryName(index);
! packages.add(pn);
}
- return packages;
}
!
! /**
! * Reads the ModuleVersion attribute
! */
! private String readModuleVersionAttribute(DataInput in, ConstantPool cpool)
! throws IOException
! {
! int index = in.readUnsignedShort();
! return cpool.getUtf8(index);
}
/**
* Reads the ModuleMainClass attribute
*/
private String readModuleMainClassAttribute(DataInput in, ConstantPool cpool)
throws IOException
{
int index = in.readUnsignedShort();
! return cpool.getClassNameAsBinaryName(index);
}
/**
* Reads the ModuleTarget attribute
*/
--- 510,537 ----
{
int package_count = in.readUnsignedShort();
Set<String> packages = new HashSet<>(package_count);
for (int i=0; i<package_count; i++) {
int index = in.readUnsignedShort();
! String pn = cpool.getPackageName(index);
! boolean added = packages.add(pn);
! if (!added) {
! throw invalidModuleDescriptor("Package " + pn + " in ModulePackages"
! + "attribute more than once");
}
}
! return packages;
}
/**
* Reads the ModuleMainClass attribute
*/
private String readModuleMainClassAttribute(DataInput in, ConstantPool cpool)
throws IOException
{
int index = in.readUnsignedShort();
! return cpool.getClassName(index);
}
/**
* Reads the ModuleTarget attribute
*/
*** 514,524 ****
int hash_count = in.readUnsignedShort();
Map<String, byte[]> map = new HashMap<>(hash_count);
for (int i=0; i<hash_count; i++) {
int module_name_index = in.readUnsignedShort();
! String mn = cpool.getUtf8AsBinaryName(module_name_index);
int hash_length = in.readUnsignedShort();
if (hash_length == 0) {
throw invalidModuleDescriptor("hash_length == 0");
}
byte[] hash = new byte[hash_length];
--- 567,577 ----
int hash_count = in.readUnsignedShort();
Map<String, byte[]> map = new HashMap<>(hash_count);
for (int i=0; i<hash_count; i++) {
int module_name_index = in.readUnsignedShort();
! String mn = cpool.getModuleName(module_name_index);
int hash_length = in.readUnsignedShort();
if (hash_length == 0) {
throw invalidModuleDescriptor("hash_length == 0");
}
byte[] hash = new byte[hash_length];
*** 527,536 ****
--- 580,614 ----
}
return new ModuleHashes(algorithm, map);
}
+ /**
+ * Reads the ModuleResolution attribute.
+ */
+ private ModuleResolution readModuleResolution(DataInput in,
+ ConstantPool cpool)
+ throws IOException
+ {
+ int flags = in.readUnsignedShort();
+
+ int reason = 0;
+ if ((flags & WARN_DEPRECATED) != 0)
+ reason = WARN_DEPRECATED;
+ if ((flags & WARN_DEPRECATED_FOR_REMOVAL) != 0) {
+ if (reason != 0)
+ throw invalidModuleDescriptor("Bad module resolution flags:" + flags);
+ reason = WARN_DEPRECATED_FOR_REMOVAL;
+ }
+ if ((flags & WARN_INCUBATING) != 0) {
+ if (reason != 0)
+ throw invalidModuleDescriptor("Bad module resolution flags:" + flags);
+ }
+
+ return new ModuleResolution(flags);
+ }
+
/**
* Returns true if the given attribute can be present at most once
* in the class file. Returns false otherwise.
*/
*** 538,551 ****
if (name.equals(MODULE) ||
name.equals(SOURCE_FILE) ||
name.equals(SDE) ||
name.equals(MODULE_PACKAGES) ||
- name.equals(MODULE_VERSION) ||
name.equals(MODULE_MAIN_CLASS) ||
name.equals(MODULE_TARGET) ||
! name.equals(MODULE_HASHES))
return true;
return false;
}
--- 616,629 ----
if (name.equals(MODULE) ||
name.equals(SOURCE_FILE) ||
name.equals(SDE) ||
name.equals(MODULE_PACKAGES) ||
name.equals(MODULE_MAIN_CLASS) ||
name.equals(MODULE_TARGET) ||
! name.equals(MODULE_HASHES) ||
! name.equals(MODULE_RESOLUTION))
return true;
return false;
}
*** 602,611 ****
--- 680,691 ----
static final int CONSTANT_InterfaceMethodref = 11;
static final int CONSTANT_NameAndType = 12;
static final int CONSTANT_MethodHandle = 15;
static final int CONSTANT_MethodType = 16;
static final int CONSTANT_InvokeDynamic = 18;
+ static final int CONSTANT_Module = 19;
+ static final int CONSTANT_Package = 20;
private static class Entry {
protected Entry(int tag) {
this.tag = tag;
}
*** 651,660 ****
--- 731,742 ----
String svalue = in.readUTF();
pool[i] = new ValueEntry(tag, svalue);
break;
case CONSTANT_Class:
+ case CONSTANT_Package:
+ case CONSTANT_Module:
case CONSTANT_String:
int index = in.readUnsignedShort();
pool[i] = new IndexEntry(tag, index);
break;
*** 713,749 ****
Entry e = pool[index];
if (e.tag != CONSTANT_Class) {
throw invalidModuleDescriptor("CONSTANT_Class expected at entry: "
+ index);
}
! return getUtf8(((IndexEntry) e).index);
}
! String getClassNameAsBinaryName(int index) {
! String value = getClassName(index);
return value.replace('/', '.'); // internal form -> binary name
}
String getUtf8(int index) {
checkIndex(index);
Entry e = pool[index];
if (e.tag != CONSTANT_Utf8) {
throw invalidModuleDescriptor("CONSTANT_Utf8 expected at entry: "
+ index);
}
return (String) (((ValueEntry) e).value);
}
- String getUtf8AsBinaryName(int index) {
- String value = getUtf8(index);
- return value.replace('/', '.'); // internal -> binary name
- }
-
void checkIndex(int index) {
if (index < 1 || index >= pool.length)
throw invalidModuleDescriptor("Index into constant pool out of range");
}
}
/**
* A DataInput implementation that reads from a ByteBuffer.
*/
--- 795,939 ----
Entry e = pool[index];
if (e.tag != CONSTANT_Class) {
throw invalidModuleDescriptor("CONSTANT_Class expected at entry: "
+ index);
}
! String value = getUtf8(((IndexEntry) e).index);
! checkUnqualifiedName("CONSTANT_Class", index, value);
! return value.replace('/', '.'); // internal form -> binary name
}
! String getPackageName(int index) {
! checkIndex(index);
! Entry e = pool[index];
! if (e.tag != CONSTANT_Package) {
! throw invalidModuleDescriptor("CONSTANT_Package expected at entry: "
! + index);
! }
! String value = getUtf8(((IndexEntry) e).index);
! checkUnqualifiedName("CONSTANT_Package", index, value);
return value.replace('/', '.'); // internal form -> binary name
}
+ String getModuleName(int index) {
+ checkIndex(index);
+ Entry e = pool[index];
+ if (e.tag != CONSTANT_Module) {
+ throw invalidModuleDescriptor("CONSTANT_Module expected at entry: "
+ + index);
+ }
+ String value = getUtf8(((IndexEntry) e).index);
+ return decodeModuleName(index, value);
+ }
+
String getUtf8(int index) {
checkIndex(index);
Entry e = pool[index];
if (e.tag != CONSTANT_Utf8) {
throw invalidModuleDescriptor("CONSTANT_Utf8 expected at entry: "
+ index);
}
return (String) (((ValueEntry) e).value);
}
void checkIndex(int index) {
if (index < 1 || index >= pool.length)
throw invalidModuleDescriptor("Index into constant pool out of range");
}
+
+ void checkUnqualifiedName(String what, int index, String value) {
+ int len = value.length();
+ if (len == 0) {
+ throw invalidModuleDescriptor(what + " at entry " + index
+ + " has zero length");
+ }
+ for (int i=0; i<len; i++) {
+ char c = value.charAt(i);
+ if (c == '.' || c == ';' || c == '[') {
+ throw invalidModuleDescriptor(what + " at entry " + index
+ + " has illegal character: '"
+ + c + "'");
+ }
+ }
+ }
+
+ /**
+ * "Decode" a module name that has been read from the constant pool.
+ */
+ String decodeModuleName(int index, String value) {
+ int len = value.length();
+ if (len == 0) {
+ throw invalidModuleDescriptor("CONSTANT_Module at entry "
+ + index + " is zero length");
+ }
+ int i = 0;
+ while (i < len) {
+ int cp = value.codePointAt(i);
+ if (cp == ':' || cp == '@' || cp < 0x20) {
+ throw invalidModuleDescriptor("CONSTANT_Module at entry "
+ + index + " has illegal character: "
+ + Character.getName(cp));
+ }
+
+ // blackslash is the escape character
+ if (cp == '\\')
+ return decodeModuleName(index, i, value);
+
+ i += Character.charCount(cp);
+ }
+ return value;
+ }
+
+ /**
+ * "Decode" a module name that has been read from the constant pool and
+ * partly checked for illegal characters (up to position {@code i}).
+ */
+ String decodeModuleName(int index, int i, String value) {
+ StringBuilder sb = new StringBuilder();
+
+ // copy the code points that have been checked
+ int j = 0;
+ while (j < i) {
+ int cp = value.codePointAt(j);
+ sb.appendCodePoint(cp);
+ j += Character.charCount(cp);
+ }
+
+ // decode from position {@code i} to end
+ int len = value.length();
+ while (i < len) {
+ int cp = value.codePointAt(i);
+ if (cp == ':' || cp == '@' || cp < 0x20) {
+ throw invalidModuleDescriptor("CONSTANT_Module at entry "
+ + index + " has illegal character: "
+ + Character.getName(cp));
+ }
+
+ // blackslash is the escape character
+ if (cp == '\\') {
+ j = i + Character.charCount(cp);
+ if (j >= len) {
+ throw invalidModuleDescriptor("CONSTANT_Module at entry "
+ + index + " has illegal "
+ + "escape sequence");
+ }
+ int next = value.codePointAt(j);
+ if (next != '\\' && next != ':' && next != '@') {
+ throw invalidModuleDescriptor("CONSTANT_Module at entry "
+ + index + " has illegal "
+ + "escape sequence");
+ }
+ sb.appendCodePoint(next);
+ i += Character.charCount(next);
+ } else {
+ sb.appendCodePoint(cp);
+ }
+
+ i += Character.charCount(cp);
+ }
+ return sb.toString();
+ }
}
/**
* A DataInput implementation that reads from a ByteBuffer.
*/
< prev index next >