All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jboss.modules.JarModuleLoader Maven / Gradle / Ivy

/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2011, Red Hat, Inc., and individual contributors
 * as indicated by the @author tags. See the copyright.txt file in the
 * distribution for a full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.jboss.modules;

import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import org.jboss.modules.filter.MultiplePathFilterBuilder;
import org.jboss.modules.filter.PathFilters;

/**
 * @author David M. Lloyd
 */
final class JarModuleLoader extends ModuleLoader {

    private static final String[] NO_STRINGS = new String[0];
    private final ModuleLoader delegate;
    private final JarFile jarFile;
    private final String simpleJarName;
    private final ModuleIdentifier myIdentifier;

    JarModuleLoader(final ModuleLoader delegate, final JarFile jarFile) {
        this.delegate = delegate;
        this.jarFile = jarFile;
        String jarName = jarFile.getName();
        simpleJarName = jarName.substring(jarName.lastIndexOf(File.separatorChar) + 1);
        myIdentifier = ModuleIdentifier.create(simpleJarName);
    }

    protected Module preloadModule(final ModuleIdentifier identifier) throws ModuleLoadException {
        if (identifier.equals(myIdentifier)) {
            return loadModuleLocal(identifier);
        } else {
            Module module = loadModuleLocal(identifier);
            if (module == null) {
                return preloadModule(identifier, delegate);
            } else {
                return module;
            }
        }
    }

    ModuleIdentifier getMyIdentifier() {
        return myIdentifier;
    }

    public String toString() {
        return "JAR module loader";
    }

    protected ModuleSpec findModule(final ModuleIdentifier identifier) throws ModuleLoadException {
        if (identifier.equals(myIdentifier)) {
            // special root JAR module
            Manifest manifest = null;
            try {
                manifest = jarFile.getManifest();
            } catch (IOException e) {
                throw new ModuleLoadException("Failed to load MANIFEST from JAR", e);
            }
            ModuleSpec.Builder builder = ModuleSpec.build(identifier);
            Attributes mainAttributes = manifest.getMainAttributes();
            String mainClass = mainAttributes.getValue(Attributes.Name.MAIN_CLASS);
            if (mainClass != null) {
                builder.setMainClass(mainClass);
            }
            String classPath = mainAttributes.getValue(Attributes.Name.CLASS_PATH);
            String dependencies = mainAttributes.getValue("Dependencies");
            MultiplePathFilterBuilder pathFilterBuilder = PathFilters.multiplePathFilterBuilder(true);
            pathFilterBuilder.addFilter(PathFilters.is("modules"), false);
            pathFilterBuilder.addFilter(PathFilters.isChildOf("modules"), false);
            builder.addResourceRoot(ResourceLoaderSpec.createResourceLoaderSpec(new JarFileResourceLoader("", jarFile), pathFilterBuilder.create()));
            String[] classPathEntries = classPath == null ? NO_STRINGS : classPath.split("\\w+");
            for (String entry : classPathEntries) {
                if (! entry.isEmpty()) {
                    if (entry.startsWith("../") || entry.startsWith("./") || entry.startsWith("/") || entry.contains("/../")) {
                        // invalid
                        continue;
                    }
                    if (entry.endsWith("/")) {
                        // directory reference
                        File root = new File(jarFile.getName(), entry);
                        FileResourceLoader resourceLoader = new FileResourceLoader(entry, root);
                        builder.addResourceRoot(ResourceLoaderSpec.createResourceLoaderSpec(resourceLoader));
                    } else {
                        // assume a JAR
                        File root = new File(jarFile.getName(), entry);
                        JarFile childJarFile;
                        try {
                            childJarFile = new JarFile(root, true);
                        } catch (IOException e) {
                            // ignore and continue
                            continue;
                        }
                        builder.addResourceRoot(ResourceLoaderSpec.createResourceLoaderSpec(new JarFileResourceLoader(entry, childJarFile)));
                    }
                }
            }
            String[] dependencyEntries = dependencies == null ? NO_STRINGS : dependencies.split("\\s*,\\s*");
            for (String dependencyEntry : dependencyEntries) {
                boolean optional = false;
                boolean export = false;
                dependencyEntry = dependencyEntry.trim();
                if (! dependencyEntry.isEmpty()) {
                    String[] fields = dependencyEntry.split("\\s+");
                    if (fields.length < 1) {
                        continue;
                    }
                    String moduleName = fields[0];
                    for (int i = 1; i < fields.length; i++) {
                        String field = fields[i];
                        if (field.equals("optional")) {
                            optional = true;
                        } else if (field.equals("export")) {
                            export = true;
                        }
                        // else ignored
                    }
                    builder.addDependency(DependencySpec.createModuleDependencySpec(ModuleIdentifier.fromString(moduleName), export, optional));
                }
            }
            builder.addDependency(DependencySpec.createSystemDependencySpec(JDKPaths.JDK));
            builder.addDependency(DependencySpec.createLocalDependencySpec());
            return builder.create();
        } else {
            String namePath = identifier.getName().replace('.', '/');
            String basePath = "modules/" + namePath + "/" + identifier.getSlot();
            JarEntry moduleXmlEntry = jarFile.getJarEntry(basePath + "/module.xml");
            if (moduleXmlEntry == null) {
                return null;
            }
            ModuleSpec moduleSpec;
            try {
                InputStream inputStream = jarFile.getInputStream(moduleXmlEntry);
                try {
                    moduleSpec = ModuleXmlParser.parseModuleXml(new ModuleXmlParser.ResourceRootFactory() {
                        public ResourceLoader createResourceLoader(final String rootPath, final String loaderPath, final String loaderName) throws IOException {
                            return new JarFileResourceLoader(loaderName, jarFile, loaderPath);
                        }
                    }, basePath, inputStream, moduleXmlEntry.getName(), identifier);
                } finally {
                    safeClose(inputStream);
                }
            } catch (IOException e) {
                throw new ModuleLoadException("Failed to read module.xml file", e);
            }
            return moduleSpec;
        }
    }

    private static void safeClose(final Closeable closeable) {
        if (closeable != null) try {
            closeable.close();
        } catch (IOException e) {
            // ignore
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy