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