Search in sources :

Example 1 with FindException

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

the class ModulePath method scan.

/**
 * Scan the given module path entry. If the entry is a directory then it is
 * a directory of modules or an exploded module. If the entry is a regular
 * file then it is assumed to be a packaged module.
 *
 * @throws FindException if an error occurs scanning the entry
 */
private Map<String, ModuleReference> scan(Path entry) {
    BasicFileAttributes attrs;
    try {
        attrs = Files.readAttributes(entry, BasicFileAttributes.class);
    } catch (NoSuchFileException e) {
        return Collections.emptyMap();
    } catch (IOException ioe) {
        throw new FindException(ioe);
    }
    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);
    }
}
Also used : Path(java.nio.file.Path) FindException(java.lang.module.FindException) ModuleReference(java.lang.module.ModuleReference) NoSuchFileException(java.nio.file.NoSuchFileException) IOException(java.io.IOException) UncheckedIOException(java.io.UncheckedIOException) BasicFileAttributes(java.nio.file.attribute.BasicFileAttributes)

Example 2 with FindException

use of java.lang.module.FindException 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 3 with FindException

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

the class ModulePath method readJar.

/**
 * Returns a {@code ModuleReference} to a module in modular JAR file on
 * the file system.
 *
 * @throws IOException
 * @throws FindException
 * @throws InvalidModuleDescriptorException
 */
private ModuleReference readJar(Path file) throws IOException {
    try (JarFile jf = new JarFile(file.toFile(), // verify
    true, ZipFile.OPEN_READ, releaseVersion)) {
        ModuleInfo.Attributes attrs;
        JarEntry entry = jf.getJarEntry(MODULE_INFO);
        if (entry == null) {
            // no module-info.class so treat it as automatic module
            try {
                ModuleDescriptor md = deriveModuleDescriptor(jf);
                attrs = new ModuleInfo.Attributes(md, null, null, null);
            } catch (RuntimeException e) {
                throw new FindException("Unable to derive module descriptor for " + jf.getName(), e);
            }
        } else {
            attrs = ModuleInfo.read(jf.getInputStream(entry), () -> jarPackages(jf));
        }
        return ModuleReferences.newJarModule(attrs, patcher, file);
    } catch (ZipException e) {
        throw new FindException("Error reading " + file, e);
    }
}
Also used : ModuleDescriptor(java.lang.module.ModuleDescriptor) FindException(java.lang.module.FindException) ZipException(java.util.zip.ZipException) JarFile(java.util.jar.JarFile) JarEntry(java.util.jar.JarEntry)

Example 4 with FindException

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

the class ModulePath method scanDirectory.

/**
 * Scans the given directory for packaged or exploded modules.
 *
 * @return a map of module name to ModuleReference for the modules found
 *         in the directory
 *
 * @throws IOException if an I/O error occurs
 * @throws FindException if an error occurs scanning the entry or the
 *         directory contains two or more modules with the same name
 */
private Map<String, ModuleReference> scanDirectory(Path dir) throws IOException {
    // The map of name -> mref of modules found in this directory.
    Map<String, ModuleReference> nameToReference = new HashMap<>();
    try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
        for (Path entry : stream) {
            BasicFileAttributes attrs;
            try {
                attrs = Files.readAttributes(entry, BasicFileAttributes.class);
            } catch (NoSuchFileException ignore) {
                // file has been removed or moved, ignore for now
                continue;
            }
            ModuleReference mref = readModule(entry, attrs);
            // module found
            if (mref != null) {
                // can have at most one version of a module in the directory
                String name = mref.descriptor().name();
                ModuleReference previous = nameToReference.put(name, mref);
                if (previous != null) {
                    String fn1 = fileName(mref);
                    String fn2 = fileName(previous);
                    throw new FindException("Two versions of module " + name + " found in " + dir + " (" + fn1 + " and " + fn2 + ")");
                }
            }
        }
    }
    return nameToReference;
}
Also used : Path(java.nio.file.Path) FindException(java.lang.module.FindException) ModuleReference(java.lang.module.ModuleReference) HashMap(java.util.HashMap) NoSuchFileException(java.nio.file.NoSuchFileException) BasicFileAttributes(java.nio.file.attribute.BasicFileAttributes)

Example 5 with FindException

use of java.lang.module.FindException 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

FindException (java.lang.module.FindException)5 Path (java.nio.file.Path)4 ModuleReference (java.lang.module.ModuleReference)3 NoSuchFileException (java.nio.file.NoSuchFileException)3 BasicFileAttributes (java.nio.file.attribute.BasicFileAttributes)3 IOException (java.io.IOException)2 UncheckedIOException (java.io.UncheckedIOException)2 InvalidModuleDescriptorException (java.lang.module.InvalidModuleDescriptorException)2 ModuleDescriptor (java.lang.module.ModuleDescriptor)2 HashMap (java.util.HashMap)2 JarEntry (java.util.jar.JarEntry)2 JarFile (java.util.jar.JarFile)2 ZipException (java.util.zip.ZipException)2 BufferedInputStream (java.io.BufferedInputStream)1 BufferedReader (java.io.BufferedReader)1 File (java.io.File)1 InputStream (java.io.InputStream)1 InputStreamReader (java.io.InputStreamReader)1 Builder (java.lang.module.ModuleDescriptor.Builder)1 ModuleFinder (java.lang.module.ModuleFinder)1