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

org.bitbucket.bradleysmithllc.etlunit.launcher.BootStrapper Maven / Gradle / Ivy

The newest version!
package org.bitbucket.bradleysmithllc.etlunit.launcher;

/*
 * #%L
 * etlunit-application-assembly
 * %%
 * Copyright (C) 2010 - 2023 bradleysmithllc
 * %%
 * 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.
 * #L%
 */

import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Model;
import org.apache.maven.model.building.DefaultModelBuilder;
import org.apache.maven.model.building.DefaultModelBuilderFactory;
import org.apache.maven.model.building.DefaultModelBuildingRequest;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
import org.apache.maven.model.resolution.ModelResolver;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuildingRequest;
import org.apache.maven.project.ProjectModelResolver;
import org.apache.maven.repository.internal.MavenRepositorySystemUtils;
import org.eclipse.aether.DefaultRepositorySystemSession;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RequestTrace;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory;
import org.eclipse.aether.impl.DefaultServiceLocator;
import org.eclipse.aether.impl.RemoteRepositoryManager;
import org.eclipse.aether.internal.impl.DefaultRepositorySystem;
import org.eclipse.aether.repository.LocalRepository;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.spi.connector.RepositoryConnectorFactory;
import org.eclipse.aether.spi.connector.transport.TransporterFactory;
import org.eclipse.aether.transport.file.FileTransporterFactory;
import org.eclipse.aether.transport.http.HttpTransporterFactory;
import org.eclipse.aether.transport.wagon.WagonTransporterFactory;

import java.io.*;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;

/**
 * Hello world!
 */
public class BootStrapper {
	private static Pair> effectiveProject = null;

	static Pair> effectiveProject() throws Exception {
		if (effectiveProject == null) {
			File pomFile = pomFile();

			if (!pomFile.exists()) {
				throw new IllegalStateException("No maven project detected");
			}

			effectiveProject = resolveProjectDependencies(pomFile);
		}

		return effectiveProject;
	}

	public static ClassLoader contextClassLoader() throws Exception {
		File localDirectory = localDirectory();

		List finalURLList = new ArrayList<>();

		// prepend the classes and test-classes directories to catch intermediate classes and resources
		addIfExists(mavenBuildDirectory(localDirectory, "test-classes"), finalURLList);
		addIfExists(mavenBuildDirectory(localDirectory, "classes"), finalURLList);
		addIfExists(mavenSrcTestDirectory(localDirectory, "resources"), finalURLList);
		addIfExists(mavenSrcMainDirectory(localDirectory, "resources"), finalURLList);

		finalURLList.addAll(effectiveProject().getRight());

		// write this log in the target folder
		File logFile = mavenBuildDirectory(localDirectory, "BootStrapper.classloader.log");

		// write out a debug log as well as creating a classpath for other modules
		StringBuilder classpathBuilder = new StringBuilder();

		FileWriter fw = new FileWriter(logFile);
		BufferedWriter writer = new BufferedWriter(fw);

		writer.write("URL ClassLoader components:\n");

		List classloaderURLList = new ArrayList<>();
		for (File file : finalURLList) {
			classloaderURLList.add(file.toURL());
			if (classpathBuilder.length() > 0) {
				classpathBuilder.append(File.pathSeparator);
			}

			classpathBuilder.append(file.getCanonicalPath());
			writer.write(file.getCanonicalPath());
			writer.write("\n");
		}

		writer.write("\n\nInternal classpath:\n\n\n");

		String str = classpathBuilder.toString();
		writer.write(str);

		writer.flush();
		writer.close();
		fw.close();

		System.setProperty("etlunit.maven.plugin.classpath", str);

		// create classloader
		ClassLoader urlClassLoader = new DelegatingClassLoader(classloaderURLList.toArray(new URL[classloaderURLList.size()]));
		Thread.currentThread().setContextClassLoader(urlClassLoader);

		return urlClassLoader;
	}

	private static void addIfExists(File directory, List finalURLList) throws MalformedURLException {
		if (directory.exists()) {
			finalURLList.add(directory);
		}
	}

	private static File pomFile() {
		File pom = new File(localDirectory(), "pom.xml");

		if (!pom.exists()) {
			throw new IllegalStateException("Not a maven project");
		}

		return pom;
	}

	private static File localDirectory() {
		return new File(System.getProperty("user.dir"));
	}

	private static File mavenSrcDirectory(File localDirectory) {
		return new File(localDirectory, "src");
	}

	private static File mavenSrcMainDirectory(File localDirectory) {
		return new File(mavenSrcDirectory(localDirectory), "main");
	}

	private static File mavenSrcTestDirectory(File localDirectory) {
		return new File(mavenSrcDirectory(localDirectory), "test");
	}

	private static File mavenSrcMainDirectory(File localDirectory, String resources) {
		return new File(mavenSrcMainDirectory(localDirectory), resources);
	}

	private static File mavenSrcTestDirectory(File localDirectory, String resources) {
		return new File(mavenSrcTestDirectory(localDirectory), resources);
	}

	private static File mavenBuildDirectory(File base) {
		return new File(base, "target");
	}

	private static File mavenBuildDirectory(File base, String classes) {
		return new File(mavenBuildDirectory(base), classes);
	}

	public static MavenProject loadProject(File pomFile) throws Exception {
		MavenProject ret = null;
		MavenXpp3Reader mavenReader = new MavenXpp3Reader();

		if (pomFile != null && pomFile.exists()) {
			FileReader reader = null;

			try {
				reader = new FileReader(pomFile);
				Model model = mavenReader.read(reader);
				model.setPomFile(pomFile);

				ret = new MavenProject(model);
			} finally {
				reader.close();
			}
		}

		return ret;
	}

	public static void main(String... argv) throws Exception {
		File localDirectory = localDirectory();
		File pomFile = pomFile();

		ClassLoader cll = contextClassLoader();

		Class cl = cll.loadClass("org.bitbucket.bradleysmithllc.etlunit.jline_cli.EtlUnitJLineCLI");

		Method method = cl.getDeclaredMethod("main", String[].class);

		// let the launcher do it's work
		method.invoke(null, new Object [] {argv});
	}

	public static Pair> resolveProjectDependencies(File pomFile) throws Exception {
		DefaultServiceLocator locator = serviceLocator();
		RepositorySystem system = locator.getService(RepositorySystem.class);

		DefaultRepositorySystemSession
			session = MavenRepositorySystemUtils.newSession();
		File localRepoDir = new File(System.getProperty("user.home"), ".m2/repository");
		localRepoDir.mkdirs();
		LocalRepository localRepo = new LocalRepository(localRepoDir);
		session.setLocalRepositoryManager(
			system.newLocalRepositoryManager(session, localRepo));

		RequestTrace requestTrace = new RequestTrace(null);
		RemoteRepositoryManager
			remoteRepositoryManager =
			locator.getService(RemoteRepositoryManager.class);
		List repos =
			Arrays.asList(new RemoteRepository.Builder("central", "default",
				"https://repo.maven.apache.org/maven2/").build());

		DefaultRepositorySystem repositorySystem =
			new DefaultRepositorySystem();
		repositorySystem.initService(locator);

		ModelResolver modelResolver =
			new ProjectModelResolver(session, requestTrace,
				repositorySystem, remoteRepositoryManager, repos,
				ProjectBuildingRequest.RepositoryMerging.POM_DOMINANT,
				null);

		DefaultModelBuildingRequest modelBuildingRequest =
			new DefaultModelBuildingRequest();
		modelBuildingRequest.setPomFile(pomFile);
		modelBuildingRequest.setModelResolver(modelResolver);
		DefaultModelBuilder
			modelBuilder = new DefaultModelBuilderFactory().newInstance();
		Model effectiveModel = modelBuilder.build(
			modelBuildingRequest).getEffectiveModel();

		List dependencies = new ArrayList<>();

		// verify that etlunit-jline is in the path, otherwise this project is not usable

		List effectiveModelDependencies = effectiveModel.getDependencies();

		for (Dependency dependency : effectiveModelDependencies) {
			// Set the coordinates of the artifact to download
			Artifact artifact = new DefaultArtifact(dependency.getGroupId(), dependency.getArtifactId(), "jar", dependency.getVersion());

			long start = System.currentTimeMillis();
			AetherTransitiveDependencies.resolve(artifact, dependencies);
			long stop = System.currentTimeMillis();
			System.out.println((stop - start) + "ms to resolve");
		}

		Set artifactSet = new HashSet<>();

		for (Artifact artifact : dependencies) {
			artifactSet.add(artifact.getGroupId() + ":" + artifact.getArtifactId());
		}

		if (!artifactSet.contains("org.bitbucket.bradleysmithllc.etlunit:etlunit-jline-cli")) {
			System.out.println("This project is not built with the org.bitbucket.bradleysmithllc.etlunit:etlunit-jline-cli dependency.  It cannot be used with this interface");
			System.exit(-1);
		}

		// this is the unfiltered list.  Make a single list of the max version for each dependency
		Map artifactVersions = new HashMap<>();

		for (Artifact artifact : dependencies) {
			String id = artifact.getGroupId() + "." + artifact.getArtifactId();

			if (!artifactVersions.containsKey(id)) {
				artifactVersions.put(id, artifact);
			} else {
				DefaultArtifactVersion thisVersion = new DefaultArtifactVersion(artifact.getVersion());
				Artifact lastArtifact = artifactVersions.get(id);
				DefaultArtifactVersion lastVersion = new DefaultArtifactVersion(lastArtifact.getVersion());

				if (thisVersion.compareTo(lastVersion) > 0) {
					artifactVersions.put(id, artifact);
				}
			}
		}

		List artifacts = new ArrayList<>(artifactVersions.values());
		Collections.sort(artifacts, Comparator.comparing(art -> (art.getGroupId() + "." + art.getArtifactId())));

		List urlList = new ArrayList<>();

		for (Artifact artifact : artifacts) {
			urlList.add(artifact.getFile());
		}

		File localCache = mavenBuildDirectory(pomFile.getParentFile(), "effectivePom.xml");

		localCache.getParentFile().mkdirs();
		FileWriter fw = new FileWriter(localCache);
		BufferedWriter bw = new BufferedWriter(fw);

		new MavenXpp3Writer().write(bw, effectiveModel);

		bw.flush();
		bw.close();

		return ImmutablePair.of(effectiveModel, urlList);
	}

	private static DefaultServiceLocator serviceLocator() {
		DefaultServiceLocator locator =
			MavenRepositorySystemUtils.newServiceLocator();
		locator.addService(RepositoryConnectorFactory.class,
			BasicRepositoryConnectorFactory.class);
		locator.addService(
			TransporterFactory.class, FileTransporterFactory.class);
		locator.addService(TransporterFactory.class,
			HttpTransporterFactory.class);
		locator.addService(TransporterFactory.class,
			WagonTransporterFactory.class);
		return locator;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy