blob: ebdc19545044ab15babc521ed5bfb41535050819 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009-2010 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
* Sonatype, Inc. - ongoing development
******************************************************************************/
package org.eclipse.equinox.p2.operations;
import org.eclipse.equinox.p2.planner.ProfileInclusionRules;
import java.util.Collection;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.p2.operations.*;
import org.eclipse.equinox.internal.provisional.p2.director.ProfileChangeRequest;
import org.eclipse.equinox.p2.engine.IProfile;
import org.eclipse.equinox.p2.engine.query.UserVisibleRootQuery;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.query.IQueryResult;
import org.eclipse.equinox.p2.query.QueryUtil;
/**
* An InstallOperation describes an operation that installs IInstallableUnits into
* a profile.
*
* The following snippet shows how one might use an InstallOperation to perform a synchronous resolution and
* then kick off an install in the background:
*
* <pre>
* InstallOperation op = new InstallOperation(session, new IInstallableUnit [] { myIU });
* IStatus result = op.resolveModal(monitor);
* if (result.isOK()) {
* op.getProvisioningJob(monitor).schedule();
* }
* </pre>
*
* @since 2.0
* @see ProfileChangeOperation
* @noextend This class is not intended to be subclassed by clients.
*/
public class InstallOperation extends ProfileChangeOperation {
private Collection<IInstallableUnit> toInstall;
/**
* Create an install operation on the specified provisioning session that installs
* the supplied IInstallableUnits. Unless otherwise specified, the operation will
* be associated with the currently running profile.
*
* @param session the session to use for obtaining provisioning services
* @param toInstall the IInstallableUnits to be installed into the profile.
*/
public InstallOperation(ProvisioningSession session, Collection<IInstallableUnit> toInstall) {
super(session);
this.toInstall = toInstall;
}
/*
* (non-Javadoc)
* @see org.eclipse.equinox.p2.operations.ProfileChangeOperation#computeProfileChangeRequest(org.eclipse.core.runtime.MultiStatus, org.eclipse.core.runtime.IProgressMonitor)
*/
protected void computeProfileChangeRequest(MultiStatus status, IProgressMonitor monitor) {
request = ProfileChangeRequest.createByProfileId(session.getProvisioningAgent(), profileId);
IProfile profile;
profile = session.getProfileRegistry().getProfile(profileId);
SubMonitor sub = SubMonitor.convert(monitor, Messages.InstallOperation_ComputeProfileChangeProgress, toInstall.size());
for (IInstallableUnit entryToInstall : toInstall) {
// If the user is installing a patch, we mark it optional. This allows
// the patched IU to be updated later by removing the patch.
if (QueryUtil.isPatch(entryToInstall))
request.setInstallableUnitInclusionRules(entryToInstall, ProfileInclusionRules.createOptionalInclusionRule(entryToInstall));
// Check to see if it is already installed. This may alter the request.
IQueryResult<IInstallableUnit> alreadyInstalled = profile.query(QueryUtil.createIUQuery(entryToInstall.getId()), null);
// TODO ideally we should only do this check if the iu is a singleton, but in practice many iu's that should
// be singletons are not, so we don't check this (yet)
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=230878
if (!alreadyInstalled.isEmpty()) { // && installedIU.isSingleton()
IInstallableUnit installedIU = alreadyInstalled.iterator().next();
int compareTo = entryToInstall.getVersion().compareTo(installedIU.getVersion());
// If the iu is a newer version of something already installed, consider this an
// update request
if (compareTo > 0) {
boolean lockedForUpdate = false;
String value = profile.getInstallableUnitProperty(installedIU, IProfile.PROP_PROFILE_LOCKED_IU);
if (value != null)
lockedForUpdate = (Integer.parseInt(value) & IProfile.LOCK_UPDATE) == IProfile.LOCK_UPDATE;
if (lockedForUpdate) {
// Add a status telling the user that this implies an update, but the
// iu should not be updated
status.merge(PlanAnalyzer.getStatus(IStatusCodes.ALTERED_IGNORED_IMPLIED_UPDATE, entryToInstall));
} else {
request.add(entryToInstall);
request.remove(installedIU);
// Add a status informing the user that the update has been inferred
status.merge(PlanAnalyzer.getStatus(IStatusCodes.ALTERED_IMPLIED_UPDATE, entryToInstall));
// Mark it as a root if it hasn't been already
if (!UserVisibleRootQuery.isUserVisible(installedIU, profile))
request.setInstallableUnitProfileProperty(entryToInstall, IProfile.PROP_PROFILE_ROOT_IU, Boolean.toString(true));
}
} else if (compareTo < 0) {
// An implied downgrade. We will not put this in the plan, add a status informing the user
status.merge(PlanAnalyzer.getStatus(IStatusCodes.ALTERED_IGNORED_IMPLIED_DOWNGRADE, entryToInstall));
} else {
// if (rootMarkerKey != null) {
if (UserVisibleRootQuery.isUserVisible(installedIU, profile))
// It is already a root, nothing to do. We tell the user it was already installed
status.merge(PlanAnalyzer.getStatus(IStatusCodes.ALTERED_IGNORED_ALREADY_INSTALLED, entryToInstall));
else {
// It was already installed but not as a root. Tell the user that parts of it are already installed and mark
// it as a root.
status.merge(PlanAnalyzer.getStatus(IStatusCodes.ALTERED_PARTIAL_INSTALL, entryToInstall));
request.setInstallableUnitProfileProperty(entryToInstall, IProfile.PROP_PROFILE_ROOT_IU, Boolean.toString(true));
}
// }
}
} else {
// Install it and mark as a root
request.add(entryToInstall);
// if (rootMarkerKey != null)
request.setInstallableUnitProfileProperty(entryToInstall, IProfile.PROP_PROFILE_ROOT_IU, Boolean.toString(true));
}
sub.worked(1);
}
sub.done();
}
/* (non-Javadoc)
* @see org.eclipse.equinox.p2.operations.ProfileChangeOperation#getResolveJobName()
*/
protected String getResolveJobName() {
return Messages.InstallOperation_ResolveJobName;
}
/* (non-Javadoc)
* @see org.eclipse.equinox.p2.operations.ProfileChangeOperation#getProvisioningJobName()
*/
protected String getProvisioningJobName() {
return Messages.InstallOperation_InstallJobName;
}
}