blob: afa04ed1c0fee058bec34662741927799250b421 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2018 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.equinox.internal.p2.touchpoint.eclipse;
import java.io.File;
import java.util.*;
import org.eclipse.equinox.frameworkadmin.BundleInfo;
import org.eclipse.equinox.internal.p2.garbagecollector.MarkSet;
import org.eclipse.equinox.internal.p2.garbagecollector.MarkSetProvider;
import org.eclipse.equinox.internal.p2.update.*;
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.engine.IProfileRegistry;
import org.eclipse.equinox.p2.metadata.*;
import org.eclipse.equinox.p2.query.IQueryResult;
import org.eclipse.equinox.p2.query.QueryUtil;
import org.eclipse.equinox.p2.repository.artifact.ArtifactKeyQuery;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository;
/**
* MarkSetProvider implementation for the Eclipse touchpoint.
*/
public class EclipseMarkSetProvider extends MarkSetProvider {
private static final String ARTIFACT_CLASSIFIER_OSGI_BUNDLE = "osgi.bundle"; //$NON-NLS-1$
private static final String ARTIFACT_CLASSIFIER_FEATURE = "org.eclipse.update.feature"; //$NON-NLS-1$
private Collection<IArtifactKey> artifactKeyList = null;
@Override
public MarkSet[] getMarkSets(IProvisioningAgent agent, IProfile inProfile) {
artifactKeyList = new HashSet<>();
IArtifactRepository repositoryToGC = Util.getBundlePoolRepository(agent, inProfile);
if (repositoryToGC == null)
return new MarkSet[0];
addArtifactKeys(inProfile);
IProfile currentProfile = getCurrentProfile(agent);
if (currentProfile != null && inProfile.getProfileId().equals(currentProfile.getProfileId())) {
addRunningBundles(repositoryToGC);
addRunningFeatures(inProfile, repositoryToGC);
}
return new MarkSet[] {
new MarkSet(artifactKeyList.toArray(new IArtifactKey[artifactKeyList.size()]), repositoryToGC) };
}
private void addRunningFeatures(IProfile profile, IArtifactRepository repositoryToGC) {
try {
List<Feature> allFeatures = getAllFeatures(Configuration
.load(new File(Util.getConfigurationFolder(profile), "org.eclipse.update/platform.xml"), null)); //$NON-NLS-1$
for (Feature f : allFeatures) {
IArtifactKey match = searchArtifact(f.getId(), Version.create(f.getVersion()),
ARTIFACT_CLASSIFIER_FEATURE, repositoryToGC);
if (match != null)
artifactKeyList.add(match);
}
} catch (ProvisionException e) {
// Ignore the exception
}
}
private static List<Feature> getAllFeatures(Configuration cfg) {
if (cfg == null)
return Collections.emptyList();
List<Site> sites = cfg.getSites();
ArrayList<Feature> result = new ArrayList<>();
for (Site object : sites) {
Feature[] features = object.getFeatures();
for (int i = 0; i < features.length; i++) {
result.add(features[i]);
}
}
return result;
}
private static IProfile getCurrentProfile(IProvisioningAgent agent) {
IProfileRegistry pr = agent.getService(IProfileRegistry.class);
if (pr == null)
return null;
return pr.getProfile(IProfileRegistry.SELF);
}
private void addArtifactKeys(IProfile aProfile) {
Iterator<IInstallableUnit> installableUnits = aProfile.query(QueryUtil.createIUAnyQuery(), null).iterator();
while (installableUnits.hasNext()) {
Collection<IArtifactKey> keys = installableUnits.next().getArtifacts();
if (keys == null)
continue;
artifactKeyList.addAll(keys);
}
}
@Override
public IArtifactRepository getRepository(IProvisioningAgent agent, IProfile aProfile) {
return Util.getBundlePoolRepository(agent, aProfile);
}
private void addRunningBundles(IArtifactRepository repo) {
artifactKeyList.addAll(findCorrespondinArtifacts(new WhatIsRunning().getBundlesBeingRun(), repo));
}
private static IArtifactKey searchArtifact(String searchedId, Version searchedVersion, String classifier,
IArtifactRepository repo) {
// This is somewhat cheating since normally we should get the artifact key from
// the IUs that were representing the running system (e.g. we could get that
// info from the rollback repo)
VersionRange range = searchedVersion != null ? new VersionRange(searchedVersion, true, searchedVersion, true)
: null;
ArtifactKeyQuery query = new ArtifactKeyQuery(classifier, searchedId, range);
// TODO short-circuit the query when we find one?
IQueryResult<IArtifactKey> keys = repo.query(query, null);
if (!keys.isEmpty())
return keys.iterator().next();
return null;
}
// Find for each bundle info a corresponding artifact in repo
private static List<IArtifactKey> findCorrespondinArtifacts(BundleInfo[] bis, IArtifactRepository repo) {
ArrayList<IArtifactKey> toRetain = new ArrayList<>();
for (int i = 0; i < bis.length; i++) {
// if version is "0.0.0", we will use null to find all versions, see bug 305710
Version version = BundleInfo.EMPTY_VERSION.equals(bis[i].getVersion()) ? null
: Version.create(bis[i].getVersion());
IArtifactKey match = searchArtifact(bis[i].getSymbolicName(), version, ARTIFACT_CLASSIFIER_OSGI_BUNDLE,
repo);
if (match != null)
toRetain.add(match);
}
return toRetain;
}
}