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

com.github.pms1.tppt.mirror.MirrorApplication Maven / Gradle / Ivy

There is a newer version: 0.3.0
Show newest version
package com.github.pms1.tppt.mirror;

import java.io.InputStream;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;

import javax.xml.bind.JAXB;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.equinox.app.IApplication;
import org.eclipse.equinox.app.IApplicationContext;
import org.eclipse.equinox.internal.p2.artifact.repository.CompositeArtifactRepository;
import org.eclipse.equinox.internal.p2.director.PermissiveSlicer;
import org.eclipse.equinox.internal.p2.metadata.repository.CompositeMetadataRepository;
import org.eclipse.equinox.internal.p2.repository.Transport;
import org.eclipse.equinox.p2.core.IProvisioningAgent;
import org.eclipse.equinox.p2.core.IProvisioningAgentProvider;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.equinox.p2.engine.IProfile;
import org.eclipse.equinox.p2.internal.repository.mirroring.Mirroring;
import org.eclipse.equinox.p2.internal.repository.tools.SlicingOptions;
import org.eclipse.equinox.p2.metadata.IArtifactKey;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.metadata.IProvidedCapability;
import org.eclipse.equinox.p2.query.IQueryable;
import org.eclipse.equinox.p2.query.QueryUtil;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
import org.eclipse.equinox.spi.p2.publisher.PublisherHelper;
import org.osgi.framework.ServiceReference;

@SuppressWarnings("restriction")
public class MirrorApplication implements IApplication {

	private static boolean debug = false;

	@SuppressWarnings("unchecked")
	private static final Map[] emptyFilters = new Map[] { Collections.emptyMap() };

	@Override
	public Object start(IApplicationContext context) throws Exception {
		Object args = context.getArguments().get(IApplicationContext.APPLICATION_ARGS);

		if (debug)
			System.out.println("MirrorApplication.commandLine        = " + Arrays.asList((String[]) args));

		for (String s : Arrays.asList((String[]) args)) {
			MirrorSpec ms;
			if (s.equals("-")) {
				ms = JAXB.unmarshal(System.in, MirrorSpec.class);
			} else {
				try (InputStream is = Files.newInputStream(Paths.get(s))) {
					ms = JAXB.unmarshal(is, MirrorSpec.class);
				}
			}

			if (debug) {
				System.out.println("MirrorApplication.mirrorRepository   = " + ms.mirrorRepository);
				System.out.println("MirrorApplication.sourceRepositories = " + Arrays.toString(ms.sourceRepositories));
				System.out.println("MirrorApplication.targetRepository   = " + ms.targetRepository);
				System.out.println("MirrorApplication.installableUnit    = " + Arrays.toString(ms.ius));
				System.out.println("MirrorApplication.offline            = " + ms.offline);
				System.out.println("MirrorApplication.stats              = " + ms.stats);
				System.out.println("MirrorApplication.filter             = " + Arrays.toString(ms.filters));
			}

			IProgressMonitor monitor = new IProgressMonitor() {

				@Override
				public void worked(int work) {
					// TODO Auto-generated method stub

				}

				@Override
				public void subTask(String name) {
					// System.err.println("ST " + name);
				}

				@Override
				public void setTaskName(String name) {
					// System.err.println("STN " + name);
				}

				@Override
				public void setCanceled(boolean value) {
					// TODO Auto-generated method stub

				}

				@Override
				public boolean isCanceled() {
					// TODO Auto-generated method stub
					return false;
				}

				@Override
				public void internalWorked(double work) {
					// TODO Auto-generated method stub

				}

				@Override
				public void done() {
					// System.err.println("DONE");
				}

				@Override
				public void beginTask(String name, int totalWork) {
					// System.err.println("BT " + name);
				}
			};

			IProvisioningAgent ourAgent = getAgent();

			MyTransport transport = new MyTransport(ms.mirrorRepository, ms.offline, ms.stats);
			ourAgent.registerService(Transport.SERVICE_NAME, transport);

			CompositeArtifactRepository sourceArtifactRepo = CompositeArtifactRepository
					.createMemoryComposite(ourAgent);
			for (URI sr : ms.sourceRepositories)
				sourceArtifactRepo.addChild(sr);
			transport.addRepositories(sourceArtifactRepo.getLoadedChildren());

			CompositeMetadataRepository sourceMetadataRepo = CompositeMetadataRepository
					.createMemoryComposite(ourAgent);
			for (URI sr : ms.sourceRepositories)
				sourceMetadataRepo.addChild(sr);

			Set finalIus = new HashSet<>();

			for (Map basicFilter : ms.filters != null ? ms.filters : emptyFilters) {
				SlicingOptions slicingOptions = new SlicingOptions();
				Map filter = new HashMap(basicFilter);
				filter.put(IProfile.PROP_INSTALL_FEATURES, "true");
				slicingOptions.setFilter(filter);
				slicingOptions.considerStrictDependencyOnly(false);

				Set root = new HashSet<>();
				for (String iu : ms.ius) {
					// TODO: allow version to be specified, only latest version,
					// ...
					for (IInstallableUnit iu1 : sourceMetadataRepo.query(QueryUtil.createIUQuery(iu), monitor))
						root.add(iu1);
				}

				for (;;) {
					int oldRootSize = root.size();

					PermissiveSlicer slicer = new PermissiveSlicer(sourceMetadataRepo, slicingOptions.getFilter(),
							slicingOptions.includeOptionalDependencies(), slicingOptions.isEverythingGreedy(),
							slicingOptions.forceFilterTo(), slicingOptions.considerStrictDependencyOnly(),
							slicingOptions.followOnlyFilteredRequirements());

					IQueryable slice = slicer.slice(root.stream().toArray(IInstallableUnit[]::new),
							monitor);

					LinkedList todo = new LinkedList<>();
					for (IInstallableUnit iu : slice.query(QueryUtil.ALL_UNITS, monitor))
						todo.add(iu);

					while (!todo.isEmpty()) {
						IInstallableUnit iu = todo.removeFirst();
						if (!finalIus.add(iu))
							continue;

						switch (getType(iu)) {
						case bundle:
							for (IInstallableUnit iu1 : sourceMetadataRepo
									.query(QueryUtil.createIUQuery(iu.getId() + ".source", iu.getVersion()), monitor))
								if (getType(iu1) == Type.source_bundle) {
									if (!finalIus.contains(iu1) && todo.add(iu1))
										System.out.println("Adding " + iu1 + " as source of " + iu);
								}
							break;
						case feature:
							if (!iu.getId().endsWith(".feature.jar"))
								throw new Error("");
							String shortId = removeSuffix(iu.getId(), ".feature.jar");
							List cand = new ArrayList<>();
							cand.add(shortId + ".source.feature.group");
							if (shortId.endsWith(".feature")) {
								String s2 = removeSuffix(shortId, ".feature");
								cand.add(s2 + ".source.feature.group");
								cand.add(s2 + ".source.feature.feature.group");
							}
							for (String c : cand)
								for (IInstallableUnit iu1 : sourceMetadataRepo
										.query(QueryUtil.createIUQuery(c, iu.getVersion()), monitor))
									if (root.add(iu1))
										System.out.println("Adding " + iu1 + " as source of " + iu);
							break;
						default:
							break;
						}
					}

					if (oldRootSize == root.size())
						break;
				}
			}

			// mirror metadata
			IMetadataRepository destinationMetadataRepo = createDestinationMetadataRepository(
					(IMetadataRepositoryManager) ourAgent.getService(IMetadataRepositoryManager.SERVICE_NAME),
					ms.targetRepository, "");

			destinationMetadataRepo.addInstallableUnits(finalIus);

			// mirror artifacts
			IArtifactRepository destinationArtifactRepo = createDestinationArtifactRepository(
					(IArtifactRepositoryManager) ourAgent.getService(IArtifactRepositoryManager.SERVICE_NAME),
					ms.targetRepository, "");

			Mirroring mirroring = new Mirroring(sourceArtifactRepo, destinationArtifactRepo, true);
			mirroring.setTransport(transport);
			mirroring.setIncludePacked(false);
			mirroring.setArtifactKeys(
					finalIus.stream().flatMap(p -> p.getArtifacts().stream()).toArray(IArtifactKey[]::new));

			MultiStatus multiStatus = mirroring.run(true, false);
			if (!multiStatus.isOK()) {
				System.err.println("STATUS=" + multiStatus);
				return 1;
			}
		}

		return null;
	}

	static IProvisioningAgent getAgent() throws ProvisionException {
		ServiceReference serviceReference = Activator.getContext()
				.getServiceReference(IProvisioningAgentProvider.SERVICE_NAME);
		IProvisioningAgentProvider agentFactory = (IProvisioningAgentProvider) Activator.getContext()
				.getService(serviceReference);
		IProvisioningAgent ourAgent;
		try {
			ourAgent = agentFactory.createAgent(null); // targetDirectory.getChild("p2agent").toURI());
		} catch (ProvisionException e) {
			throw e;
		} finally {
			Activator.getContext().ungetService(serviceReference);
		}
		return ourAgent;
	}

	private String removeSuffix(String id, String suffix) {
		Objects.requireNonNull(id);
		Objects.requireNonNull(suffix);
		if (!id.endsWith(suffix))
			throw new IllegalArgumentException("'" + id + "' does not end with '" + suffix + "'");
		return id.substring(0, id.length() - suffix.length());
	}

	static enum Type {
		feature, bundle, source_bundle, other
	}

	private Type getType(IInstallableUnit iu) {

		Optional cap = iu.getProvidedCapabilities().stream()
				.filter(p -> p.getNamespace().equals(PublisherHelper.NAMESPACE_ECLIPSE_TYPE)).findAny();

		if (!cap.isPresent())
			return Type.other;
		switch (cap.get().getName()) {
		case "source":
			return Type.source_bundle;
		case "bundle":
			return Type.bundle;
		case "feature":
			return Type.feature;
		default:
			System.err.println("UNHANDLED " + cap.get());
			return Type.other;
		}

	}

	final String featureSuffix = ".feature.group";

	private IArtifactRepository createDestinationArtifactRepository(IArtifactRepositoryManager mgr, Path path,
			String name) {
		try {
			try {
				return mgr.loadRepository(path.toUri(), IArtifactRepositoryManager.REPOSITORY_HINT_MODIFIABLE,
						new NullProgressMonitor());
			} catch (ProvisionException e) {
				// assume that repository does not exist
			}

			IArtifactRepository dest;
			try {
				dest = mgr.createRepository(path.toUri(), name, IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY,
						null);
				return dest;
			} catch (ProvisionException e) {
				throw new RuntimeException(e);
			}
		} catch (OperationCanceledException e) {
			throw new RuntimeException(e);
		}
	}

	private IMetadataRepository createDestinationMetadataRepository(IMetadataRepositoryManager mgr, Path path,
			String string) {
		try {
			try {
				return mgr.loadRepository(path.toUri(), IMetadataRepositoryManager.REPOSITORY_HINT_MODIFIABLE,
						new NullProgressMonitor());
			} catch (ProvisionException e) {
				// assume that repository does not exist
			}

			IMetadataRepository dest;
			try {
				dest = mgr.createRepository(path.toUri(), string, IMetadataRepositoryManager.TYPE_SIMPLE_REPOSITORY,
						null);
				return dest;
			} catch (ProvisionException e) {
				throw new RuntimeException(e);
			}
		} catch (OperationCanceledException e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public void stop() {
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy