Skip to main content
summaryrefslogtreecommitdiffstats
blob: c016de25b6e947d01b12429d5bd6e26307a0ecf7 (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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/*******************************************************************************
 *  Copyright (c) 2011 Sonatype, Inc. 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:
 *     Sonatype, Inc. - initial API and implementation
 *     IBM Corporation - Ongoing development
 *******************************************************************************/
package org.eclipse.equinox.p2.operations;

import java.net.URI;
import java.util.*;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.p2.operations.Activator;
import org.eclipse.equinox.internal.p2.operations.Messages;
import org.eclipse.equinox.p2.core.IProvisioningAgent;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.equinox.p2.engine.*;
import org.eclipse.equinox.p2.engine.query.UserVisibleRootQuery;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.metadata.IVersionedId;
import org.eclipse.equinox.p2.query.*;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;

/**
 * OperationFactory provides a set of helpers to simplify dealing with the running installation.
 * Among other things, it simplifies the installation, un-installation and update.
 * If the system you are trying to modify is not the running one, you need to directly use the various subclass of {@link ProfileChangeOperation}.
 * @since 2.1  
 */
public class OperationFactory {

	private IProvisioningAgent getAgent() {
		Collection<ServiceReference<IProvisioningAgent>> ref = null;
		try {
			ref = Activator.getContext().getServiceReferences(IProvisioningAgent.class, '(' + IProvisioningAgent.SERVICE_CURRENT + '=' + Boolean.TRUE.toString() + ')');
		} catch (InvalidSyntaxException e) {
			//ignore can't happen since we write the filter ourselves
		}
		if (ref == null || ref.size() == 0)
			throw new IllegalStateException(Messages.OperationFactory_noAgent);
		IProvisioningAgent agent = Activator.getContext().getService(ref.iterator().next());
		Activator.getContext().ungetService(ref.iterator().next());
		return agent;
	}

	//Return a list of IUs from the list of versionedIDs originally provided
	private Collection<IInstallableUnit> gatherIUs(IQueryable<IInstallableUnit> searchContext, Collection<? extends IVersionedId> ius, boolean checkIUs, IProgressMonitor monitor) throws ProvisionException {
		Collection<IInstallableUnit> gatheredIUs = new ArrayList<IInstallableUnit>(ius.size());

		for (IVersionedId versionedId : ius) {
			if (!checkIUs && versionedId instanceof IInstallableUnit) {
				gatheredIUs.add((IInstallableUnit) versionedId);
				continue;
			}

			IQuery<IInstallableUnit> installableUnits = QueryUtil.createIUQuery(versionedId.getId(), versionedId.getVersion());
			IQueryResult<IInstallableUnit> matches = searchContext.query(installableUnits, monitor);
			if (matches.isEmpty())
				throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, NLS.bind(Messages.OperationFactory_noIUFound, versionedId)));

			//Add the first IU
			Iterator<IInstallableUnit> iuIt = matches.iterator();
			gatheredIUs.add(iuIt.next());
		}
		return gatheredIUs;
	}

	private ProvisioningContext createProvisioningContext(Collection<URI> repos, IProvisioningAgent agent) {
		ProvisioningContext ctx = new ProvisioningContext(agent);
		if (repos != null) {
			ctx.setMetadataRepositories(repos.toArray(new URI[repos.size()]));
			ctx.setArtifactRepositories(repos.toArray(new URI[repos.size()]));
		}
		return ctx;
	}

	/**
	 * This factory method creates an {@link InstallOperation} to install all the elements listed from the specified repositories. 
	 * @param toInstall the elements to install. This can not be null.
	 * @param repos the repositories to install the elements from. If null is passed, it will use all previously registered repositories.
	 * @param monitor the progress monitor
	 * @return an operation to install
	 */
	public InstallOperation createInstallOperation(Collection<? extends IVersionedId> toInstall, Collection<URI> repos, IProgressMonitor monitor) throws ProvisionException {
		Assert.isNotNull(toInstall);
		IProvisioningAgent agent = getAgent();

		//add the repos
		ProvisioningContext ctx = createProvisioningContext(repos, agent);

		//find the ius to install and create the operation
		InstallOperation resultingOperation = new InstallOperation(new ProvisioningSession(agent), gatherIUs(ctx.getMetadata(monitor), toInstall, false, monitor));
		resultingOperation.setProvisioningContext(ctx);
		resultingOperation.setProfileId(IProfileRegistry.SELF);

		return resultingOperation;
	}

	/**
	 * Create an {@link UninstallOperation} that will uninstall the listed elements from the running instance. 
	 * @param toUninstall the elements to uninstall. This can not be null.
	 * @param repos the repositories to install the elements from. If null is passed, it will use all previously registered repositories. 
	 * @param monitor the progress monitor
	 * @return an operation to uninstall
	 */
	public UninstallOperation createUninstallOperation(Collection<? extends IVersionedId> toUninstall, Collection<URI> repos, IProgressMonitor monitor) throws ProvisionException {
		Assert.isNotNull(toUninstall);
		IProvisioningAgent agent = getAgent();
		ProvisioningContext ctx = createProvisioningContext(repos, agent);

		//find the ius to uninstall and create the operation
		UninstallOperation resultingOperation = new UninstallOperation(new ProvisioningSession(agent), gatherIUs(listInstalledElements(false, monitor), toUninstall, true, monitor));
		resultingOperation.setProvisioningContext(ctx);
		resultingOperation.setProfileId(IProfileRegistry.SELF);

		return resultingOperation;
	}

	/**
	 * Returns the {@link IInstallableUnit}s that are installed in the running instance of Eclipse.
	 *
	 * @param rootsOnly set to true to return only the elements that have been explicitly installed (aka roots).
	 * @param monitor the progress monitor
	 * @return the installable units installed, or an empty result if the installation profile of the running system
	 *     cannot be accessed
	 */
	public IQueryResult<IInstallableUnit> listInstalledElements(boolean rootsOnly, IProgressMonitor monitor) {
		IProfileRegistry registry = (IProfileRegistry) getAgent().getService(IProfileRegistry.SERVICE_NAME);
		IProfile profile = registry.getProfile(IProfileRegistry.SELF);
		if (profile == null)
			return new CollectionResult<IInstallableUnit>(null);
		if (rootsOnly)
			return profile.query(new UserVisibleRootQuery(), monitor);
		return profile.query(QueryUtil.ALL_UNITS, monitor);
	}

	/**
	 * Create an {@link UpdateOperation} that will update the elements specified.
	 * @param toUpdate The elements to update.Passing null will result in looking for an update to all the installed. Note that you can pass the results of {@link OperationFactory#listInstalledElements(boolean, IProgressMonitor)} to this 
	 * method if you wish to update all elements installed in the running instance of eclipse.
	 * @param repos the repositories to update the elements from. If null is passed, it will use all previously registered repositories.
	 * @param monitor the progress monitor
	 * @return an instance of {@link UpdateOperation}
	 */
	public UpdateOperation createUpdateOperation(Collection<? extends IVersionedId> toUpdate, Collection<URI> repos, IProgressMonitor monitor) throws ProvisionException {
		IProvisioningAgent agent = getAgent();
		ProvisioningContext ctx = createProvisioningContext(repos, agent);

		//find the ius to update and create the operation
		UpdateOperation resultingOperation = new UpdateOperation(new ProvisioningSession(agent), toUpdate == null ? null : gatherIUs(listInstalledElements(false, monitor), toUpdate, false, monitor));
		resultingOperation.setProvisioningContext(ctx);
		resultingOperation.setProfileId(IProfileRegistry.SELF);

		return resultingOperation;
	}

	/**
	 * This factory method creates an {@link SynchronizeOperation} that will cause the current installation to exclusively contain the elements listed once executed.
	 * @param toInstall the elements to install. This can not be null.
	 * @param repos the repositories to install the elements from. If null is passed, it will use all previously registered repositories.
	 * @param monitor the progress monitor
	 * @return an instance of {@link SynchronizeOperation}.
	 */
	public SynchronizeOperation createSynchronizeOperation(Collection<? extends IVersionedId> toInstall, Collection<URI> repos, IProgressMonitor monitor) throws ProvisionException {
		IProvisioningAgent agent = getAgent();
		ProvisioningContext ctx = createProvisioningContext(repos, agent);

		Collection<IInstallableUnit> iusToInstall;
		if (toInstall == null)
			iusToInstall = ctx.getMetadata(monitor).query(QueryUtil.createIUGroupQuery(), monitor).toUnmodifiableSet();
		else
			iusToInstall = gatherIUs(ctx.getMetadata(monitor), toInstall, false, monitor);

		SynchronizeOperation resultingOperation = new SynchronizeOperation(new ProvisioningSession(agent), iusToInstall);
		resultingOperation.setProvisioningContext(ctx);
		resultingOperation.setProfileId(IProfileRegistry.SELF);

		return resultingOperation;
	}
}

Back to the top