org.terasology.module.ClasspathModule.java Source code

Java tutorial

Introduction

Here is the source code for org.terasology.module.ClasspathModule.java

Source

/*
 * Copyright 2015 MovingBlocks
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.terasology.module;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.terasology.module.exceptions.InvalidModulePathException;
import org.terasology.util.Varargs;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.CodeSource;
import java.util.Collection;
import java.util.Set;

/**
 * A module that exists on the classpath. This means that it is always loaded and available, so should not be loaded in a secondary class loader.
 *
 * @author Immortius
 */
public final class ClasspathModule extends BaseModule {

    private static final Logger logger = LoggerFactory.getLogger(ClasspathModule.class);
    private final ImmutableList<URL> classpaths;

    /**
     * @param metadata Module metadata describing this module
     * @param paths    a collection of paths to the module locations - may be a mixture of file and directory paths
     */
    private ClasspathModule(ModuleMetadata metadata, Collection<Path> paths) {
        super(paths, metadata);
        logger.debug("Creating ClasspathModule '{}' with paths '{}'", metadata.getId(), paths);
        ImmutableList.Builder<URL> builder = ImmutableList.builder();
        for (Path path : paths) {
            try {
                builder.add(path.toUri().toURL());
            } catch (MalformedURLException e) {
                throw new InvalidModulePathException("Path cannot be converted to URL: " + path, e);
            }
        }
        classpaths = builder.build();
    }

    /**
     * Creates a classpath module from a set of code sources.
     * <p>
     * There is an option to include directories on the classpath. This should only be done for one classpath module - this is for use when running from source
     * in environments that keep resources and classes in separate locations (e.g. gradle by default). Any directory on the classpath (as opposed to jars) will be
     * included in this module
     * </p>
     *
     * @param metadata           Metadata describing the module to create
     * @param includeDirectories Whether to include directories on the classpath.
     * @param primarySource      The first source to include in this module
     * @param additionalSources  Any additional sources to include
     * @return A new ClasspathModule
     * @throws URISyntaxException If a source location cannot be converted to a proper URI (typically because the path to the source includes an invalid character).
     */
    public static ClasspathModule create(ModuleMetadata metadata, boolean includeDirectories,
            CodeSource primarySource, CodeSource... additionalSources) throws URISyntaxException {
        Set<Path> paths = Sets.newLinkedHashSet();

        for (CodeSource source : Varargs.combineToSet(primarySource, additionalSources)) {
            paths.add(Paths.get(source.getLocation().toURI()));
        }
        if (includeDirectories) {
            addClasspathDirectories(paths);
        }
        return new ClasspathModule(metadata, paths);
    }

    /**
     * Creates a classpath module from a set of representative classes. The code source (e.g. Jar or directory) for each class is included in the Classpath module.
     *
     * @param metadata          Metadata describing the module to create
     * @param primaryClass      The first representative class to include in the module
     * @param additionalClasses Any additional representative classes to include.
     * @return A new ClasspathModule
     * @throws URISyntaxException If a source location cannot be converted to a proper URI (typically because the path to the source includes an invalid character).
     */
    public static ClasspathModule create(ModuleMetadata metadata, Class<?> primaryClass,
            Class<?>... additionalClasses) throws URISyntaxException {
        return create(metadata, false, primaryClass, additionalClasses);
    }

    /**
     * Creates a classpath module from a set of representative classes. The code source (e.g. Jar or directory) for each class is included in the Classpath module.
     * <p>
     * There is an option to include directories on the classpath. This should only be done for one classpath module - this is for use when running from source
     * in environments that keep resources and classes in separate locations (e.g. gradle by default). Any directory on the classpath (as opposed to jars) will be
     * included in this module
     * </p>
     *
     * @param metadata           Metadata describing the module to create
     * @param includeDirectories Should directories on the classpath be included in this module?
     * @param primaryClass       The first representative class to include in the module
     * @param additionalClasses  Any additional representative classes to include.
     * @return A new ClasspathModule
     * @throws URISyntaxException If a source location cannot be converted to a proper URI (typically because the path to the source includes an invalid character).
     */
    public static ClasspathModule create(ModuleMetadata metadata, boolean includeDirectories, Class<?> primaryClass,
            Class<?>... additionalClasses) throws URISyntaxException {
        Set<Path> paths = Sets.newLinkedHashSet();

        for (Class<?> type : Varargs.combineToSet(primaryClass, additionalClasses)) {
            paths.add(Paths.get(type.getProtectionDomain().getCodeSource().getLocation().toURI()));
        }
        if (includeDirectories) {
            addClasspathDirectories(paths);
        }
        return new ClasspathModule(metadata, paths);
    }

    private static void addClasspathDirectories(Set<Path> paths) {
        for (String classpath : System.getProperty("java.class.path").split(File.pathSeparator)) {
            Path path = Paths.get(classpath);
            if (Files.isDirectory(path)) {
                paths.add(path);
            }
        }
    }

    @Override
    public ImmutableList<URL> getClasspaths() {
        return classpaths;
    }

    @Override
    public boolean isOnClasspath() {
        return true;
    }

    @Override
    public boolean isCodeModule() {
        return true;
    }

}