]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.project/src/org/simantics/project/management/install/InstallUpdateProductOperation.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.project / src / org / simantics / project / management / install / InstallUpdateProductOperation.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *     Code 9 - ongoing development
11  *     Sonatype, Inc. - ongoing development
12  *******************************************************************************/
13 package org.simantics.project.management.install;
14
15 import java.net.URI;
16 import java.util.ArrayList;
17 import java.util.Collection;
18 import java.util.HashMap;
19 import java.util.Iterator;
20 import java.util.Map;
21
22 import org.eclipse.core.runtime.CoreException;
23 import org.eclipse.core.runtime.IPath;
24 import org.eclipse.core.runtime.IProgressMonitor;
25 import org.eclipse.core.runtime.IStatus;
26 import org.eclipse.core.runtime.Status;
27 import org.eclipse.core.runtime.SubMonitor;
28 import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper;
29 import org.eclipse.equinox.internal.p2.director.ProfileChangeRequest;
30 import org.eclipse.equinox.internal.provisional.p2.director.IDirector;
31 import org.eclipse.equinox.internal.provisional.p2.installer.IInstallOperation;
32 import org.eclipse.equinox.internal.provisional.p2.installer.InstallDescription;
33 import org.eclipse.equinox.p2.core.IProvisioningAgent;
34 import org.eclipse.equinox.p2.core.ProvisionException;
35 import org.eclipse.equinox.p2.engine.IProfile;
36 import org.eclipse.equinox.p2.engine.IProfileRegistry;
37 import org.eclipse.equinox.p2.metadata.IInstallableUnit;
38 import org.eclipse.equinox.p2.metadata.IVersionedId;
39 import org.eclipse.equinox.p2.metadata.Version;
40 import org.eclipse.equinox.p2.metadata.VersionRange;
41 import org.eclipse.equinox.p2.query.IQuery;
42 import org.eclipse.equinox.p2.query.IQueryResult;
43 import org.eclipse.equinox.p2.query.QueryUtil;
44 import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager;
45 import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
46 import org.eclipse.osgi.service.environment.EnvironmentInfo;
47 import org.eclipse.osgi.util.NLS;
48 import org.simantics.project.internal.Activator;
49
50 /**
51  * This operation performs installation or update of an Eclipse-based product.
52  */
53 @SuppressWarnings("restriction")
54 public class InstallUpdateProductOperation implements IInstallOperation {
55
56         private IArtifactRepositoryManager artifactRepoMan;
57         private IProvisioningAgent agent;
58         private IDirector director;
59         private final InstallDescription installDescription;
60         private boolean isInstall = true;
61         private IMetadataRepositoryManager metadataRepoMan;
62         private IProfileRegistry profileRegistry;
63         private IStatus result;
64
65         public InstallUpdateProductOperation(IProvisioningAgent agent, InstallDescription description) {
66                 this.agent = agent;
67                 this.installDescription = description;
68         }
69
70         /**
71          * Determine what top level installable units should be installed by the director
72          */
73         private Collection<IInstallableUnit> computeUnitsToInstall() throws CoreException {
74                 ArrayList<IInstallableUnit> units = new ArrayList<IInstallableUnit>();
75                 IVersionedId roots[] = installDescription.getRoots();
76                 for (int i = 0; i < roots.length; i++) {
77                         IVersionedId root = roots[i];
78                         IInstallableUnit iu = findUnit(root);
79                         if (iu != null)
80                                 units.add(iu);
81                 }
82                 return units;
83         }
84
85         /**
86          * This profile is being updated; return the units to uninstall from the profile.
87          */
88         private IQueryResult<IInstallableUnit> computeUnitsToUninstall(IProfile p) {
89                 return p.query(QueryUtil.createIUAnyQuery(), null);
90         }
91
92         /**
93          * Create and return the profile into which units will be installed.
94          */
95         private IProfile createProfile() throws ProvisionException {
96                 IProfile profile = getProfile();
97                 if (profile == null) {
98                         Map<String, String> properties = new HashMap<String, String>();
99                         properties.put(IProfile.PROP_INSTALL_FOLDER, installDescription.getInstallLocation().toString());
100                         EnvironmentInfo info = (EnvironmentInfo) ServiceHelper.getService(Activator.getDefault().getBundle().getBundleContext(), EnvironmentInfo.class.getName());
101                         String env = "osgi.os=" + info.getOS() + ",osgi.ws=" + info.getWS() + ",osgi.arch=" + info.getOSArch(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
102                         properties.put(IProfile.PROP_ENVIRONMENTS, env);
103                         properties.put(IProfile.PROP_NAME, installDescription.getProductName());
104                         properties.putAll(installDescription.getProfileProperties());
105                         IPath location = installDescription.getBundleLocation();
106                         if (location != null)
107                                 properties.put(IProfile.PROP_CACHE, location.toOSString());
108                         profile = profileRegistry.addProfile(getProfileId(), properties);
109                 }
110                 return profile;
111         }
112
113         /**
114          * Performs the actual product install or update.
115          */
116         private void doInstall(SubMonitor monitor) throws CoreException {
117                 prepareMetadataRepositories();
118                 prepareArtifactRepositories();
119                 IProfile p = createProfile();
120                 Collection<IInstallableUnit> toInstall = computeUnitsToInstall();
121                 monitor.worked(5);
122
123                 IStatus s;
124                 ProfileChangeRequest request = new ProfileChangeRequest(p);
125                 if (isInstall) {
126                         monitor.setTaskName(NLS.bind("Installing", installDescription.getProductName()));
127                         request.addAll(toInstall);
128                         s = director.provision(request, null, monitor.newChild(90));
129                 } else {
130                         monitor.setTaskName(NLS.bind("Updating", installDescription.getProductName()));
131                         IQueryResult<IInstallableUnit> toUninstall = computeUnitsToUninstall(p);
132                         request.removeAll(toUninstall.toUnmodifiableSet());
133                         request.addAll(toInstall);
134                         s = director.provision(request, null, monitor.newChild(90));
135                 }
136                 if (!s.isOK())
137                         throw new CoreException(s);
138         }
139
140         /**
141          * Returns an exception of severity error with the given error message.
142          */
143         private CoreException fail(String message) {
144                 return fail(message, null);
145         }
146
147         /**
148          * Returns an exception of severity error with the given error message.
149          */
150         private CoreException fail(String message, Throwable throwable) {
151                 return new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, message, throwable));
152         }
153
154         /**
155          * Finds and returns the installable unit with the given id, and optionally the
156          * given version.
157          */
158         private IInstallableUnit findUnit(IVersionedId spec) throws CoreException {
159                 String id = spec.getId();
160                 if (id == null)
161                         throw fail("No id");
162                 Version version = spec.getVersion();
163                 VersionRange range = VersionRange.emptyRange;
164                 if (version != null && !version.equals(Version.emptyVersion))
165                         range = new VersionRange(version, true, version, true);
166                 IQuery<IInstallableUnit> query = QueryUtil.createIUQuery(id, range);
167                 Iterator<IInstallableUnit> matches = metadataRepoMan.query(query, null).iterator();
168                 // pick the newest match
169                 IInstallableUnit newest = null;
170                 while (matches.hasNext()) {
171                         IInstallableUnit candidate = matches.next();
172                         if (newest == null || (newest.getVersion().compareTo(candidate.getVersion()) < 0))
173                                 newest = candidate;
174                 }
175                 if (newest == null)
176                         throw fail("IU not found " + id);
177                 return newest;
178         }
179
180         /**
181          * Returns the profile being installed into.
182          */
183         private IProfile getProfile() {
184                 return profileRegistry.getProfile(getProfileId());
185         }
186
187         /**
188          * Returns the id of the profile to use for install/update based on this operation's install description.
189          */
190         private String getProfileId() {
191                 IPath location = installDescription.getInstallLocation();
192                 if (location != null)
193                         return location.toString();
194                 return installDescription.getProductName();
195         }
196
197         /**
198          * Returns the result of the install operation, or <code>null</code> if
199          * no install operation has been run.
200          */
201         public IStatus getResult() {
202                 return result;
203         }
204
205         private Object getService(String name) throws CoreException {
206                 Object service = agent.getService(name);
207                 if (service == null)
208                         throw fail("No service "  + name);
209                 return service;
210         }
211
212         /* (non-Javadoc)
213          * @see org.eclipse.equinox.internal.provisional.p2.installer.IInstallOperation#install(org.eclipse.core.runtime.IProgressMonitor)
214          */
215         public IStatus install(IProgressMonitor pm) {
216                 SubMonitor monitor = SubMonitor.convert(pm, "Preparing", 100);
217                 try {
218                         try {
219                                 preInstall();
220                                 isInstall = getProfile() == null;
221                                 doInstall(monitor);
222                                 result = new Status(IStatus.OK, Activator.PLUGIN_ID, isInstall ? "Install Complete" : "Update Complete", null);
223                                 monitor.setTaskName("Cleanup");
224                         } finally {
225                                 postInstall();
226                         }
227                 } catch (CoreException e) {
228                         result = e.getStatus();
229                 } finally {
230                         monitor.done();
231                 }
232                 return result;
233         }
234
235         /**
236          * Returns whether this operation represents the product being installed
237          * for the first time, in a new profile.
238          */
239         public boolean isFirstInstall() {
240                 return isInstall;
241         }
242
243         private void postInstall() {
244                 //nothing to do
245         }
246
247         private void preInstall() throws CoreException {
248                 //obtain required services
249                 director = (IDirector) getService(IDirector.SERVICE_NAME);
250                 metadataRepoMan = (IMetadataRepositoryManager) getService(IMetadataRepositoryManager.SERVICE_NAME);
251                 artifactRepoMan = (IArtifactRepositoryManager) getService(IArtifactRepositoryManager.SERVICE_NAME);
252                 profileRegistry = (IProfileRegistry) getService(IProfileRegistry.SERVICE_NAME);
253         }
254
255         private void prepareArtifactRepositories() throws ProvisionException {
256                 URI[] repos = installDescription.getArtifactRepositories();
257                 if (repos == null)
258                         return;
259
260                 // Repositories must be registered before they are loaded
261                 // This is to avoid them being possibly overridden with the configuration as a referenced repository
262                 for (int i = 0; i < repos.length; i++) {
263                         artifactRepoMan.addRepository(repos[i]);
264                         artifactRepoMan.loadRepository(repos[i], null);
265                 }
266         }
267
268         private void prepareMetadataRepositories() throws ProvisionException {
269                 URI[] repos = installDescription.getMetadataRepositories();
270                 if (repos == null)
271                         return;
272
273                 // Repositories must be registered before they are loaded
274                 // This is to avoid them being possibly overridden with the configuration as a referenced repository
275                 for (int i = 0; i < repos.length; i++) {
276                         metadataRepoMan.addRepository(repos[i]);
277                         metadataRepoMan.loadRepository(repos[i], null);
278                 }
279         }
280 }