Search in sources :

Example 1 with Dependencies

use of org.lanternpowered.launch.dependencies.Dependencies in project LanternServer by LanternPowered.

the class LanternClassLoader method load.

private static LanternClassLoader load() throws IOException {
    ClassLoader.registerAsParallelCapable();
    // Get the bootstrap class loader
    final ClassLoader classLoader = LanternClassLoader.class.getClassLoader();
    // Load the dependencies files
    final List<Dependencies> dependenciesEntries = new ArrayList<>();
    // Load the dependencies file within the jar, not available in the IDE
    final URL dependenciesURL = classLoader.getResource("dependencies.json");
    if (dependenciesURL != null) {
        try {
            dependenciesEntries.add(DependenciesParser.read(new BufferedReader(new InputStreamReader(dependenciesURL.openStream()))));
        } catch (ParseException e) {
            throw new IllegalStateException("Failed to parse the dependencies.json file within the jar.", e);
        }
    }
    // Try to generate or load the dependencies file
    final Path dependenciesFile = Paths.get("dependencies.json");
    if (!Files.exists(dependenciesFile)) {
        try (BufferedWriter writer = Files.newBufferedWriter(dependenciesFile)) {
            writer.write("{\n    \"repositories\": [\n    ],\n    \"dependencies\": [\n    ]\n}");
        }
    } else {
        try {
            dependenciesEntries.add(DependenciesParser.read(Files.newBufferedReader(dependenciesFile)));
        } catch (ParseException e) {
            throw new IllegalStateException("Failed to parse the dependencies.json file within the root directory.", e);
        }
    }
    // Merge the dependencies files
    final List<URL> repositoryUrls = new ArrayList<>();
    final Map<String, Dependency> dependencyMap = new HashMap<>();
    for (Dependencies dependencies : dependenciesEntries) {
        dependencies.getRepositories().stream().map(Repository::getUrl).filter(e -> !repositoryUrls.contains(e)).forEach(repositoryUrls::add);
        for (Dependency dependency : dependencies.getDependencies()) {
            dependencyMap.put(dependency.getGroup() + ':' + dependency.getName(), dependency);
        }
    }
    String localRepoPath = System.getProperty("maven.repo.local");
    if (localRepoPath == null) {
        final String mavenHome = System.getenv("M2_HOME");
        if (mavenHome != null) {
            final Path settingsPath = Paths.get(mavenHome, "conf", "setting.xml");
            if (Files.exists(settingsPath)) {
                try {
                    final DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
                    final Document document = documentBuilder.parse(settingsPath.toFile());
                    // http://stackoverflow.com/questions/13786607/normalization-in-dom-parsing-with-java-how-does-it-work
                    document.getDocumentElement().normalize();
                    final Node node = document.getElementsByTagName("localRepository").item(0);
                    if (node != null) {
                        localRepoPath = node.getTextContent();
                    }
                } catch (ParserConfigurationException | SAXException e) {
                    throw new IllegalStateException(e);
                }
            }
        }
    }
    if (localRepoPath == null) {
        localRepoPath = "~/.m/repository";
    }
    localRepoPath = localRepoPath.trim();
    if (localRepoPath.charAt(0) == '~') {
        localRepoPath = System.getProperty("user.home") + '/' + localRepoPath.substring(2);
    }
    // Try to find the local maven repository
    repositoryUrls.add(0, new File(localRepoPath).toURL());
    final List<FileRepository> repositories = new ArrayList<>();
    for (URL repositoryUrl : repositoryUrls) {
        if (repositoryUrl.getProtocol().equals("file")) {
            final File baseFile = new File(repositoryUrl.getFile());
            repositories.add(path -> {
                final File file = new File(baseFile, path);
                try {
                    return file.exists() ? file.toURL().openStream() : null;
                } catch (IOException e) {
                    throw new IllegalStateException(e);
                }
            });
        } else {
            String repositoryUrlBase = repositoryUrl.toString();
            if (repositoryUrlBase.endsWith("/")) {
                repositoryUrlBase = repositoryUrlBase.substring(0, repositoryUrlBase.length() - 1);
            }
            final String urlBase = repositoryUrlBase;
            repositories.add(path -> {
                try {
                    final URL url = new URL(urlBase + "/" + path);
                    final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                    connection.setRequestMethod("GET");
                    final String encoding = connection.getHeaderField("Content-Encoding");
                    InputStream is = connection.getInputStream();
                    if (encoding != null) {
                        if (encoding.equals("gzip")) {
                            is = new GZIPInputStream(is);
                        } else {
                            throw new IllegalStateException("Unsupported encoding: " + encoding);
                        }
                    }
                    return is;
                } catch (IOException e) {
                    return null;
                }
            });
        }
    }
    // If we are outside development mode, the server will be packed
    // into a jar. We will also need to make sure that this one gets
    // added in this case
    final CodeSource source = LanternClassLoader.class.getProtectionDomain().getCodeSource();
    final URL location = source == null ? null : source.getLocation();
    // Setup the environment variable
    final String env = System.getProperty(ENVIRONMENT);
    final Environment environment;
    if (env != null) {
        try {
            environment = Environment.valueOf(env.toUpperCase());
        } catch (IllegalArgumentException e) {
            throw new RuntimeException("Invalid environment type: " + env);
        }
    } else {
        environment = location == null || new File(location.getFile()).isDirectory() ? Environment.DEVELOPMENT : Environment.PRODUCTION;
        System.setProperty(ENVIRONMENT, environment.toString().toLowerCase());
    }
    Environment.set(environment);
    // Scan the jar for library jars
    if (location != null) {
        repositories.add(path -> classLoader.getResourceAsStream("dependencies/" + path));
    }
    final List<URL> libraryUrls = new ArrayList<>();
    // Download or load all the dependencies
    final Path internalLibrariesPath = Paths.get(".cached-dependencies");
    for (Dependency dependency : dependencyMap.values()) {
        final String group = dependency.getGroup();
        final String name = dependency.getName();
        final String version = dependency.getVersion();
        final Path target = internalLibrariesPath.resolve(String.format("%s/%s/%s/%s-%s.jar", group.replace('.', '/'), name, version, name, version));
        libraryUrls.add(target.toUri().toURL());
        final String id = String.format("%s:%s:%s", dependency.getGroup(), dependency.getName(), dependency.getVersion());
        if (Files.exists(target)) {
            System.out.printf("Loaded: \"%s\"\n", id);
            continue;
        }
        InputStream is = null;
        for (FileRepository repository : repositories) {
            is = repository.get(dependency);
            if (is != null) {
                break;
            }
        }
        if (is == null) {
            throw new IllegalStateException("The following dependency could not be found: " + id);
        }
        final Path parent = target.getParent();
        if (!Files.exists(parent)) {
            Files.createDirectories(parent);
        }
        System.out.printf("Downloading \"%s\"\n", id);
        try (ReadableByteChannel i = Channels.newChannel(is);
            FileOutputStream o = new FileOutputStream(target.toFile())) {
            o.getChannel().transferFrom(i, 0, Long.MAX_VALUE);
        }
    }
    // All the folders are from lantern or sponge,
    // in development mode are all the libraries on
    // the classpath, so there is no need to add them
    // to the library classloader
    final List<URL> urls = new ArrayList<>();
    final String classPath = System.getProperty("java.class.path");
    final String[] libraries = classPath.split(File.pathSeparator);
    for (String library : libraries) {
        try {
            final URL url = Paths.get(library).toUri().toURL();
            if (!library.endsWith(".jar") || url.equals(location)) {
                urls.add(url);
            }
        } catch (MalformedURLException ignored) {
            System.out.println("Invalid library found in the class path: " + library);
        }
    }
    // The server class loader will load lantern, the api and all the plugins
    final LanternClassLoader serverClassLoader = new LanternClassLoader(urls.toArray(new URL[urls.size()]), libraryUrls.toArray(new URL[libraryUrls.size()]), classLoader);
    Thread.currentThread().setContextClassLoader(serverClassLoader);
    return serverClassLoader;
}
Also used : HttpURLConnection(java.net.HttpURLConnection) Manifest(java.util.jar.Manifest) Arrays(java.util.Arrays) GZIPInputStream(java.util.zip.GZIPInputStream) Enumeration(java.util.Enumeration) URL(java.net.URL) JarFile(java.util.jar.JarFile) Repository(org.lanternpowered.launch.dependencies.Repository) URLClassLoader(java.net.URLClassLoader) Document(org.w3c.dom.Document) Map(java.util.Map) Method(java.lang.reflect.Method) Path(java.nio.file.Path) Dependency(org.lanternpowered.launch.dependencies.Dependency) LanternServer(org.lanternpowered.server.LanternServer) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Set(java.util.Set) InvocationTargetException(java.lang.reflect.InvocationTargetException) List(java.util.List) DependenciesParser(org.lanternpowered.launch.dependencies.DependenciesParser) SAXException(org.xml.sax.SAXException) Optional(java.util.Optional) DocumentBuilderFactory(javax.xml.parsers.DocumentBuilderFactory) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) HashMap(java.util.HashMap) CodeSigner(java.security.CodeSigner) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) ClassTransformer(org.lanternpowered.launch.transformer.ClassTransformer) ParseException(org.json.simple.parser.ParseException) Objects.requireNonNull(java.util.Objects.requireNonNull) Node(org.w3c.dom.Node) Exclusion(org.lanternpowered.launch.transformer.Exclusion) NoSuchElementException(java.util.NoSuchElementException) ReadableByteChannel(java.nio.channels.ReadableByteChannel) MalformedURLException(java.net.MalformedURLException) Files(java.nio.file.Files) BufferedWriter(java.io.BufferedWriter) Channels(java.nio.channels.Channels) FileOutputStream(java.io.FileOutputStream) IOException(java.io.IOException) InputStreamReader(java.io.InputStreamReader) Dependencies(org.lanternpowered.launch.dependencies.Dependencies) File(java.io.File) Consumer(java.util.function.Consumer) Element(org.w3c.dom.Element) Paths(java.nio.file.Paths) ParserConfigurationException(javax.xml.parsers.ParserConfigurationException) DocumentBuilder(javax.xml.parsers.DocumentBuilder) BufferedReader(java.io.BufferedReader) CodeSource(java.security.CodeSource) Collections(java.util.Collections) InputStream(java.io.InputStream) ReadableByteChannel(java.nio.channels.ReadableByteChannel) MalformedURLException(java.net.MalformedURLException) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) Node(org.w3c.dom.Node) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) Document(org.w3c.dom.Document) URL(java.net.URL) BufferedWriter(java.io.BufferedWriter) SAXException(org.xml.sax.SAXException) GZIPInputStream(java.util.zip.GZIPInputStream) HttpURLConnection(java.net.HttpURLConnection) URLClassLoader(java.net.URLClassLoader) Dependencies(org.lanternpowered.launch.dependencies.Dependencies) ParserConfigurationException(javax.xml.parsers.ParserConfigurationException) Path(java.nio.file.Path) InputStreamReader(java.io.InputStreamReader) GZIPInputStream(java.util.zip.GZIPInputStream) InputStream(java.io.InputStream) Dependency(org.lanternpowered.launch.dependencies.Dependency) IOException(java.io.IOException) CodeSource(java.security.CodeSource) Repository(org.lanternpowered.launch.dependencies.Repository) DocumentBuilder(javax.xml.parsers.DocumentBuilder) FileOutputStream(java.io.FileOutputStream) BufferedReader(java.io.BufferedReader) ParseException(org.json.simple.parser.ParseException) JarFile(java.util.jar.JarFile) File(java.io.File)

Aggregations

BufferedReader (java.io.BufferedReader)1 BufferedWriter (java.io.BufferedWriter)1 File (java.io.File)1 FileOutputStream (java.io.FileOutputStream)1 IOException (java.io.IOException)1 InputStream (java.io.InputStream)1 InputStreamReader (java.io.InputStreamReader)1 InvocationTargetException (java.lang.reflect.InvocationTargetException)1 Method (java.lang.reflect.Method)1 HttpURLConnection (java.net.HttpURLConnection)1 MalformedURLException (java.net.MalformedURLException)1 URL (java.net.URL)1 URLClassLoader (java.net.URLClassLoader)1 Channels (java.nio.channels.Channels)1 ReadableByteChannel (java.nio.channels.ReadableByteChannel)1 Files (java.nio.file.Files)1 Path (java.nio.file.Path)1 Paths (java.nio.file.Paths)1 CodeSigner (java.security.CodeSigner)1 CodeSource (java.security.CodeSource)1