Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: afa04ed1c0fee058bec34662741927799250b421 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*******************************************************************************
 * 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;
	}
}

Back to the top