< prev index next >

src/java.base/share/classes/jdk/internal/module/ModulePath.java

Print this page

        

*** 1,7 **** /* ! * Copyright (c) 2014, 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 * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this --- 1,7 ---- /* ! * Copyright (c) 2014, 2017, 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 * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this
*** 193,217 **** try { if (attrs.isDirectory()) { Path mi = entry.resolve(MODULE_INFO); if (!Files.exists(mi)) { ! // does not exist or unable to determine so assume a ! // directory of modules return scanDirectory(entry); } } // packaged or exploded module ModuleReference mref = readModule(entry, attrs); if (mref != null) { String name = mref.descriptor().name(); return Collections.singletonMap(name, mref); } else { ! // skipped ! return Collections.emptyMap(); } } catch (IOException ioe) { throw new FindException(ioe); } } --- 193,222 ---- try { if (attrs.isDirectory()) { Path mi = entry.resolve(MODULE_INFO); if (!Files.exists(mi)) { ! // assume a directory of modules return scanDirectory(entry); } } // packaged or exploded module ModuleReference mref = readModule(entry, attrs); if (mref != null) { String name = mref.descriptor().name(); return Collections.singletonMap(name, mref); + } + + // not recognized + String msg; + if (!isLinkPhase && entry.toString().endsWith(".jmod")) { + msg = "JMOD format not supported at execution time"; } else { ! msg = "Module format not recognized"; } + throw new FindException(msg + ": " + entry); } catch (IOException ioe) { throw new FindException(ioe); } }
*** 264,307 **** return nameToReference; } /** ! * Locates a packaged or exploded module, returning a {@code ModuleReference} ! * to the module. Returns {@code null} if the entry is skipped because it is ! * to a directory that does not contain a module-info.class or it's a hidden ! * file. * * @throws IOException if an I/O error occurs ! * @throws FindException if the file is not recognized as a module or an ! * error occurs parsing its module descriptor */ private ModuleReference readModule(Path entry, BasicFileAttributes attrs) throws IOException { try { if (attrs.isDirectory()) { return readExplodedModule(entry); // may return null ! } ! String fn = entry.getFileName().toString(); if (attrs.isRegularFile()) { if (fn.endsWith(".jar")) { return readJar(entry); ! } else if (fn.endsWith(".jmod")) { ! if (isLinkPhase) return readJMod(entry); - throw new FindException("JMOD files not supported: " + entry); } } - - // skip hidden files - if (fn.startsWith(".") || Files.isHidden(entry)) { return null; - } else { - throw new FindException("Unrecognized module: " + entry); } } catch (InvalidModuleDescriptorException e) { throw new FindException("Error reading module: " + entry, e); } --- 269,301 ---- return nameToReference; } /** ! * Reads a packaged or exploded module, returning a {@code ModuleReference} ! * to the module. Returns {@code null} if the entry is not recognized. * * @throws IOException if an I/O error occurs ! * @throws FindException if an error occurs parsing its module descriptor */ private ModuleReference readModule(Path entry, BasicFileAttributes attrs) throws IOException { try { if (attrs.isDirectory()) { return readExplodedModule(entry); // may return null ! } else { String fn = entry.getFileName().toString(); if (attrs.isRegularFile()) { if (fn.endsWith(".jar")) { return readJar(entry); ! } else if (isLinkPhase && fn.endsWith(".jmod")) { return readJMod(entry); } } return null; } } catch (InvalidModuleDescriptorException e) { throw new FindException("Error reading module: " + entry, e); }
*** 360,370 **** private static final String SERVICES_PREFIX = "META-INF/services/"; /** * Returns the service type corresponding to the name of a services ! * configuration file if it is a valid Java identifier. * * For example, if called with "META-INF/services/p.S" then this method * returns a container with the value "p.S". */ private Optional<String> toServiceName(String cf) { --- 354,364 ---- private static final String SERVICES_PREFIX = "META-INF/services/"; /** * Returns the service type corresponding to the name of a services ! * configuration file if it is a legal type name. * * For example, if called with "META-INF/services/p.S" then this method * returns a container with the value "p.S". */ private Optional<String> toServiceName(String cf) {
*** 372,382 **** int index = cf.lastIndexOf("/") + 1; if (index < cf.length()) { String prefix = cf.substring(0, index); if (prefix.equals(SERVICES_PREFIX)) { String sn = cf.substring(index); ! if (Checks.isJavaIdentifier(sn)) return Optional.of(sn); } } return Optional.empty(); } --- 366,376 ---- int index = cf.lastIndexOf("/") + 1; if (index < cf.length()) { String prefix = cf.substring(0, index); if (prefix.equals(SERVICES_PREFIX)) { String sn = cf.substring(index); ! if (Checks.isClassName(sn)) return Optional.of(sn); } } return Optional.empty(); }
*** 401,415 **** /** * Treat the given JAR file as a module as follows: * * 1. The module name (and optionally the version) is derived from the file * name of the JAR file ! * 2. All packages are exported and open ! * 3. It has no non-exported/non-open packages ! * 4. The contents of any META-INF/services configuration files are mapped * to "provides" declarations ! * 5. The Main-Class attribute in the main attributes of the JAR manifest * is mapped to the module descriptor mainClass */ private ModuleDescriptor deriveModuleDescriptor(JarFile jf) throws IOException { --- 395,408 ---- /** * Treat the given JAR file as a module as follows: * * 1. The module name (and optionally the version) is derived from the file * name of the JAR file ! * 2. All packages are derived from the .class files in the JAR file ! * 3. The contents of any META-INF/services configuration files are mapped * to "provides" declarations ! * 4. The Main-Class attribute in the main attributes of the JAR manifest * is mapped to the module descriptor mainClass */ private ModuleDescriptor deriveModuleDescriptor(JarFile jf) throws IOException {
*** 441,471 **** // finally clean up the module name mn = cleanModuleName(mn); // Builder throws IAE if module name is empty or invalid ! ModuleDescriptor.Builder builder ! = ModuleDescriptor.automaticModule(mn) ! .requires(Set.of(Requires.Modifier.MANDATED), "java.base"); if (vs != null) builder.version(vs); // scan the names of the entries in the JAR file Map<Boolean, Set<String>> map = VersionedStream.stream(jf) .filter(e -> !e.isDirectory()) .map(JarEntry::getName) .collect(Collectors.partitioningBy(e -> e.startsWith(SERVICES_PREFIX), Collectors.toSet())); ! Set<String> resources = map.get(Boolean.FALSE); Set<String> configFiles = map.get(Boolean.TRUE); ! // all packages are exported and open ! resources.stream() .map(this::toPackageName) .flatMap(Optional::stream) .distinct() ! .forEach(pn -> builder.exports(pn).opens(pn)); // map names of service configuration files to service names Set<String> serviceNames = configFiles.stream() .map(this::toServiceName) .flatMap(Optional::stream) --- 434,467 ---- // finally clean up the module name mn = cleanModuleName(mn); // Builder throws IAE if module name is empty or invalid ! ModuleDescriptor.Builder builder = ModuleDescriptor.newAutomaticModule(mn); if (vs != null) builder.version(vs); // scan the names of the entries in the JAR file Map<Boolean, Set<String>> map = VersionedStream.stream(jf) .filter(e -> !e.isDirectory()) .map(JarEntry::getName) + .filter(e -> (e.endsWith(".class") ^ e.startsWith(SERVICES_PREFIX))) .collect(Collectors.partitioningBy(e -> e.startsWith(SERVICES_PREFIX), Collectors.toSet())); ! Set<String> classFiles = map.get(Boolean.FALSE); Set<String> configFiles = map.get(Boolean.TRUE); ! ! // the packages containing class files ! Set<String> packages = classFiles.stream() .map(this::toPackageName) .flatMap(Optional::stream) .distinct() ! .collect(Collectors.toSet()); ! ! // all packages are exported and open ! builder.packages(packages); // map names of service configuration files to service names Set<String> serviceNames = configFiles.stream() .map(this::toServiceName) .flatMap(Optional::stream)
*** 479,488 **** --- 475,489 ---- BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8")); String cn; while ((cn = nextLine(reader)) != null) { if (cn.length() > 0) { + String pn = packageName(cn); + if (!packages.contains(pn)) { + String msg = "Provider class " + cn + " not in module"; + throw new IOException(msg); + } providerClasses.add(cn); } } } if (!providerClasses.isEmpty())
*** 492,503 **** // Main-Class attribute if it exists Manifest man = jf.getManifest(); if (man != null) { Attributes attrs = man.getMainAttributes(); String mainClass = attrs.getValue(Attributes.Name.MAIN_CLASS); ! if (mainClass != null) ! builder.mainClass(mainClass.replace("/", ".")); } return builder.build(); } --- 493,511 ---- // Main-Class attribute if it exists Manifest man = jf.getManifest(); if (man != null) { Attributes attrs = man.getMainAttributes(); String mainClass = attrs.getValue(Attributes.Name.MAIN_CLASS); ! if (mainClass != null) { ! mainClass = mainClass.replace("/", "."); ! String pn = packageName(mainClass); ! if (!packages.contains(pn)) { ! String msg = "Main-Class " + mainClass + " not in module"; ! throw new IOException(msg); ! } ! builder.mainClass(mainClass); ! } } return builder.build(); }
*** 567,580 **** // no module-info.class so treat it as automatic module try { ModuleDescriptor md = deriveModuleDescriptor(jf); attrs = new ModuleInfo.Attributes(md, null, null); ! } catch (IllegalArgumentException iae) { throw new FindException( "Unable to derive module descriptor for: " ! + jf.getName(), iae); } } else { attrs = ModuleInfo.read(jf.getInputStream(entry), () -> jarPackages(jf)); --- 575,588 ---- // no module-info.class so treat it as automatic module try { ModuleDescriptor md = deriveModuleDescriptor(jf); attrs = new ModuleInfo.Attributes(md, null, null); ! } catch (IllegalArgumentException e) { throw new FindException( "Unable to derive module descriptor for: " ! + jf.getName(), e); } } else { attrs = ModuleInfo.read(jf.getInputStream(entry), () -> jarPackages(jf));
*** 619,649 **** } return ModuleReferences.newExplodedModule(attrs, dir); } /** * Maps the name of an entry in a JAR or ZIP file to a package name. * * @throws IllegalArgumentException if the name is a class file in * the top-level directory of the JAR/ZIP file (and it's * not module-info.class) */ private Optional<String> toPackageName(String name) { assert !name.endsWith("/"); - int index = name.lastIndexOf("/"); if (index == -1) { if (name.endsWith(".class") && !name.equals(MODULE_INFO)) { throw new IllegalArgumentException(name ! + " found in top-level directory:" + " (unnamed package not allowed in module)"); } return Optional.empty(); } String pn = name.substring(0, index).replace('/', '.'); ! if (Checks.isJavaIdentifier(pn)) { return Optional.of(pn); } else { // not a valid package name return Optional.empty(); } --- 627,664 ---- } return ModuleReferences.newExplodedModule(attrs, dir); } /** + * Maps a type name to its package name. + */ + private static String packageName(String cn) { + int index = cn.lastIndexOf('.'); + return (index == -1) ? "" : cn.substring(0, index); + } + + /** * Maps the name of an entry in a JAR or ZIP file to a package name. * * @throws IllegalArgumentException if the name is a class file in * the top-level directory of the JAR/ZIP file (and it's * not module-info.class) */ private Optional<String> toPackageName(String name) { assert !name.endsWith("/"); int index = name.lastIndexOf("/"); if (index == -1) { if (name.endsWith(".class") && !name.equals(MODULE_INFO)) { throw new IllegalArgumentException(name ! + " found in top-level directory" + " (unnamed package not allowed in module)"); } return Optional.empty(); } String pn = name.substring(0, index).replace('/', '.'); ! if (Checks.isPackageName(pn)) { return Optional.of(pn); } else { // not a valid package name return Optional.empty(); }
*** 662,679 **** Path parent = file.getParent(); if (parent == null) { String name = file.toString(); if (name.endsWith(".class") && !name.equals(MODULE_INFO)) { throw new IllegalArgumentException(name ! + " found in in top-level directory" + " (unnamed package not allowed in module)"); } return Optional.empty(); } String pn = parent.toString().replace(File.separatorChar, '.'); ! if (Checks.isJavaIdentifier(pn)) { return Optional.of(pn); } else { // not a valid package name return Optional.empty(); } --- 677,694 ---- Path parent = file.getParent(); if (parent == null) { String name = file.toString(); if (name.endsWith(".class") && !name.equals(MODULE_INFO)) { throw new IllegalArgumentException(name ! + " found in top-level directory" + " (unnamed package not allowed in module)"); } return Optional.empty(); } String pn = parent.toString().replace(File.separatorChar, '.'); ! if (Checks.isPackageName(pn)) { return Optional.of(pn); } else { // not a valid package name return Optional.empty(); }
< prev index next >