Search in sources :

Example 1 with InvalidModuleDescriptorException

use of java.lang.module.InvalidModuleDescriptorException in project Bytecoder by mirkosertic.

the class ModulePath method deriveModuleDescriptor.

/**
 * Treat the given JAR file as a module as follows:
 *
 * 1. The value of the Automatic-Module-Name attribute is the module name
 * 2. The version, and the module name when the  Automatic-Module-Name
 *    attribute is not present, is derived from the file ame of the JAR file
 * 3. All packages are derived from the .class files in the JAR file
 * 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 if possible
 */
private ModuleDescriptor deriveModuleDescriptor(JarFile jf) throws IOException {
    // Read Automatic-Module-Name attribute if present
    Manifest man = jf.getManifest();
    Attributes attrs = null;
    String moduleName = null;
    if (man != null) {
        attrs = man.getMainAttributes();
        if (attrs != null) {
            moduleName = attrs.getValue(AUTOMATIC_MODULE_NAME);
        }
    }
    // Derive the version, and the module name if needed, from JAR file name
    String fn = jf.getName();
    int i = fn.lastIndexOf(File.separator);
    if (i != -1)
        fn = fn.substring(i + 1);
    // drop ".jar"
    String name = fn.substring(0, fn.length() - 4);
    String vs = null;
    // find first occurrence of -${NUMBER}. or -${NUMBER}$
    Matcher matcher = Patterns.DASH_VERSION.matcher(name);
    if (matcher.find()) {
        int start = matcher.start();
        // attempt to parse the tail as a version string
        try {
            String tail = name.substring(start + 1);
            ModuleDescriptor.Version.parse(tail);
            vs = tail;
        } catch (IllegalArgumentException ignore) {
        }
        name = name.substring(0, start);
    }
    // Create builder, using the name derived from file name when
    // Automatic-Module-Name not present
    Builder builder;
    if (moduleName != null) {
        try {
            builder = ModuleDescriptor.newAutomaticModule(moduleName);
        } catch (IllegalArgumentException e) {
            throw new FindException(AUTOMATIC_MODULE_NAME + ": " + e.getMessage());
        }
    } else {
        builder = ModuleDescriptor.newAutomaticModule(cleanModuleName(name));
    }
    // module version if present
    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).collect(Collectors.toSet());
    // parse each service configuration file
    for (String sn : serviceNames) {
        JarEntry entry = jf.getJarEntry(SERVICES_PREFIX + sn);
        List<String> providerClasses = new ArrayList<>();
        try (InputStream in = jf.getInputStream(entry)) {
            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 InvalidModuleDescriptorException(msg);
                    }
                    providerClasses.add(cn);
                }
            }
        }
        if (!providerClasses.isEmpty())
            builder.provides(sn, providerClasses);
    }
    // Main-Class attribute if it exists
    if (attrs != null) {
        String mainClass = attrs.getValue(Attributes.Name.MAIN_CLASS);
        if (mainClass != null) {
            mainClass = mainClass.replace("/", ".");
            if (Checks.isClassName(mainClass)) {
                String pn = packageName(mainClass);
                if (packages.contains(pn)) {
                    builder.mainClass(mainClass);
                }
            }
        }
    }
    return builder.build();
}
Also used : Builder(java.lang.module.ModuleDescriptor.Builder) Manifest(java.util.jar.Manifest) NoSuchFileException(java.nio.file.NoSuchFileException) BufferedInputStream(java.io.BufferedInputStream) VersionedStream(jdk.internal.util.jar.VersionedStream) ModuleDescriptor(java.lang.module.ModuleDescriptor) ModuleReference(java.lang.module.ModuleReference) HashMap(java.util.HashMap) JarFile(java.util.jar.JarFile) ArrayList(java.util.ArrayList) Section(jdk.internal.jmod.JmodFile.Section) DirectoryStream(java.nio.file.DirectoryStream) JarEntry(java.util.jar.JarEntry) Matcher(java.util.regex.Matcher) ModuleFinder(java.lang.module.ModuleFinder) Map(java.util.Map) ZipFile(java.util.zip.ZipFile) URI(java.net.URI) Path(java.nio.file.Path) FindException(java.lang.module.FindException) PerfCounter(jdk.internal.perf.PerfCounter) ZipException(java.util.zip.ZipException) Files(java.nio.file.Files) Set(java.util.Set) IOException(java.io.IOException) BasicFileAttributes(java.nio.file.attribute.BasicFileAttributes) InputStreamReader(java.io.InputStreamReader) Attributes(java.util.jar.Attributes) Collectors(java.util.stream.Collectors) File(java.io.File) UncheckedIOException(java.io.UncheckedIOException) Objects(java.util.Objects) List(java.util.List) JmodFile(jdk.internal.jmod.JmodFile) Paths(java.nio.file.Paths) InvalidModuleDescriptorException(java.lang.module.InvalidModuleDescriptorException) Optional(java.util.Optional) BufferedReader(java.io.BufferedReader) Pattern(java.util.regex.Pattern) Collections(java.util.Collections) InputStream(java.io.InputStream) Set(java.util.Set) Optional(java.util.Optional) InputStreamReader(java.io.InputStreamReader) Matcher(java.util.regex.Matcher) BufferedInputStream(java.io.BufferedInputStream) InputStream(java.io.InputStream) Builder(java.lang.module.ModuleDescriptor.Builder) BasicFileAttributes(java.nio.file.attribute.BasicFileAttributes) Attributes(java.util.jar.Attributes) ArrayList(java.util.ArrayList) Manifest(java.util.jar.Manifest) JarEntry(java.util.jar.JarEntry) InvalidModuleDescriptorException(java.lang.module.InvalidModuleDescriptorException) FindException(java.lang.module.FindException) BufferedReader(java.io.BufferedReader)

Example 2 with InvalidModuleDescriptorException

use of java.lang.module.InvalidModuleDescriptorException in project Bytecoder by mirkosertic.

the class ModulePath method toPackageName.

/**
 * Maps the relative path of an entry in an exploded module to a package
 * name.
 *
 * @throws InvalidModuleDescriptorException if the name is a class file in
 *         the top-level directory (and it's not module-info.class)
 */
private Optional<String> toPackageName(Path file) {
    assert file.getRoot() == null;
    Path parent = file.getParent();
    if (parent == null) {
        String name = file.toString();
        if (name.endsWith(".class") && !name.equals(MODULE_INFO)) {
            String msg = name + " found in top-level directory" + " (unnamed package not allowed in module)";
            throw new InvalidModuleDescriptorException(msg);
        }
        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();
    }
}
Also used : Path(java.nio.file.Path) InvalidModuleDescriptorException(java.lang.module.InvalidModuleDescriptorException)

Example 3 with InvalidModuleDescriptorException

use of java.lang.module.InvalidModuleDescriptorException in project Bytecoder by mirkosertic.

the class ModulePath method readModule.

/**
 * 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 {
        // exploded module
        if (attrs.isDirectory()) {
            // may return null
            return readExplodedModule(entry);
        }
        // JAR or JMOD file
        if (attrs.isRegularFile()) {
            String fn = entry.getFileName().toString();
            boolean isDefaultFileSystem = isDefaultFileSystem(entry);
            // JAR file
            if (fn.endsWith(".jar")) {
                if (isDefaultFileSystem) {
                    return readJar(entry);
                } else {
                    // the JAR file is in a custom file system so
                    // need to copy it to the local file system
                    Path tmpdir = Files.createTempDirectory("mlib");
                    Path target = Files.copy(entry, tmpdir.resolve(fn));
                    return readJar(target);
                }
            }
            // JMOD file
            if (isDefaultFileSystem && isLinkPhase && fn.endsWith(".jmod")) {
                return readJMod(entry);
            }
        }
        return null;
    } catch (InvalidModuleDescriptorException e) {
        throw new FindException("Error reading module: " + entry, e);
    }
}
Also used : Path(java.nio.file.Path) FindException(java.lang.module.FindException) InvalidModuleDescriptorException(java.lang.module.InvalidModuleDescriptorException)

Aggregations

InvalidModuleDescriptorException (java.lang.module.InvalidModuleDescriptorException)3 Path (java.nio.file.Path)3 FindException (java.lang.module.FindException)2 BufferedInputStream (java.io.BufferedInputStream)1 BufferedReader (java.io.BufferedReader)1 File (java.io.File)1 IOException (java.io.IOException)1 InputStream (java.io.InputStream)1 InputStreamReader (java.io.InputStreamReader)1 UncheckedIOException (java.io.UncheckedIOException)1 ModuleDescriptor (java.lang.module.ModuleDescriptor)1 Builder (java.lang.module.ModuleDescriptor.Builder)1 ModuleFinder (java.lang.module.ModuleFinder)1 ModuleReference (java.lang.module.ModuleReference)1 URI (java.net.URI)1 DirectoryStream (java.nio.file.DirectoryStream)1 Files (java.nio.file.Files)1 NoSuchFileException (java.nio.file.NoSuchFileException)1 Paths (java.nio.file.Paths)1 BasicFileAttributes (java.nio.file.attribute.BasicFileAttributes)1