/*******************************************************************************
* Copyright (c) 2004, 2006
* Thomas Hallgren, Kenneth Olwing, Mitch Sonies
* Pontus Rydin, Nils Unden, Peer Torngren
* The code, documentation and other materials contained herein have been
* licensed under the Eclipse Public License - v 1.0 by the individual
* copyright holders listed above, as Initial Contributors under such license.
* The text of such license is available at www.eclipse.org.
*
* Contributors:
* Lorenzo Bettini - https://bugs.eclipse.org/bugs/show_bug.cgi?id=428301
*******************************************************************************/
package org.eclipse.buckminster.core.reader;
import java.io.File;
import java.net.URI;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.buckminster.core.CorePlugin;
import org.eclipse.buckminster.core.KeyConstants;
import org.eclipse.buckminster.core.RMContext;
import org.eclipse.buckminster.core.cspec.builder.CSpecBuilder;
import org.eclipse.buckminster.core.ctype.IComponentType;
import org.eclipse.buckminster.core.helpers.MapUtils;
import org.eclipse.buckminster.core.materializer.IMaterializer;
import org.eclipse.buckminster.core.materializer.P2Materializer;
import org.eclipse.buckminster.core.metadata.MissingComponentException;
import org.eclipse.buckminster.core.metadata.model.BOMNode;
import org.eclipse.buckminster.core.metadata.model.Resolution;
import org.eclipse.buckminster.core.metadata.model.ResolvedNode;
import org.eclipse.buckminster.core.resolver.NodeQuery;
import org.eclipse.buckminster.core.rmap.model.Provider;
import org.eclipse.buckminster.core.version.ProviderMatch;
import org.eclipse.buckminster.core.version.VersionMatch;
import org.eclipse.buckminster.runtime.BuckminsterException;
import org.eclipse.buckminster.runtime.Logger;
import org.eclipse.buckminster.runtime.MonitorUtils;
import org.eclipse.buckminster.runtime.URLUtils;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.equinox.internal.p2.touchpoint.eclipse.PublisherUtil;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.equinox.p2.metadata.IArtifactKey;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.query.IQueryResult;
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.artifact.IArtifactRequest;
import org.eclipse.equinox.p2.repository.artifact.IFileArtifactRepository;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
@SuppressWarnings("restriction")
public class P2ReaderType extends CatalogReaderType {
public static final String SIMPLE_ARTIFACTS_TYPE = org.eclipse.equinox.internal.p2.artifact.repository.Activator.ID + ".simpleRepository"; //$NON-NLS-1$
public static IArtifactRepository getArtifactRepository(Provider provider, Map<String, ? extends Object> properties, IProgressMonitor monitor)
throws CoreException {
return getArtifactRepository(getURI(provider, properties), monitor);
}
public static IArtifactRepository getArtifactRepository(ProviderMatch providerMatch, IProgressMonitor monitor) throws CoreException {
return getArtifactRepository(providerMatch.getProvider(), providerMatch.getNodeQuery().getProperties(), monitor);
}
public static IArtifactRepository getArtifactRepository(URI repoLocation, IProgressMonitor monitor) throws CoreException {
IArtifactRepositoryManager manager = getArtifactRepositoryManager();
SubMonitor subMon = SubMonitor.convert(monitor, 200);
try {
return manager.loadRepository(repoLocation, subMon.newChild(100));
} catch (ProvisionException e) {
return manager.refreshRepository(repoLocation, subMon.newChild(100));
} finally {
if (monitor != null)
monitor.done();
}
}
public static IArtifactRepositoryManager getArtifactRepositoryManager() throws CoreException {
IArtifactRepositoryManager manager = (IArtifactRepositoryManager) CorePlugin.getDefault().getResolverAgent()
.getService(IArtifactRepositoryManager.SERVICE_NAME);
if (manager == null)
throw new IllegalStateException("No artifact repository manager found"); //$NON-NLS-1$
return manager;
}
public static IInstallableUnit getIU(ProviderMatch providerMatch, IProgressMonitor monitor) throws CoreException {
IMetadataRepository mdr = getMetadataRepository(providerMatch, monitor);
VersionMatch vm = providerMatch.getVersionMatch();
IQueryResult<IInstallableUnit> result = mdr.query(QueryUtil.createIUQuery(vm.getArtifactInfo(), vm.getVersion()), monitor);
return result.isEmpty() ? null : result.iterator().next();
}
public static IMetadataRepository getMetadataRepository(Provider provider, Map<String, ? extends Object> properties, IProgressMonitor monitor)
throws CoreException {
return getMetadataRepository(getURI(provider, properties), monitor);
}
public static IMetadataRepository getMetadataRepository(ProviderMatch providerMatch, IProgressMonitor monitor) throws CoreException {
return getMetadataRepository(providerMatch.getProvider(), providerMatch.getNodeQuery().getProperties(), monitor);
}
public static IMetadataRepository getMetadataRepository(URI repoLocation, IProgressMonitor monitor) throws CoreException {
IMetadataRepositoryManager manager = (IMetadataRepositoryManager) CorePlugin.getDefault().getResolverAgent()
.getService(IMetadataRepositoryManager.SERVICE_NAME);
if (manager == null)
throw new IllegalStateException("No metadata repository manager found"); //$NON-NLS-1$
SubMonitor subMon = SubMonitor.convert(monitor, 200);
try {
return manager.loadRepository(repoLocation, subMon.newChild(100));
} catch (ProvisionException e) {
return manager.refreshRepository(repoLocation, subMon.newChild(100));
} finally {
if (monitor != null)
monitor.done();
}
}
public static IFileArtifactRepository getTempAR(SubMonitor subMon) throws CoreException {
File tempRepositoryFolder = new File(CorePlugin.getDefault().getResolverAgentLocation(), "tempAr"); //$NON-NLS-1$
IArtifactRepositoryManager manager = getArtifactRepositoryManager();
URI tempRepositoryURI = tempRepositoryFolder.toURI();
IFileArtifactRepository tempAr;
try {
tempAr = (IFileArtifactRepository) manager.loadRepository(tempRepositoryURI, subMon);
} catch (ProvisionException e) {
tempAr = (IFileArtifactRepository) manager.createRepository(tempRepositoryURI,
"temporary artifacts" + " artifacts", SIMPLE_ARTIFACTS_TYPE, Collections.<String, String> emptyMap()); //$NON-NLS-1$ //$NON-NLS-2$
}
return tempAr;
}
public static URI getURI(Provider provider, Map<String, ? extends Object> properties) throws CoreException {
return P2Materializer.cleanURIFromImportType(URLUtils.normalizeToURI(provider.getURI(properties), true));
}
public P2ReaderType() {
}
@Override
public String convertFetchFactoryLocator(Map<String, Object> fetchFactoryLocator, String componentName) throws CoreException {
// This property is guaranteed to be set
return MapUtils.getString(fetchFactoryLocator, "repository"); //$NON-NLS-1$
}
@Override
public URI getArtifactURL(Resolution resolution, RMContext context) throws CoreException {
throw new UnsupportedOperationException();
}
@Override
public Map<String, String> getFetchFactoryProviderProps(Map<String, Object> properties, Provider delegee) {
Map<String, String> props = new HashMap<String, String>();
props.put(KeyConstants.IS_SOURCE, Boolean.FALSE.toString());
props.put(KeyConstants.IS_MUTABLE, Boolean.FALSE.toString());
return props;
}
@Override
public IComponentReader getReader(ProviderMatch providerMatch, IProgressMonitor monitor) throws CoreException {
throw new UnsupportedOperationException();
}
@Override
public String getRecommendedMaterializer() {
return IMaterializer.P2;
}
public BOMNode getResolution(ProviderMatch providerMatch, IProgressMonitor monitor) throws CoreException {
SubMonitor subMon = SubMonitor.convert(monitor, 20);
try {
IInstallableUnit iu = getIU(providerMatch, subMon.newChild(22));
if (iu == null)
throw new MissingComponentException(providerMatch.getNodeQuery().getComponentRequest().toString());
MonitorUtils.testCancelStatus(subMon);
if (Boolean.valueOf(iu.getProperty(IInstallableUnit.PROP_PARTIAL_IU)).booleanValue())
iu = resolvePartialIU(iu, providerMatch, subMon.newChild(10));
else
subMon.worked(10);
IMetadataRepository mdr = getMetadataRepository(providerMatch, subMon.newChild(2));
return new ResolvedNode(providerMatch.getNodeQuery(), new Resolution(providerMatch.createResolution(new CSpecBuilder(providerMatch
.getNodeQuery().getProperties(), mdr, iu), false)));
} finally {
MonitorUtils.done(monitor);
}
}
@Override
public IVersionFinder getVersionFinder(Provider provider, IComponentType ctype, NodeQuery nodeQuery, IProgressMonitor monitor)
throws CoreException {
IMetadataRepository mdr = getMetadataRepository(provider, nodeQuery.getProperties(), monitor);
return new P2VersionFinder(provider, ctype, nodeQuery, mdr);
}
IInstallableUnit resolvePartialIU(IInstallableUnit iu, ProviderMatch providerMatch, SubMonitor subMon) throws CoreException {
Logger logger = CorePlugin.getLogger();
String info = "Converting partial IU for " + iu.getId() + "..."; //$NON-NLS-1$//$NON-NLS-2$
subMon.beginTask(info, 1110);
logger.debug(info);
IArtifactRepository sourceAr = getArtifactRepository(providerMatch, subMon.newChild(100));
MonitorUtils.testCancelStatus(subMon);
Collection<IArtifactKey> artifacts = iu.getArtifacts();
IArtifactKey key = artifacts.iterator().next();
IFileArtifactRepository tempAr = getTempAR(subMon.newChild(10));
MonitorUtils.testCancelStatus(subMon);
IArtifactRequest request = getArtifactRepositoryManager().createMirrorRequest(key, tempAr, null, null);
request.perform(sourceAr, subMon.newChild(1000));
IStatus result = request.getResult();
switch (result.getSeverity()) {
case IStatus.INFO:
logger.info(result.getMessage());
case IStatus.OK:
// Unfortunately, this doesn't necessarily mean that everything
// is OK. Zero sized files are
// silently ignored. See bug 290986
// We can't have that here.
if (!tempAr.contains(key))
throw BuckminsterException.fromMessage("Zero bytes copied while mirroring partial IU artifact %s", key); //$NON-NLS-1$
break;
case IStatus.CANCEL:
throw new OperationCanceledException();
default:
if (result.getCode() == org.eclipse.equinox.p2.core.ProvisionException.ARTIFACT_EXISTS) {
logger.debug("Artifact %s is already present", key); //$NON-NLS-1$
break;
}
throw BuckminsterException.wrap(result);
}
File bundleFile = tempAr.getArtifactFile(key);
if (bundleFile == null)
throw BuckminsterException.fromMessage("Unable to resolve partial IU. Artifact file for %s could not be found", key); //$NON-NLS-1$
IInstallableUnit preparedIU = PublisherUtil.createBundleIU(key, bundleFile);
if (preparedIU == null)
throw BuckminsterException.fromMessage("Unable to resolve partial IU. Artifact file for %s did not contain a bundle manifest", key); //$NON-NLS-1$
return preparedIU;
}
}