blob: 7466229d8911df6f3eb5cad178e15248605faf5a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2009 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
* WindRiver - https://bugs.eclipse.org/bugs/show_bug.cgi?id=227372
*******************************************************************************/
package org.eclipse.equinox.p2.engine;
import java.net.URI;
import java.util.*;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.p2.engine.DebugHelper;
import org.eclipse.equinox.p2.core.IProvisioningAgent;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.equinox.p2.metadata.*;
import org.eclipse.equinox.p2.query.*;
import org.eclipse.equinox.p2.repository.IRepositoryManager;
import org.eclipse.equinox.p2.repository.artifact.*;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
/**
* A provisioning context defines the scope in which a provisioning operation
* occurs. A context can be used to specify the set of repositories available
* to the planner and engine as they perform provisioning work.
* @since 2.0
*/
public class ProvisioningContext {
private IProvisioningAgent agent;
private Collection<IRequirement> additionalRequirements;
private URI[] artifactRepositories; //artifact repositories to consult
private final List<IInstallableUnit> extraIUs = Collections.synchronizedList(new ArrayList<IInstallableUnit>());
private URI[] metadataRepositories; //metadata repositories to consult
private final Map<String, String> properties = new HashMap<String, String>();
private static final String FILE_PROTOCOL = "file"; //$NON-NLS-1$
/**
* This Comparator sorts the repositories such that local repositories are first
*/
private static final Comparator<URI> LOCAL_FIRST_COMPARATOR = new Comparator<URI>() {
public int compare(URI arg0, URI arg1) {
String protocol0 = arg0.getScheme();
String protocol1 = arg1.getScheme();
if (FILE_PROTOCOL.equals(protocol0) && !FILE_PROTOCOL.equals(protocol1))
return -1;
if (!FILE_PROTOCOL.equals(protocol0) && FILE_PROTOCOL.equals(protocol1))
return 1;
return 0;
}
};
/**
* Instructs the provisioning context to follow repository references when providing
* queryables for obtaining metadata and artifacts. When this property is set to
* "true", then both enabled and disabled repository references that are encountered
* while loading the specified metadata repositories will be included in the provisioning
* context. In this mode, the provisioning context has a distinct lifecycle, whereby
* the metadata and artifact repositories to be used are determined when the client
* retrieves the metadata queryable. Clients using this property should not reset the
* list of metadata repository locations or artifact repository locations once the
* metadata queryable has been retrieved.
*
* @see #getMetadata(IProgressMonitor)
* @see #setMetadataRepositories(URI[])
* @see #setArtifactRepositories(URI[])
*/
public static final String FOLLOW_REPOSITORY_REFERENCES = "org.eclipse.equinox.p2.director.followRepositoryReferences"; //$NON-NLS-1$
/**
* Creates a new provisioning context that includes all available metadata and
* artifact repositories available to the specified provisioning agent.
*
* @param agent the provisioning agent from which to obtain any necessary services.
*/
public ProvisioningContext(IProvisioningAgent agent) {
this.agent = agent;
// null repos means look at them all
metadataRepositories = null;
artifactRepositories = null;
}
/**
* Returns a collection of additional requirements that must be satisfied by the planner,
* or <code>null</code> if there are no additional requirements.
* This method has no effect on the execution of the engine.
*
* @return a collection of additional requirements
*/
public Collection<IRequirement> getAdditionalRequirements() {
return additionalRequirements;
}
/**
* Returns a queryable that can be used to obtain any artifact keys that
* are needed for the provisioning operation.
*
* @param monitor a progress monitor to be used when creating the queryable
* @return a queryable that can be used to query available artifact keys.
*
* @see #setArtifactRepositories(URI[])
* @see #FOLLOW_REPOSITORY_REFERENCES
*/
public IQueryable<IArtifactKey> getArtifactKeys(IProgressMonitor monitor) {
IArtifactRepositoryManager repoManager = (IArtifactRepositoryManager) agent.getService(IArtifactRepositoryManager.SERVICE_NAME);
URI[] repositories = getArtifactRepositories();
List<IArtifactRepository> repos = new ArrayList<IArtifactRepository>();
SubMonitor sub = SubMonitor.convert(monitor, repositories.length * 100);
try {
for (int i = 0; i < repositories.length; i++) {
if (sub.isCanceled())
throw new OperationCanceledException();
repos.add(repoManager.loadRepository(repositories[i], sub.newChild(100)));
}
} catch (ProvisionException e) {
//skip unreadable repositories
}
return QueryUtil.compoundQueryable(repos);
}
/**
* Returns a queryable that can be used to obtain any artifact descriptors that
* are needed for the provisioning operation.
*
* @param monitor a progress monitor to be used when creating the queryable
* @return a queryable that can be used to query available artifact descriptors.
*
* @see #setArtifactRepositories(URI[])
* @see #FOLLOW_REPOSITORY_REFERENCES
*/
public IQueryable<IArtifactDescriptor> getArtifactDescriptors(IProgressMonitor monitor) {
IArtifactRepositoryManager repoManager = (IArtifactRepositoryManager) agent.getService(IArtifactRepositoryManager.SERVICE_NAME);
URI[] repositories = getArtifactRepositories();
List<IQueryable<IArtifactDescriptor>> descriptorQueryables = new ArrayList<IQueryable<IArtifactDescriptor>>();
SubMonitor sub = SubMonitor.convert(monitor, repositories.length * 100);
try {
for (int i = 0; i < repositories.length; i++) {
if (sub.isCanceled())
throw new OperationCanceledException();
IArtifactRepository repo = repoManager.loadRepository(repositories[i], sub.newChild(100));
descriptorQueryables.add(repo.descriptorQueryable());
}
} catch (ProvisionException e) {
//skip unreadable repositories
}
return QueryUtil.compoundQueryable(descriptorQueryables);
}
/**
* Returns a queryable that can be used to obtain any artifact repositories that
* are needed for the provisioning operation.
*
* @param monitor a progress monitor to be used when creating the queryable
* @return a queryable that can be used to query available artifact repositories.
*
* @see #setArtifactRepositories(URI[])
* @see #FOLLOW_REPOSITORY_REFERENCES
*/
public IQueryable<IArtifactRepository> getArtifactRepositories(IProgressMonitor monitor) {
IArtifactRepositoryManager repoManager = (IArtifactRepositoryManager) agent.getService(IArtifactRepositoryManager.SERVICE_NAME);
URI[] repositories = getArtifactRepositories();
final List<IArtifactRepository> repos = new ArrayList<IArtifactRepository>();
SubMonitor sub = SubMonitor.convert(monitor, repositories.length * 100);
try {
for (int i = 0; i < repositories.length; i++) {
if (sub.isCanceled())
throw new OperationCanceledException();
repos.add(repoManager.loadRepository(repositories[i], sub.newChild(100)));
}
} catch (ProvisionException e) {
//skip unreadable repositories
}
return new IQueryable<IArtifactRepository>() {
public IQueryResult<IArtifactRepository> query(IQuery<IArtifactRepository> query, IProgressMonitor mon) {
return query.perform(repos.iterator());
}
};
}
/**
* Returns a queryable that can be used to obtain any metadata (installable units)
* that are needed for the provisioning operation.
*
* @param monitor a progress monitor to be used when creating the queryable
* @return a queryable that can be used to query available metadata.
*
* @see #setMetadataRepositories(URI[])
* @see #FOLLOW_REPOSITORY_REFERENCES
*/
public IQueryable<IInstallableUnit> getMetadata(IProgressMonitor monitor) {
IMetadataRepositoryManager repoManager = (IMetadataRepositoryManager) agent.getService(IMetadataRepositoryManager.SERVICE_NAME);
URI[] repositories = metadataRepositories == null ? repoManager.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL) : metadataRepositories;
List<IMetadataRepository> repos = new ArrayList<IMetadataRepository>();
SubMonitor sub = SubMonitor.convert(monitor, repositories.length * 100);
try {
for (int i = 0; i < repositories.length; i++) {
if (sub.isCanceled())
throw new OperationCanceledException();
repos.add(repoManager.loadRepository(repositories[i], sub.newChild(100)));
}
} catch (ProvisionException e) {
//skip unreadable repositories
}
return QueryUtil.compoundQueryable(repos);
}
/**
* Returns the list of additional installable units that should be considered as
* available for installation by the planner. Returns an empty list if
* there are no extra installable units to consider. This method has no effect on the
* execution of the engine.
*
* @return The extra installable units that are available
*/
public List<IInstallableUnit> getExtraInstallableUnits() {
return extraIUs;
}
/**
* Returns the properties that are defined in this context. Context properties can
* be used to influence the behavior of either the planner or engine.
*
* @return the defined provisioning context properties
*/
public Map<String, String> getProperties() {
return properties;
}
/**
* Returns the value of the property with the given key, or <code>null</code>
* if no such property is defined
* @param key the property key
* @return the property value, or <code>null</code>
*/
public String getProperty(String key) {
return properties.get(key);
}
/**
* Sets the additional requirements that must be satisfied by the planner.
* This method has no effect on the execution of the engine.
*
* @param requirements the additional requirements
*/
public void setAdditionalRequirements(Collection<IRequirement> requirements) {
additionalRequirements = requirements;
}
/**
* Sets the artifact repositories to consult when performing an operation.
* <p>
* When the {@link #FOLLOW_REPOSITORY_REFERENCES} property is set, this
* method should be called prior to calling {@link #getMetadata(IProgressMonitor)},
* because setting the repositories after retrieving metadata will have no
* effect.
*
* @param artifactRepositories the artifact repository locations
* @see #FOLLOW_REPOSITORY_REFERENCES
*/
public void setArtifactRepositories(URI[] artifactRepositories) {
this.artifactRepositories = artifactRepositories;
}
/**
* Sets the metadata repositories to consult when performing an operation.
* @param metadataRepositories the metadata repository locations
*/
public void setMetadataRepositories(URI[] metadataRepositories) {
this.metadataRepositories = metadataRepositories;
}
/**
* Sets the list of additional installable units that should be considered as
* available for installation by the planner. This method has no effect on the
* execution of the engine.
* @param extraIUs the extra installable units
*/
public void setExtraInstallableUnits(List<IInstallableUnit> extraIUs) {
this.extraIUs.clear();
//copy the list to prevent future client tampering
if (extraIUs != null)
this.extraIUs.addAll(extraIUs);
}
/**
* Sets a property on this provisioning context. Context properties can
* be used to influence the behavior of either the planner or engine.
* @param key the property key
* @param value the property value
*/
public void setProperty(String key, String value) {
properties.put(key, value);
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append("{artifactRepos=" + DebugHelper.formatArray(Arrays.asList(artifactRepositories), true, false)); //$NON-NLS-1$
buffer.append(", metadataRepos=" + DebugHelper.formatArray(Arrays.asList(metadataRepositories), true, false)); //$NON-NLS-1$
buffer.append(", properties=" + getProperties() + "}"); //$NON-NLS-1$ //$NON-NLS-2$
return buffer.toString();
}
/**
* Return the array of repository locations for artifact repositories.
* @return an array of repository locations. This is never <code>null</code>.
*
* @deprecated This method will be removed before the final release of 3.6
* @noreference This method will be removed before the final release of 3.6
* @see #getArtifactRepositories()
* @see #getArtifactDescriptors(IProgressMonitor)
* @see #getArtifactKeys(IProgressMonitor)
*/
public URI[] getArtifactRepositories() {
IArtifactRepositoryManager repoManager = (IArtifactRepositoryManager) agent.getService(IArtifactRepositoryManager.SERVICE_NAME);
URI[] repositories = artifactRepositories == null ? repoManager.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL) : artifactRepositories;
Arrays.sort(repositories, LOCAL_FIRST_COMPARATOR);
return repositories;
}
}