/*******************************************************************************
* Copyright (c) 2010 The Eclipse Foundation 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:
* The Eclipse Foundation - initial API and implementation
*******************************************************************************/
package org.eclipse.epp.internal.mpc.ui.operations;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.epp.internal.mpc.ui.MarketplaceClientUi;
import org.eclipse.equinox.internal.p2.director.ProfileChangeRequest;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.metadata.IRequirement;
import org.eclipse.equinox.p2.operations.InstallOperation;
import org.eclipse.equinox.p2.operations.ProfileChangeOperation;
import org.eclipse.equinox.p2.operations.ProvisioningSession;
import org.eclipse.equinox.p2.planner.IProfileChangeRequest;
@SuppressWarnings("restriction")
class CompositeProfileChangeOperation extends InstallOperation {
CompositeProfileChangeOperation(ProvisioningSession session) {
super(session, null);
this.session = session;
}
private final ProvisioningSession session;
private final List<ProfileChangeOperation> operations = new ArrayList<ProfileChangeOperation>();
public CompositeProfileChangeOperation add(ProfileChangeOperation operation) {
operations.add(operation);
return this;
}
public List<ProfileChangeOperation> getOperations() {
return operations;
}
@Override
protected void computeProfileChangeRequest(MultiStatus status, IProgressMonitor monitor) {
ProfileChangeRequest request = ProfileChangeRequest.createByProfileId(session.getProvisioningAgent(),
getProfileId());
SubMonitor progress = SubMonitor.convert(monitor, 1000 * operations.size());
for (ProfileChangeOperation operation : operations) {
updateRequest(request, operation, status, progress.newChild(1000));
}
try {
Field requestField = ProfileChangeOperation.class.getDeclaredField("request"); //$NON-NLS-1$
boolean accessible = requestField.isAccessible();
try {
requestField.setAccessible(true);
requestField.set(this, request);
} finally {
requestField.setAccessible(accessible);
}
} catch (Exception e) {
status.add(new Status(IStatus.ERROR, MarketplaceClientUi.BUNDLE_ID,
Messages.CompositeProfileChangeOperation_ChangeRequestError, e));
}
}
private void updateRequest(ProfileChangeRequest request, ProfileChangeOperation operation, MultiStatus status, IProgressMonitor monitor) {
IStatus result = operation.resolveModal(monitor);//TODO we do too much here - this already does the plan resolution, which is expensive...
status.merge(result);
if (status.getSeverity() != IStatus.ERROR) {
IProfileChangeRequest operationChangeRequest = operation.getProfileChangeRequest();
Collection<IInstallableUnit> additions = operationChangeRequest.getAdditions();
Collection<IInstallableUnit> removals = operationChangeRequest.getRemovals();
Collection<IRequirement> extraRequirements = operationChangeRequest.getExtraRequirements();
request.removeAll(removals);
request.addAll(additions);
if (extraRequirements != null) {
request.addExtraRequirements(extraRequirements);
}
if (operationChangeRequest instanceof ProfileChangeRequest) {
ProfileChangeRequest internalRequest = (ProfileChangeRequest) operationChangeRequest;
Map<IInstallableUnit, List<String>> installableUnitProfilePropertiesToRemove = internalRequest.getInstallableUnitProfilePropertiesToRemove();
for (Entry<IInstallableUnit, List<String>> entry : installableUnitProfilePropertiesToRemove.entrySet()) {
List<String> properties = entry.getValue();
if (properties != null && !properties.isEmpty()) {
IInstallableUnit iu = entry.getKey();
for (String property : properties) {
request.removeInstallableUnitProfileProperty(iu, property);
}
}
}
Map<IInstallableUnit, Map<String, String>> installableUnitProfilePropertiesToAdd = internalRequest.getInstallableUnitProfilePropertiesToAdd();
for (Entry<IInstallableUnit, Map<String, String>> entry : installableUnitProfilePropertiesToAdd.entrySet()) {
Map<String, String> properties = entry.getValue();
if (properties != null && !properties.isEmpty()) {
IInstallableUnit iu = entry.getKey();
for (Entry<String, String> property : properties.entrySet()) {
request.setInstallableUnitProfileProperty(iu, property.getKey(), property.getValue());
}
}
}
String[] propertiesToRemove = internalRequest.getPropertiesToRemove();
for (String property : propertiesToRemove) {
request.removeProfileProperty(property);
}
Map<String, String> propertiesToAdd = internalRequest.getPropertiesToAdd();
for (Entry<String, String> property : propertiesToAdd.entrySet()) {
request.setProfileProperty(property.getKey(), property.getValue());
}
}
}
}
}