use of org.lanternpowered.launch.dependencies.Dependency 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;
}
Aggregations