blob: 15a7c7f5fc8c2e0c9efa5b7a70e3b93b124a71fe [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.equinox.p2.internal.repository.tools;
import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.app.IApplication;
import org.eclipse.equinox.app.IApplicationContext;
import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
import org.eclipse.equinox.internal.p2.director.PermissiveSlicer;
import org.eclipse.equinox.internal.p2.repository.Transport;
import org.eclipse.equinox.internal.p2.repository.helpers.RepositoryHelper;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.equinox.p2.engine.*;
import org.eclipse.equinox.p2.internal.repository.mirroring.*;
import org.eclipse.equinox.p2.metadata.*;
import org.eclipse.equinox.p2.planner.IPlanner;
import org.eclipse.equinox.p2.planner.IProfileChangeRequest;
import org.eclipse.equinox.p2.query.*;
import org.eclipse.equinox.p2.repository.artifact.IArtifactDescriptor;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
import org.eclipse.osgi.util.NLS;
public class MirrorApplication extends AbstractApplication implements IApplication, IExecutableExtension {
private static final String LOG_ROOT = "p2.mirror"; //$NON-NLS-1$
private static final String MIRROR_MODE = "metadataOrArtifacts"; //$NON-NLS-1$
protected SlicingOptions slicingOptions = new SlicingOptions();
private URI baseline;
private String comparatorID;
private IQuery<IArtifactDescriptor> compareExclusions = null;
private boolean compare = false;
private boolean failOnError = true;
private boolean raw = true;
private boolean verbose = false;
private boolean validate = false;
private boolean mirrorReferences = true;
private String metadataOrArtifacts = null;
private String[] rootIUs = null;
private File mirrorLogFile; // file to log mirror output to (optional)
private File comparatorLogFile; // file to comparator output to (optional)
private IArtifactMirrorLog mirrorLog;
private IArtifactMirrorLog comparatorLog;
/**
* Convert a list of tokens into an array. The list separator has to be
* specified.
*/
public static String[] getArrayArgsFromString(String list, String separator) {
if (list == null || list.trim().equals("")) //$NON-NLS-1$
return new String[0];
List<String> result = new ArrayList<String>();
for (StringTokenizer tokens = new StringTokenizer(list, separator); tokens.hasMoreTokens();) {
String token = tokens.nextToken().trim();
if (!token.equals("")) { //$NON-NLS-1$
if ((token.indexOf('[') >= 0 || token.indexOf('(') >= 0) && tokens.hasMoreTokens())
result.add(token + separator + tokens.nextToken());
else
result.add(token);
}
}
return result.toArray(new String[result.size()]);
}
public Object start(IApplicationContext context) throws Exception {
Map<?, ?> args = context.getArguments();
initializeFromArguments((String[]) args.get(IApplicationContext.APPLICATION_ARGS));
run(null);
return IApplication.EXIT_OK;
}
public void stop() {
// TODO Auto-generated method stub
}
/*
* The old "org.eclipse.equinox.p2.artifact.repository.mirrorApplication" application only does artifacts
* Similary, "org.eclipse.equinox.p2.metadata.repository.mirrorApplication" only does metadata
*/
public void setInitializationData(IConfigurationElement config, String propertyName, Object data) {
if (data instanceof Map<?, ?> && ((Map<?, ?>) data).containsKey(MIRROR_MODE)) {
metadataOrArtifacts = (String) ((Map<?, ?>) data).get(MIRROR_MODE);
}
}
public void initializeFromArguments(String[] args) throws Exception {
if (args == null)
return;
File comparatorLogLocation = null;
File mirrorLogLocation = null;
RepositoryDescriptor destination = new RepositoryDescriptor();
RepositoryDescriptor sourceRepo = new RepositoryDescriptor();
if (metadataOrArtifacts != null) {
destination.setKind(metadataOrArtifacts);
sourceRepo.setKind(metadataOrArtifacts);
}
addDestination(destination);
addSource(sourceRepo);
for (int i = 0; i < args.length; i++) {
// check for args without parameters (i.e., a flag arg)
if (args[i].equalsIgnoreCase("-raw")) //$NON-NLS-1$
raw = true;
else if (args[i].equalsIgnoreCase("-ignoreErrors")) //$NON-NLS-1$
failOnError = false;
else if (args[i].equalsIgnoreCase("-verbose")) //$NON-NLS-1$
verbose = true;
else if (args[i].equalsIgnoreCase("-compare")) //$NON-NLS-1$
compare = true;
else if (args[i].equalsIgnoreCase("-validate")) //$NON-NLS-1$
validate = true;
else if (args[i].equalsIgnoreCase("-references")) //$NON-NLS-1$
mirrorReferences = true;
// check for args with parameters. If we are at the last argument or
// if the next one has a '-' as the first character, then we can't have
// an arg with a param so continue.
if (i == args.length - 1 || args[i + 1].startsWith("-")) //$NON-NLS-1$
continue;
String arg = args[++i];
if (args[i - 1].equalsIgnoreCase("-comparator")) //$NON-NLS-1$
comparatorID = arg;
else if (args[i - 1].equalsIgnoreCase("-comparatorLog")) //$NON-NLS-1$
comparatorLogLocation = new File(arg);
else if (args[i - 1].equalsIgnoreCase("-destinationName")) //$NON-NLS-1$
destination.setName(arg);
else if (args[i - 1].equalsIgnoreCase("-writeMode")) { //$NON-NLS-1$
if (args[i].equalsIgnoreCase("clean")) //$NON-NLS-1$
destination.setAppend(false);
} else if (args[i - 1].equalsIgnoreCase("-log")) { //$NON-NLS-1$
mirrorLogLocation = new File(arg);
} else if (args[i - 1].equalsIgnoreCase("-roots")) { //$NON-NLS-1$
rootIUs = getArrayArgsFromString(arg, ","); //$NON-NLS-1$
} else {
try {
if (args[i - 1].equalsIgnoreCase("-source")) { //$NON-NLS-1$
URI uri = RepositoryHelper.localRepoURIHelper(URIUtil.fromString(arg));
sourceRepo.setLocation(uri);
destination.setFormat(uri);
} else if (args[i - 1].equalsIgnoreCase("-destination")) //$NON-NLS-1$
destination.setLocation(RepositoryHelper.localRepoURIHelper(URIUtil.fromString(arg)));
else if (args[i - 1].equalsIgnoreCase("-compareAgainst")) { //$NON-NLS-1$
baseline = RepositoryHelper.localRepoURIHelper(URIUtil.fromString(arg));
compare = true;
}
} catch (URISyntaxException e) {
throw new IllegalArgumentException(NLS.bind(Messages.ProcessRepo_location_not_url, arg));
}
}
}
// Create logs
if (mirrorLogLocation != null)
mirrorLog = getLog(mirrorLogLocation, "p2.artifact.mirror"); //$NON-NLS-1$
if (comparatorLogLocation != null && comparatorID != null)
comparatorLog = getLog(comparatorLogLocation, comparatorID);
}
public IStatus run(IProgressMonitor monitor) throws ProvisionException {
IStatus mirrorStatus = Status.OK_STATUS;
try {
initializeRepos(new NullProgressMonitor());
initializeLogs();
validate();
initializeIUs();
IQueryable<IInstallableUnit> slice = slice(new NullProgressMonitor());
if (destinationArtifactRepository != null) {
mirrorStatus = mirrorArtifacts(slice, new NullProgressMonitor());
if (failOnError && mirrorStatus.getSeverity() == IStatus.ERROR)
return mirrorStatus;
}
if (destinationMetadataRepository != null)
mirrorMetadata(slice, new NullProgressMonitor());
} finally {
finalizeRepositories();
finalizeLogs();
}
if (mirrorStatus.isOK())
return Status.OK_STATUS;
return mirrorStatus;
}
private IStatus mirrorArtifacts(IQueryable<IInstallableUnit> slice, IProgressMonitor monitor) {
// Obtain ArtifactKeys from IUs
IQueryResult<IInstallableUnit> ius = slice.query(QueryUtil.createIUAnyQuery(), monitor);
ArrayList<IArtifactKey> keys = new ArrayList<IArtifactKey>();
for (Iterator<IInstallableUnit> iterator = ius.iterator(); iterator.hasNext();) {
IInstallableUnit iu = iterator.next();
keys.addAll(iu.getArtifacts());
}
Mirroring mirror = new Mirroring(getCompositeArtifactRepository(), destinationArtifactRepository, raw);
mirror.setCompare(compare);
mirror.setComparatorId(comparatorID);
mirror.setBaseline(initializeBaseline());
mirror.setValidate(validate);
mirror.setCompareExclusions(compareExclusions);
mirror.setTransport((Transport) agent.getService(Transport.SERVICE_NAME));
// If IUs have been specified then only they should be mirrored, otherwise mirror everything.
if (keys.size() > 0)
mirror.setArtifactKeys(keys.toArray(new IArtifactKey[keys.size()]));
if (comparatorLog != null)
mirror.setComparatorLog(comparatorLog);
IStatus result = mirror.run(failOnError, verbose);
if (mirrorLog != null)
mirrorLog.log(result);
else
LogHelper.log(result);
return result;
}
private IArtifactRepository initializeBaseline() {
if (baseline == null)
return null;
try {
return addRepository(getArtifactRepositoryManager(), baseline, 0, null);
} catch (ProvisionException e) {
if (mirrorLog != null && e.getStatus() != null)
mirrorLog.log(e.getStatus());
return null;
}
}
private void mirrorMetadata(IQueryable<IInstallableUnit> slice, IProgressMonitor monitor) {
IQueryResult<IInstallableUnit> allIUs = slice.query(QueryUtil.createIUAnyQuery(), monitor);
destinationMetadataRepository.addInstallableUnits(allIUs.toUnmodifiableSet());
if (mirrorReferences)
destinationMetadataRepository.addReferences(getCompositeMetadataRepository().getReferences());
}
/*
* Ensure all mandatory parameters have been set. Throw an exception if there
* are any missing. We don't require the user to specify the artifact repository here,
* we will default to the ones already registered in the manager. (callers are free
* to add more if they wish)
*/
private void validate() throws ProvisionException {
if (sourceRepositories.isEmpty())
throw new ProvisionException(Messages.MirrorApplication_set_source_repositories);
if (!hasArtifactSources() && destinationArtifactRepository != null)
throw new ProvisionException(Messages.MirrorApplication_artifactDestinationNoSource);
if (!hasMetadataSources() && destinationMetadataRepository != null)
throw new ProvisionException(Messages.MirrorApplication_metadataDestinationNoSource);
}
/*
* If no IUs have been specified we want to mirror them all
*/
private void initializeIUs() throws ProvisionException {
IMetadataRepository metadataRepo = getCompositeMetadataRepository();
if (rootIUs != null) {
sourceIUs = new ArrayList<IInstallableUnit>();
for (int i = 0; i < rootIUs.length; i++) {
String[] segments = getArrayArgsFromString(rootIUs[i], "/"); //$NON-NLS-1$
VersionRange range = segments.length > 1 ? new VersionRange(segments[1]) : null;
Iterator<IInstallableUnit> queryResult = metadataRepo.query(QueryUtil.createIUQuery(segments[0], range), null).iterator();
while (queryResult.hasNext())
sourceIUs.add(queryResult.next());
}
} else if (sourceIUs == null || sourceIUs.isEmpty()) {
sourceIUs = new ArrayList<IInstallableUnit>();
Iterator<IInstallableUnit> queryResult = metadataRepo.query(QueryUtil.createIUAnyQuery(), null).iterator();
while (queryResult.hasNext())
sourceIUs.add(queryResult.next());
/* old metadata mirroring app did not throw an exception here */
if (sourceIUs.size() == 0 && destinationMetadataRepository != null && metadataOrArtifacts == null)
throw new ProvisionException(Messages.MirrorApplication_no_IUs);
}
}
/*
* Initialize logs, if applicable
*/
private void initializeLogs() {
if (compare && comparatorLogFile != null)
comparatorLog = getLog(comparatorLogFile, comparatorID);
if (mirrorLog == null && mirrorLogFile != null)
mirrorLog = getLog(mirrorLogFile, LOG_ROOT);
}
/*
* Finalize logs, if applicable
*/
private void finalizeLogs() {
if (comparatorLog != null)
comparatorLog.close();
if (mirrorLog != null)
mirrorLog.close();
}
/*
* Get the log for a location
*/
private IArtifactMirrorLog getLog(File location, String root) {
String absolutePath = location.getAbsolutePath();
if (absolutePath.toLowerCase().endsWith(".xml")) //$NON-NLS-1$
return new XMLMirrorLog(absolutePath, 0, root);
return new FileMirrorLog(absolutePath, 0, root);
}
private IQueryable<IInstallableUnit> performResolution(IProgressMonitor monitor) throws ProvisionException {
IProfileRegistry registry = Activator.getProfileRegistry();
String profileId = "MirrorApplication-" + System.currentTimeMillis(); //$NON-NLS-1$
IProfile profile = registry.addProfile(profileId, slicingOptions.getFilter());
IPlanner planner = (IPlanner) Activator.getAgent().getService(IPlanner.SERVICE_NAME);
if (planner == null)
throw new IllegalStateException();
IProfileChangeRequest pcr = planner.createChangeRequest(profile);
pcr.addAll(sourceIUs);
IProvisioningPlan plan = planner.getProvisioningPlan(pcr, null, monitor);
registry.removeProfile(profileId);
@SuppressWarnings("unchecked")
IQueryable<IInstallableUnit>[] arr = new IQueryable[plan.getInstallerPlan() == null ? 1 : 2];
arr[0] = plan.getAdditions();
if (plan.getInstallerPlan() != null)
arr[1] = plan.getInstallerPlan().getAdditions();
return new CompoundQueryable<IInstallableUnit>(arr);
}
private IQueryable<IInstallableUnit> slice(IProgressMonitor monitor) throws ProvisionException {
if (slicingOptions == null)
slicingOptions = new SlicingOptions();
if (slicingOptions.getInstallTimeLikeResolution())
return performResolution(monitor);
PermissiveSlicer slicer = new PermissiveSlicer(getCompositeMetadataRepository(), slicingOptions.getFilter(), slicingOptions.includeOptionalDependencies(), slicingOptions.isEverythingGreedy(), slicingOptions.forceFilterTo(), slicingOptions.considerStrictDependencyOnly(), slicingOptions.followOnlyFilteredRequirements());
IQueryable<IInstallableUnit> slice = slicer.slice(sourceIUs.toArray(new IInstallableUnit[sourceIUs.size()]), monitor);
if (slice != null && slicingOptions.latestVersionOnly()) {
IQueryResult<IInstallableUnit> queryResult = slice.query(QueryUtil.createLatestIUQuery(), monitor);
slice = queryResult;
}
if (slicer.getStatus().getSeverity() != IStatus.OK && mirrorLog != null) {
mirrorLog.log(slicer.getStatus());
}
if (slice == null) {
throw new ProvisionException(slicer.getStatus());
}
return slice;
}
public void setSlicingOptions(SlicingOptions options) {
slicingOptions = options;
}
/*
* Set the location of the baseline repository. (used in comparison)
*/
public void setBaseline(URI baseline) {
this.baseline = baseline;
compare = true;
}
/*
* Set the identifier of the comparator to use.
*/
public void setComparatorID(String value) {
comparatorID = value;
compare = true;
}
/*
* Set whether or not the application should be calling a comparator when mirroring.
*/
public void setCompare(boolean value) {
compare = value;
}
/*
* Set whether or not we should ignore errors when running the mirror application.
*/
public void setIgnoreErrors(boolean value) {
failOnError = !value;
}
/*
* Set whether or not the the artifacts are raw.
*/
public void setRaw(boolean value) {
raw = value;
}
/*
* Set whether or not the mirror application should be run in verbose mode.
*/
public void setVerbose(boolean value) {
verbose = value;
}
/*
* Set the location of the log for comparator output
*/
public void setComparatorLog(File comparatorLog) {
this.comparatorLogFile = comparatorLog;
}
/*
* Set the location of the log for mirroring.
*/
public void setLog(File mirrorLog) {
this.mirrorLogFile = mirrorLog;
}
/*
* Set the ArtifactMirror log
*/
public void setLog(IArtifactMirrorLog log) {
mirrorLog = log;
}
/*
* Set if the artifact mirror should be validated
*/
public void setValidate(boolean value) {
validate = value;
}
/*
* Set if references should be mirrored
*/
public void setReferences(boolean flag) {
mirrorReferences = flag;
}
public void setComparatorExclusions(IQuery<IArtifactDescriptor> exclusions) {
compareExclusions = exclusions;
}
}