blob: 69dd91fb32ea3a2b5a64fcfeae3e7065f73d381f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007 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.installer;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.p2.artifact.repository.IArtifactRepositoryManager;
import org.eclipse.equinox.p2.core.helpers.ServiceHelper;
import org.eclipse.equinox.p2.director.IDirector;
import org.eclipse.equinox.p2.engine.IProfileRegistry;
import org.eclipse.equinox.p2.engine.Profile;
import org.eclipse.equinox.p2.installer.IInstallOperation;
import org.eclipse.equinox.p2.installer.InstallDescription;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.metadata.repository.IMetadataRepository;
import org.eclipse.equinox.p2.metadata.repository.IMetadataRepositoryManager;
import org.eclipse.osgi.service.environment.EnvironmentInfo;
import org.eclipse.osgi.service.resolver.VersionRange;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.*;
/**
* This operation performs installation or update of an Eclipse-based product.
*/
public class InstallUpdateProductOperation implements IInstallOperation {
/**
* This constant comes from value of FrameworkAdmin.SERVICE_PROP_KEY_LAUNCHER_NAME.
* This profile property is being used as a short term solution for branding of the launcher.
*/
private static final String PROP_LAUNCHER_NAME = "org.eclipse.equinox.frameworkhandler.launcher.name";
private IArtifactRepositoryManager artifactRepoMan;
private BundleContext bundleContext;
private IDirector director;
private final InstallDescription installDescription;
private boolean isInstall = true;
private IMetadataRepositoryManager metadataRepoMan;
private IProfileRegistry profileRegistry;
private IStatus result;
private ArrayList serviceReferences = new ArrayList();
public InstallUpdateProductOperation(BundleContext context, InstallDescription description) {
this.bundleContext = context;
this.installDescription = description;
}
/**
* Determine what top level installable units should be installed by the director
*/
private IInstallableUnit[] computeUnitsToInstall() throws CoreException {
return new IInstallableUnit[] {findUnit(installDescription.getRootId(), installDescription.getRootVersion())};
}
/**
* This profile is being updated; return the units to uninstall from the profile.
*/
private IInstallableUnit[] computeUnitsToUninstall(Profile profile) {
ArrayList units = new ArrayList();
for (Iterator it = profile.getInstallableUnits(); it.hasNext();)
units.add(it.next());
return (IInstallableUnit[]) units.toArray(new IInstallableUnit[units.size()]);
}
/**
* Create and return the profile into which units will be installed.
*/
private Profile createProfile() {
Profile profile = getProfile();
if (profile == null) {
profile = new Profile(installDescription.getProductName());
profile.setValue(Profile.PROP_INSTALL_FOLDER, installDescription.getInstallLocation().toString());
profile.setValue(Profile.PROP_FLAVOR, installDescription.getFlavor());
profile.setValue(PROP_LAUNCHER_NAME, installDescription.getLauncherName());
EnvironmentInfo info = (EnvironmentInfo) ServiceHelper.getService(InstallerActivator.getDefault().getContext(), EnvironmentInfo.class.getName());
String env = "osgi.os=" + info.getOS() + ",osgi.ws=" + info.getWS() + ",osgi.arch=" + info.getOSArch();
profile.setValue(Profile.PROP_ENVIRONMENTS, env);
profileRegistry.addProfile(profile);
}
return profile;
}
/**
* Performs the actual product install or update.
*/
private void doInstall(SubMonitor monitor) throws CoreException {
prepareMetadataRepository();
prepareArtifactRepository();
Profile p = createProfile();
IInstallableUnit[] toInstall = computeUnitsToInstall();
monitor.worked(5);
IStatus s;
if (isInstall) {
monitor.setTaskName(NLS.bind("Installing {0}", installDescription.getProductName()));
s = director.install(toInstall, p, monitor.newChild(90));
} else {
monitor.setTaskName(NLS.bind("Updating {0}", installDescription.getProductName()));
IInstallableUnit[] toUninstall = computeUnitsToUninstall(p);
s = director.replace(toUninstall, toInstall, p, monitor.newChild(90));
}
if (!s.isOK())
throw new CoreException(s);
}
/**
* Throws an exception of severity error with the given error message.
*/
private CoreException fail(String message) {
return fail(message, null);
}
/**
* Throws an exception of severity error with the given error message.
*/
private CoreException fail(String message, Throwable throwable) {
return new CoreException(new Status(IStatus.ERROR, InstallerActivator.PI_INSTALLER, message, throwable));
}
/**
* Finds and returns the installable unit with the given id, and optionally the
* given version.
*/
private IInstallableUnit findUnit(String id, Version version) throws CoreException {
if (id == null)
throw fail("Installable unit id not specified");
VersionRange range = VersionRange.emptyRange;
if (version != null && !version.equals(Version.emptyVersion))
range = new VersionRange(version, true, version, true);
IMetadataRepository[] repos = metadataRepoMan.getKnownRepositories();
for (int i = 0; i < repos.length; i++) {
IInstallableUnit[] found = repos[i].query(id, range, null, true, null);
if (found.length > 0)
return found[0];
}
throw fail("Installable unit not found: " + id);
}
/**
* Returns the profile being installed into.
*/
private Profile getProfile() {
return profileRegistry.getProfile(installDescription.getProductName());
}
/**
* Returns the result of the install operation, or <code>null</code> if
* no install operation has been run.
*/
public IStatus getResult() {
return result;
}
private Object getService(String name) throws CoreException {
ServiceReference ref = bundleContext.getServiceReference(name);
if (ref == null)
throw fail("Install requires a service that is not available: " + name);
Object service = bundleContext.getService(ref);
if (service == null)
throw fail("Install requires a service implementation that is not available: " + name);
serviceReferences.add(ref);
return service;
}
/* (non-Javadoc)
* @see org.eclipse.equinox.p2.installer.IInstallOperation#install(org.eclipse.core.runtime.IProgressMonitor)
*/
public IStatus install(IProgressMonitor pm) {
SubMonitor monitor = SubMonitor.convert(pm, "Preparing to install", 100);
try {
try {
preInstall();
isInstall = getProfile() == null;
doInstall(monitor);
result = new Status(IStatus.OK, InstallerActivator.PI_INSTALLER, isInstall ? "Install complete" : "Update complete", null);
monitor.setTaskName("Some final housekeeping");
} finally {
postInstall();
}
} catch (CoreException e) {
result = e.getStatus();
} finally {
monitor.done();
}
return result;
}
/**
* Returns whether this operation represents the product being installed
* for the first time, in a new profile.
*/
public boolean isFirstInstall() {
return isInstall;
}
private void postInstall() {
for (Iterator it = serviceReferences.iterator(); it.hasNext();) {
ServiceReference sr = (ServiceReference) it.next();
bundleContext.ungetService(sr);
}
serviceReferences.clear();
}
private void preInstall() throws CoreException {
if (System.getProperty("eclipse.p2.data.area") == null) //$NON-NLS-1$
System.setProperty("eclipse.p2.data.area", installDescription.getInstallLocation().append("installer").toString()); //$NON-NLS-1$ //$NON-NLS-2$
if (System.getProperty("eclipse.p2.cache") == null) //$NON-NLS-1$
System.setProperty("eclipse.p2.cache", installDescription.getInstallLocation().toString()); //$NON-NLS-1$
//start up p2
try {
InstallerActivator.getDefault().getBundle("org.eclipse.equinox.p2.exemplarysetup").start(Bundle.START_ACTIVATION_POLICY);
} catch (BundleException e) {
throw fail("Unable to start p2", e);
}
//obtain required services
serviceReferences.clear();
director = (IDirector) getService(IDirector.class.getName());
metadataRepoMan = (IMetadataRepositoryManager) getService(IMetadataRepositoryManager.class.getName());
artifactRepoMan = (IArtifactRepositoryManager) getService(IArtifactRepositoryManager.class.getName());
profileRegistry = (IProfileRegistry) getService(IProfileRegistry.class.getName());
}
private void prepareArtifactRepository() {
URL artifactRepo = installDescription.getArtifactRepository();
if (artifactRepo != null)
artifactRepoMan.loadRepository(artifactRepo, null);
}
private void prepareMetadataRepository() {
URL metadataRepo = installDescription.getMetadataRepository();
if (metadataRepo != null)
metadataRepoMan.loadRepository(metadataRepo, null);
}
}