blob: 01a9a98cf7757456eb6e42cbd72160c958e20283 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2015 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.internal.p2.engine;
import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
import org.eclipse.equinox.internal.provisional.p2.core.eventbus.IProvisioningEventBus;
import org.eclipse.equinox.internal.provisional.p2.repository.RepositoryEvent;
import org.eclipse.equinox.p2.core.IProvisioningAgent;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.equinox.p2.engine.IProfile;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.query.IQuery;
import org.eclipse.equinox.p2.query.IQueryResult;
import org.eclipse.equinox.p2.repository.IRepository;
import org.eclipse.equinox.p2.repository.IRepositoryReference;
import org.eclipse.equinox.p2.repository.metadata.spi.AbstractMetadataRepository;
import org.eclipse.equinox.p2.repository.spi.RepositoryReference;
import org.eclipse.osgi.util.NLS;
public class ProfileMetadataRepository extends AbstractMetadataRepository {
private static final String DEFAULT_ARTIFACT_REPO_DIRECTORY = "org.eclipse.equinox.p2.core/cache"; //$NON-NLS-1$
private static final String ARTIFACTS_XML = "artifacts.xml"; //$NON-NLS-1$
private static final String FILE_SCHEME = "file"; //$NON-NLS-1$
private static final String DOT_PROFILE = ".profile"; //$NON-NLS-1$
public static final String TYPE = "org.eclipse.equinox.p2.engine.repo.metadataRepository"; //$NON-NLS-1$
public static final Integer VERSION = new Integer(1);
private IProfile profile;
private HashSet<IRepositoryReference> repositories = new HashSet<IRepositoryReference>();
public ProfileMetadataRepository(IProvisioningAgent agent, URI location, IProgressMonitor monitor) throws ProvisionException {
super(agent, location.toString(), TYPE, VERSION.toString(), location, null, null, null);
try {
profile = getProfile(agent, location);
} catch (RuntimeException e) {
throw new ProvisionException(new Status(IStatus.ERROR, EngineActivator.ID, ProvisionException.REPOSITORY_FAILED_READ, e.getMessage(), e));
}
publishArtifactRepos();
}
private void publishArtifactRepos() {
List<URI> artifactRepos = findArtifactRepos();
IProvisioningEventBus bus = (IProvisioningEventBus) getProvisioningAgent().getService(IProvisioningEventBus.SERVICE_NAME);
if (bus == null)
return;
for (URI repo : artifactRepos) {
repositories.add(new RepositoryReference(repo, null, IRepository.TYPE_ARTIFACT, IRepository.ENABLED));
bus.publishEvent(new RepositoryEvent(repo, IRepository.TYPE_ARTIFACT, RepositoryEvent.DISCOVERED, true));
}
}
private List<URI> findArtifactRepos() {
List<URI> artifactRepos = new ArrayList<URI>();
File p2Directory = findP2Directory();
// Add the profile registry's default agent artifact repository.
// Currently this is used by the Native Touchpoint to store artifacts however
// other touchpoints might use this as well.
File agentArtifactRepository = findAgentArtifactRepositoryDirectory(p2Directory);
if (agentArtifactRepository != null)
artifactRepos.add(agentArtifactRepository.toURI());
// bundle pool
String bundlePool = profile.getProperty(IProfile.PROP_CACHE);
if (bundlePool != null) {
File bundlePoolFile = new File(bundlePool);
if (bundlePoolFile.exists())
artifactRepos.add(bundlePoolFile.toURI());
else if (Boolean.parseBoolean(profile.getProperty(IProfile.PROP_ROAMING))) {
// the profile has not been used yet but is a roaming profile
// best effort to add "just" the default bundle pool
bundlePoolFile = findDefaultBundlePool(p2Directory);
if (bundlePoolFile != null)
artifactRepos.add(bundlePoolFile.toURI());
return artifactRepos;
}
}
// shared bundle pool
String sharedBundlePool = profile.getProperty(IProfile.PROP_SHARED_CACHE);
if (sharedBundlePool != null)
artifactRepos.add(new File(sharedBundlePool).toURI());
// cache extensions
// Currently set exclusively by dropins
String dropinRepositories = profile.getProperty("org.eclipse.equinox.p2.cache.extensions"); //$NON-NLS-1$
if (dropinRepositories != null) {
StringTokenizer tokenizer = new StringTokenizer(dropinRepositories, "|"); //$NON-NLS-1$
while (tokenizer.hasMoreTokens()) {
String repoLocation = ""; //$NON-NLS-1$
try {
repoLocation = tokenizer.nextToken();
artifactRepos.add(new URI(repoLocation));
} catch (URISyntaxException e) {
LogHelper.log(new Status(IStatus.WARNING, EngineActivator.ID, "invalid repo reference with location: " + repoLocation, e)); //$NON-NLS-1$
}
}
}
return artifactRepos;
}
private File findAgentArtifactRepositoryDirectory(File p2Directory) {
if (p2Directory == null)
return null;
File agentArtifactRepositoryDirectory = new File(p2Directory, DEFAULT_ARTIFACT_REPO_DIRECTORY);
if (!agentArtifactRepositoryDirectory.isDirectory())
return null;
return agentArtifactRepositoryDirectory;
}
private File findDefaultBundlePool(File p2Directory) {
if (p2Directory == null)
return null;
File productDirectory = p2Directory.getParentFile();
if (productDirectory == null || !(new File(productDirectory, ARTIFACTS_XML).exists()))
return null;
return productDirectory;
}
private File findP2Directory() {
File target = new File(getLocation());
if (target.isFile())
target = target.getParentFile();
// by default the profile registry is in {product}/p2/org.eclipse.equinox.p2.engine/profileRegistry
// the default bundle pool is in the {product} folder
File profileRegistryDirectory = target.getParentFile();
if (profileRegistryDirectory == null)
return null;
File p2EngineDirectory = profileRegistryDirectory.getParentFile();
if (p2EngineDirectory == null)
return null;
return p2EngineDirectory.getParentFile();
}
public Collection<IRepositoryReference> getReferences() {
return Collections.unmodifiableCollection(repositories);
}
public void initialize(RepositoryState state) {
// nothing to do
}
public IQueryResult<IInstallableUnit> query(IQuery<IInstallableUnit> query, IProgressMonitor monitor) {
return profile.query(query, monitor);
}
private static IProfile getProfile(IProvisioningAgent agent, URI location) throws ProvisionException {
if (!FILE_SCHEME.equalsIgnoreCase(location.getScheme()))
fail(location, ProvisionException.REPOSITORY_NOT_FOUND);
File target = new File(location);
if (!target.exists())
fail(location, ProvisionException.REPOSITORY_NOT_FOUND);
long timestamp = -1;
int index = target.getName().lastIndexOf(DOT_PROFILE);
if (index == -1)
fail(location, ProvisionException.REPOSITORY_NOT_FOUND);
String profileId = target.getName().substring(0, index);
if (target.isFile()) {
try {
timestamp = Long.parseLong(profileId);
} catch (NumberFormatException e) {
fail(location, ProvisionException.REPOSITORY_FAILED_READ);
}
target = target.getParentFile();
if (target == null)
fail(location, ProvisionException.REPOSITORY_NOT_FOUND);
index = target.getName().lastIndexOf(DOT_PROFILE);
profileId = target.getName().substring(0, index);
}
profileId = SimpleProfileRegistry.unescape(profileId);
File registryDirectory = target.getParentFile();
if (registryDirectory == null)
fail(location, ProvisionException.REPOSITORY_NOT_FOUND);
SimpleProfileRegistry profileRegistry = new SimpleProfileRegistry(agent, registryDirectory, null, false);
if (timestamp == -1) {
long[] timestamps = profileRegistry.listProfileTimestamps(profileId);
timestamp = timestamps[timestamps.length - 1];
}
IProfile profile = profileRegistry.getProfile(profileId, timestamp);
if (profile == null)
fail(location, ProvisionException.REPOSITORY_NOT_FOUND);
return profile;
}
private static void fail(URI location, int code) throws ProvisionException {
switch (code) {
case ProvisionException.REPOSITORY_NOT_FOUND :
String msg = NLS.bind(Messages.io_NotFound, location);
throw new ProvisionException(new Status(IStatus.ERROR, EngineActivator.ID, ProvisionException.REPOSITORY_NOT_FOUND, msg, null));
case ProvisionException.REPOSITORY_FAILED_READ :
msg = NLS.bind(Messages.io_FailedRead, location);
throw new ProvisionException(new Status(IStatus.ERROR, EngineActivator.ID, ProvisionException.REPOSITORY_NOT_FOUND, msg, null));
}
}
}