Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine')
-rw-r--r--bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/AbstractProvisioningTransaction.java135
-rw-r--r--bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/BeginOperationEvent.java20
-rw-r--r--bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/CommitOperationEvent.java20
-rw-r--r--bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/DefaultPhaseSet.java21
-rw-r--r--bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/Engine.java83
-rw-r--r--bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/EngineSession.java33
-rw-r--r--bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/IProfileRegistry.java53
-rw-r--r--bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/IProvisioningAction.java36
-rw-r--r--bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/ITouchpoint.java26
-rw-r--r--bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/ITouchpointAction.java18
-rw-r--r--bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/IUPhase.java100
-rw-r--r--bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/InstallableUnitEvent.java68
-rw-r--r--bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/Operand.java35
-rw-r--r--bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/Phase.java61
-rw-r--r--bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/PhaseSet.java64
-rw-r--r--bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/Profile.java142
-rw-r--r--bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/ProfileEvent.java36
-rw-r--r--bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/ProvisioningConfigurationException.java21
-rw-r--r--bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/RollbackOperationEvent.java28
-rw-r--r--bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/SimpleProfileRegistry.java184
-rw-r--r--bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/TransactionEvent.java30
-rw-r--r--bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/Utils.java25
-rw-r--r--bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/phases/Collect.java76
-rw-r--r--bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/phases/Install.java60
-rw-r--r--bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/phases/Messages.java33
-rw-r--r--bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/phases/Uninstall.java58
-rw-r--r--bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/phases/messages.properties17
27 files changed, 1483 insertions, 0 deletions
diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/AbstractProvisioningTransaction.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/AbstractProvisioningTransaction.java
new file mode 100644
index 000000000..2f48238a2
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/AbstractProvisioningTransaction.java
@@ -0,0 +1,135 @@
+/*******************************************************************************
+ * 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.prov.engine;
+
+import java.util.ArrayList;
+import org.eclipse.core.runtime.*;
+import org.eclipse.equinox.internal.prov.engine.EngineActivator;
+import org.eclipse.equinox.prov.core.helpers.MultiStatus;
+import org.eclipse.equinox.prov.core.helpers.MultiStatusUtil;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * An abstract provisioning transaction specifies a simple mechanism
+ * for atomicity of a sequence of actions, based on the ability to
+ * revert the consequences of those actions.
+ *
+ * TODO: Implementation(s) of transactions should be registered via
+ * an extension point by classes that extended this class.
+ * This class should really be abstract.
+ */
+public abstract class AbstractProvisioningTransaction {
+
+ private ArrayList actions = new ArrayList();
+
+ private String description;
+
+ private boolean isUndoable;
+
+ private MultiStatus result;
+
+ private IProgressMonitor progressMonitor;
+
+ public AbstractProvisioningTransaction(String description, boolean isUndoable, MultiStatus result, IProgressMonitor monitor) {
+ this.description = description;
+ this.isUndoable = isUndoable;
+ this.result = (result != null ? result : new MultiStatus());
+ this.progressMonitor = monitor;
+ }
+
+ public IStatus performActions(IProvisioningAction[] ops, int[] weights, IProgressMonitor monitor) {
+ SubMonitor pm = SubMonitor.convert(monitor, weights.length);
+ IStatus status = Status.OK_STATUS;
+ try {
+ for (int i = 0; i < ops.length; i += 1) {
+ IProvisioningAction action = ops[i];
+ IProgressMonitor sub = (i < weights.length ? (IProgressMonitor) pm.newChild(weights[i]) : new NullProgressMonitor());
+ status = performAction(action, sub);
+ if (MultiStatusUtil.isErrorOrCancel(status)) {
+ break;
+ }
+ }
+ } finally {
+ pm.done();
+ }
+ return status;
+ }
+
+ protected IStatus performAction(IProvisioningAction action, IProgressMonitor monitor) {
+ actions.add(action);
+ IStatus opStatus = action.perform(this, monitor);
+ IStatus status = opStatus;
+
+ if (!isUndoable) {
+ result.add(opStatus);
+ status = Status.OK_STATUS;
+ } else if (MultiStatusUtil.isErrorOrCancel(opStatus)) {
+ int length = actions.size();
+ IProvisioningAction lastAction = (IProvisioningAction) actions.get(length - 1);
+ if (!lastAction.shouldRevertOnError()) {
+ actions.remove(length - 1);
+ }
+ } else if (monitor.isCanceled()) {
+ // first time we noticed cancellation
+ opStatus = new Status(IStatus.CANCEL, EngineActivator.ID, 0, ""/*Messages.Engine_Operation_Canceled_By_User*/, null);
+ }
+
+ if (opStatus.matches(IStatus.ERROR) && result.getMessage().length() == 0) {
+ result.setMessage(NLS.bind("Errors occurred during the transaction {0}", //$NON-NLS-1$
+ description));
+ } else if (opStatus.matches(IStatus.CANCEL) && result.getMessage().length() == 0) {
+ result.setMessage(NLS.bind("The transaction {0} was canceled", //$NON-NLS-1$
+ description));
+ }
+
+ monitor.done();
+ return status;
+ }
+
+ public void rollback(IProgressMonitor monitor) {
+ if (!isUndoable)
+ return;
+ isUndoable = false;
+
+ // TODO: is it necessary to allow support rollback that does NOT reverse the order
+ // of the actions? Consider phases.
+
+ SubMonitor pm = SubMonitor.convert(monitor, actions.size());
+ for (int i = actions.size() - 1; i >= 0; i--) {
+ IProvisioningAction action = (IProvisioningAction) actions.get(i);
+ try {
+ IStatus status = action.revert(this, pm.newChild(10));
+ // log.statusNotOK(status);
+ } catch (Exception e) {
+ // log.exception
+ }
+ }
+ }
+
+ public IProgressMonitor getProgressMonitor() {
+ return progressMonitor;
+ }
+
+ public boolean isUndoable() {
+ return isUndoable;
+ }
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("Transaction: "); //$NON-NLS-1$
+ sb.append(description);
+ sb.append(", ").append(actions.size()).append( //$NON-NLS-1$
+ " actions performed"); //$NON-NLS-1$
+ if (!isUndoable) {
+ sb.append(", isUndoable=").append(isUndoable); //$NON-NLS-1$
+ }
+ return sb.toString();
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/BeginOperationEvent.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/BeginOperationEvent.java
new file mode 100644
index 000000000..9acffd2cf
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/BeginOperationEvent.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * 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.prov.engine;
+
+public class BeginOperationEvent extends TransactionEvent {
+
+ private static final long serialVersionUID = 6389318375739324865L;
+
+ public BeginOperationEvent(Profile profile, PhaseSet phaseSet, Operand[] deltas, Engine engine) {
+ super(profile, phaseSet, deltas, engine);
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/CommitOperationEvent.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/CommitOperationEvent.java
new file mode 100644
index 000000000..e3bdd998a
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/CommitOperationEvent.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * 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.prov.engine;
+
+public class CommitOperationEvent extends TransactionEvent {
+ private static final long serialVersionUID = -523967775426133720L;
+
+ public CommitOperationEvent(Profile profile, PhaseSet phaseSet, Operand[] deltas, Engine engine) {
+ super(profile, phaseSet, deltas, engine);
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/DefaultPhaseSet.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/DefaultPhaseSet.java
new file mode 100644
index 000000000..ec52bb252
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/DefaultPhaseSet.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * 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.prov.engine;
+
+import org.eclipse.equinox.prov.engine.phases.*;
+
+public class DefaultPhaseSet extends PhaseSet {
+
+ public DefaultPhaseSet() {
+ super(new Phase[] {new Collect(10), new Uninstall(10), new Install(10)});
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/Engine.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/Engine.java
new file mode 100644
index 000000000..4a81eb640
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/Engine.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * 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.prov.engine;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.eclipse.core.runtime.*;
+import org.eclipse.equinox.prov.core.eventbus.ProvisioningEventBus;
+import org.eclipse.equinox.prov.core.helpers.MultiStatus;
+
+public class Engine {
+
+ private final ProvisioningEventBus eventBus;
+ private List lockedProfiles = new ArrayList();
+
+ public Engine(ProvisioningEventBus eventBus) {
+ this.eventBus = eventBus;
+ }
+
+ public MultiStatus perform(Profile profile, PhaseSet phaseSet, Operand[] operands, IProgressMonitor monitor) {
+
+ // TODO -- Messages
+ if (profile == null)
+ throw new IllegalArgumentException("Profile must not be null.");
+
+ if (phaseSet == null)
+ throw new IllegalArgumentException("PhaseSet must not be null.");
+
+ if (operands == null)
+ throw new IllegalArgumentException("Operands must not be null.");
+
+ if (monitor == null)
+ monitor = new NullProgressMonitor();
+
+ if (operands.length == 0)
+ return new MultiStatus(IStatus.OK, null);
+
+ lockProfile(profile);
+ try {
+ eventBus.publishEvent(new BeginOperationEvent(profile, phaseSet, operands, this));
+
+ EngineSession session = new EngineSession();
+ MultiStatus result = phaseSet.perform(session, profile, operands, monitor);
+ if (result.isOK()) {
+ eventBus.publishEvent(new CommitOperationEvent(profile, phaseSet, operands, this));
+ session.commit();
+ }
+
+ if (result.isErrorOrCancel()) {
+ eventBus.publishEvent(new RollbackOperationEvent(profile, phaseSet, operands, this, result));
+ session.rollback();
+ }
+ return result;
+ } finally {
+ unlockProfile(profile);
+ }
+ }
+
+ private synchronized void unlockProfile(Profile profile) {
+ lockedProfiles.remove(profile);
+ notify();
+ }
+
+ private synchronized void lockProfile(Profile profile) {
+ while (lockedProfiles.contains(profile)) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ // TODO We should think about how we want to handle blocked engine requests
+ Thread.currentThread().interrupt();
+ }
+ }
+ lockedProfiles.add(profile);
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/EngineSession.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/EngineSession.java
new file mode 100644
index 000000000..893e40ec0
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/EngineSession.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * 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.prov.engine;
+
+import java.util.*;
+
+public class EngineSession {
+ List actions = new ArrayList();
+
+ public void record(ITouchpointAction action) {
+ actions.add(action);
+ }
+
+ public void commit() {
+ actions.clear();
+ }
+
+ public void rollback() {
+ for (ListIterator it = actions.listIterator(actions.size()); it.hasPrevious();) {
+ ITouchpointAction action = (ITouchpointAction) it.previous();
+ action.undo();
+ }
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/IProfileRegistry.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/IProfileRegistry.java
new file mode 100644
index 000000000..504ae8651
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/IProfileRegistry.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * 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.prov.engine;
+
+/**
+ * This encapsulates the access to the profile registry.
+ * It deals with persistence in a transparent way.
+ */
+public interface IProfileRegistry {
+ public static final String SELF = "_SELF_"; //$NON-NLS-1$
+
+ /**
+ * Return the profile in the registry that has the given id. If it does not exist,
+ * then return <code>null</code>.
+ *
+ * @param id the profile identifier
+ * @return the profile or <code>null</code>
+ */
+ Profile getProfile(String id);
+
+ /**
+ * Return an array of profiles known to this registry. If there are none, then
+ * return an empty array.
+ *
+ * @return the array of profiles
+ */
+ Profile[] getProfiles();
+
+ /**
+ * Add the given profile to this profile registry.
+ *
+ * @param toAdd the profile to add
+ * @throws IllegalArgumentException if a profile
+ * with the same id is already present in the registry.
+ */
+ void addProfile(Profile toAdd) throws IllegalArgumentException;
+
+ /**
+ * Remove the given profile from this profile registry.
+ *
+ * @param toRemove the profile to remove
+ */
+ void removeProfile(Profile toRemove);
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/IProvisioningAction.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/IProvisioningAction.java
new file mode 100644
index 000000000..7b976aa69
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/IProvisioningAction.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * 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.prov.engine;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+
+/**
+ * The provisioning action interface represents a unit of work
+ * that can be performed during a provisioning activity.
+ * The granularity of the action can vary from a simple,
+ * indivisible unit of work to a complex, organized collection
+ * of steps.
+ * <p>
+ * The results of an provisioning activity must be revert-able
+ * an error or if a cancellation occurs. A provisioning action
+ * that will return an error or cancel status may choose to revert
+ * any work performed before returning or may indicate that
+ * the caller must explicitly revert.
+ */
+public interface IProvisioningAction {
+
+ public IStatus perform(AbstractProvisioningTransaction transaction, IProgressMonitor monitor);
+
+ public IStatus revert(AbstractProvisioningTransaction transaction, IProgressMonitor monitor);
+
+ public boolean shouldRevertOnError();
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/ITouchpoint.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/ITouchpoint.java
new file mode 100644
index 000000000..838d2a3de
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/ITouchpoint.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * 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.prov.engine;
+
+import org.eclipse.equinox.prov.metadata.TouchpointType;
+
+/**
+ * A touchpoint is responsible for executing a given phase for a given
+ * targeted system (eclipse, native). The order of phases is defined in the {@link PhaseSet}.
+ */
+public interface ITouchpoint {
+
+ public TouchpointType getTouchpointType();
+
+ public boolean supports(String phaseId);
+
+ public ITouchpointAction[] getActions(String phaseId, Profile profile, Operand operand);
+}
diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/ITouchpointAction.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/ITouchpointAction.java
new file mode 100644
index 000000000..c7a9a78e7
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/ITouchpointAction.java
@@ -0,0 +1,18 @@
+/*******************************************************************************
+ * 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.prov.engine;
+
+public interface ITouchpointAction {
+
+ Object execute();
+
+ Object undo();
+}
diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/IUPhase.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/IUPhase.java
new file mode 100644
index 000000000..4ac09ee3c
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/IUPhase.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * 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.prov.engine;
+
+import org.eclipse.core.runtime.*;
+import org.eclipse.equinox.prov.core.helpers.MultiStatus;
+
+// An operation that is applied to a set of IUs.
+public abstract class IUPhase extends Phase {
+ protected int PRE_PERFORM_WORK = 1000;
+ protected int PERFORM_WORK = 10000;
+ protected int POST_PERFORM_WORK = 1000;
+
+ protected IUPhase(String phaseId, int weight, String phaseName) {
+ super(phaseId, weight, phaseName);
+ }
+
+ protected void perform(MultiStatus status, EngineSession session, Profile profile, Operand[] operands, IProgressMonitor monitor) { //TODO Maybe should we do some kind of adaptable
+ SubMonitor subMonitor = SubMonitor.convert(monitor, PRE_PERFORM_WORK + PERFORM_WORK + POST_PERFORM_WORK);
+ prePerform(status, profile, operands, subMonitor.newChild(PRE_PERFORM_WORK));
+ if (status.isErrorOrCancel())
+ return;
+
+ subMonitor.setWorkRemaining(PERFORM_WORK + POST_PERFORM_WORK);
+ mainPerform(status, session, profile, operands, subMonitor.newChild(PERFORM_WORK));
+ if (status.isErrorOrCancel())
+ return;
+
+ subMonitor.setWorkRemaining(POST_PERFORM_WORK);
+ postPerform(status, profile, operands, subMonitor.newChild(POST_PERFORM_WORK));
+ if (status.isErrorOrCancel())
+ return;
+
+ subMonitor.done();
+ }
+
+ protected void mainPerform(MultiStatus status, EngineSession session, Profile profile, Operand[] operands, SubMonitor subMonitor) {
+ int operandWork = PERFORM_WORK / operands.length;
+ for (int i = 0; i < operands.length; ++i) {
+ if (subMonitor.isCanceled())
+ throw new OperationCanceledException();
+ Operand currentOperand = operands[i];
+ if (!isApplicable(currentOperand))
+ continue;
+ IStatus result = performOperand(session, profile, currentOperand, subMonitor.newChild(operandWork));
+ status.add(result);
+ if (status.isErrorOrCancel())
+ return;
+ }
+ }
+
+ protected abstract boolean isApplicable(Operand op);
+
+ // ITouchpoint touchpoint = TouchpointManager.getInstance().getTouchpoint(currentOperand.getTouchpointType());
+ // if (touchpoint == null) { //TODO Should we throw an exception instead?
+ // status.add(new Status(IStatus.ERROR, "org.eclipse.equinox.prov.engine", "The touchpoint " + currentOperand.getTouchpointType() + " is not available."));
+ // return;
+ // }
+ // if (touchpoint.supports(phaseId)) {
+ // status.add(performIU(touchpoint, currentOperand, subMonitor.newChild(operandWork)));
+ // }
+ // if (status.isErrorOrCancel() || sub.isCanceled()) {
+ // undoPerform(status, ius, i, context);
+ // return;
+ // }
+
+ // Error or cancel: undo IUs that were done.
+ // private void undoPerform(MultiStatus status, InstallableUnitPair[] ius, int currentIU, InstallContext context) {
+ // if (!status.isErrorOrCancel()) {
+ // status.setCanceled(); // first time we noticed cancelation
+ // currentIU += 1; // currentIU was completed so it must be undone
+ // }
+ // InstallableUnitPair[] undoIUs = new InstallableUnitPair[currentIU];
+ // for (int i = 0; i < currentIU; i += 1) {
+ // log.debug("Undo {0} phase for {1}", super.phaseName, ius[i]); //$NON-NLS-1$
+ // undoIUs[i] = ius[currentIU - (i + 1)].reverse();
+ // }
+ // // 1 unit to undo this phase, 10 for preceding phases
+ // SplitProgressMonitor pm = new SplitProgressMonitor(getUndoProgressMonitor(), new int[] {1, 10});
+ // doPerform(status, /*undoable*/false, undoIUs, context, pm.next());
+ // setUndoProgressMonitor(pm.next());
+ // }
+ protected abstract IStatus performOperand(EngineSession session, Profile profile, Operand operand, IProgressMonitor monitor);
+
+ protected void prePerform(MultiStatus status, Profile profile, Operand[] deltas, IProgressMonitor monitor) {
+ //Nothing to do.
+ }
+
+ protected void postPerform(MultiStatus status, Profile profile, Operand[] deltas, IProgressMonitor monitor) {
+ //Nothing to do.
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/InstallableUnitEvent.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/InstallableUnitEvent.java
new file mode 100644
index 000000000..6ba45dc09
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/InstallableUnitEvent.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * 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.prov.engine;
+
+import java.util.EventObject;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+
+public class InstallableUnitEvent extends EventObject {
+ private static final long serialVersionUID = 3318712818811459886L;
+
+ private String phaseId;
+ private boolean prePhase;
+
+ private Profile profile;
+ private Operand operand;
+ private ITouchpoint touchpoint;
+ private IStatus result;
+
+ public InstallableUnitEvent(String phaseId, boolean prePhase, Profile profile, Operand operand, ITouchpoint touchpoint) {
+ this(phaseId, prePhase, profile, operand, touchpoint, null);
+ }
+
+ public InstallableUnitEvent(String phaseId, boolean prePhase, Profile profile, Operand operand, ITouchpoint touchpoint, IStatus result) {
+ super(touchpoint); //TODO not sure if the touchpoint should be the source
+ this.phaseId = phaseId;
+ this.prePhase = prePhase;
+ this.profile = profile;
+ this.operand = operand;
+ this.result = result;
+ }
+
+ public ITouchpoint getTouchpoint() {
+ return touchpoint;
+ }
+
+ public Profile getProfile() {
+ return profile;
+ }
+
+ public Operand getOperand() {
+ return operand;
+ }
+
+ public String getPhase() {
+ return phaseId;
+ }
+
+ public boolean isPre() {
+ return prePhase;
+ }
+
+ public boolean isPost() {
+ return !prePhase;
+ }
+
+ public IStatus getResult() {
+ return (result != null ? result : Status.OK_STATUS);
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/Operand.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/Operand.java
new file mode 100644
index 000000000..5a4ac821e
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/Operand.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * 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.prov.engine;
+
+import org.eclipse.equinox.prov.metadata.IResolvedInstallableUnit;
+
+public class Operand {
+ private final IResolvedInstallableUnit first;
+ private final IResolvedInstallableUnit second;
+
+ public Operand(IResolvedInstallableUnit first, IResolvedInstallableUnit second) {
+ this.first = first;
+ this.second = second;
+ }
+
+ public IResolvedInstallableUnit first() {
+ return first;
+ }
+
+ public IResolvedInstallableUnit second() {
+ return second;
+ }
+
+ public String toString() {
+ return first + " --> " + second; //$NON-NLS-1$
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/Phase.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/Phase.java
new file mode 100644
index 000000000..19729096f
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/Phase.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * 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.prov.engine;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.equinox.internal.prov.engine.Messages;
+import org.eclipse.equinox.prov.core.helpers.MultiStatus;
+import org.eclipse.osgi.util.NLS;
+
+public abstract class Phase {
+ protected final String phaseId;
+ protected final int weight;
+ protected final String phaseName;
+
+ protected Phase(String phaseId, int weight, String phaseName) {
+ if (phaseId == null || phaseId.length() == 0) {
+ throw new IllegalArgumentException("Phase id must be set.");
+ }
+
+ if (weight <= 0) {
+ throw new IllegalArgumentException("Phase weight must be positive.");
+ }
+
+ if (phaseName == null || phaseName.length() == 0) {
+ throw new IllegalArgumentException("Phase name must be set.");
+ }
+
+ this.weight = weight;
+ this.phaseName = phaseName;
+ this.phaseId = phaseId;
+ }
+
+ public String toString() {
+ return "Phase: " + this.phaseName + " - " + this.weight; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ protected MultiStatus perform(EngineSession session, Profile profile, Operand[] deltas, IProgressMonitor monitor) {
+ MultiStatus status = new MultiStatus();
+ // log.start(log.info(Messages2.Engine_Performing_Phase, this.phaseName));
+ perform(status, session, profile, deltas, monitor);
+ // log.stop();
+ if (status.matches(IStatus.CANCEL)) {
+ status.setMessage(Messages.Engine_Operation_Canceled_By_User);
+ } else if (status.matches(IStatus.ERROR)) {
+ status.setMessage(NLS.bind(Messages.Engine_Error_During_Phase, this.phaseName));
+ }
+ return status;
+ }
+
+ protected abstract void perform(MultiStatus status, EngineSession session, Profile profile, Operand[] deltas, IProgressMonitor monitor);
+
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/PhaseSet.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/PhaseSet.java
new file mode 100644
index 000000000..f5d85a2b4
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/PhaseSet.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * 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.prov.engine;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.equinox.prov.core.helpers.MultiStatus;
+
+public abstract class PhaseSet {
+ private final Phase[] phases;
+
+ public PhaseSet(Phase[] phases) {
+ if (phases == null)
+ throw new IllegalArgumentException("Phases must not be null");
+
+ this.phases = phases;
+ }
+
+ public MultiStatus perform(EngineSession session, Profile profile, Operand[] deltas, IProgressMonitor monitor) {
+ MultiStatus result = new MultiStatus();
+ int[] weights = getProgressWeights();
+ int totalWork = getTotalWork(weights);
+ SubMonitor pm = SubMonitor.convert(monitor, totalWork);
+ try {
+ for (int i = 0; i < phases.length; i++) {
+ if (pm.isCanceled()) {
+ result.setCanceled();
+ return result;
+ }
+ Phase phase = phases[i];
+ result.add(phase.perform(session, profile, deltas, pm.newChild(weights[i])));
+ if (result.isErrorOrCancel())// || sub.isCanceled()) {
+ //TODO Need to perform the undo if we don't we use transactions
+ return result;
+ }
+ } finally {
+ pm.done();
+ }
+ return result;
+ }
+
+ private int getTotalWork(int[] weights) {
+ int sum = 0;
+ for (int i = 0; i < weights.length; i++)
+ sum += weights[i];
+ return sum;
+ }
+
+ private int[] getProgressWeights() {
+ int[] weights = new int[phases.length];
+ for (int i = 0; i < phases.length; i += 1) {
+ weights[i] = phases[i].weight;
+ }
+ return weights;
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/Profile.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/Profile.java
new file mode 100644
index 000000000..1894f375d
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/Profile.java
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * 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.prov.engine;
+
+import java.util.*;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.equinox.internal.prov.engine.EngineActivator;
+import org.eclipse.equinox.prov.core.helpers.ServiceHelper;
+import org.eclipse.equinox.prov.installregistry.IInstallRegistry;
+import org.eclipse.equinox.prov.installregistry.IProfileInstallRegistry;
+import org.eclipse.equinox.prov.metadata.IInstallableUnit;
+import org.eclipse.equinox.prov.metadata.RequiredCapability;
+import org.eclipse.equinox.prov.query.IQueryable;
+import org.eclipse.equinox.prov.query.QueryableArray;
+import org.eclipse.osgi.service.resolver.VersionRange;
+
+public class Profile implements IQueryable {
+
+ /**
+ * Profile property constant indicating the flavor for the profile.
+ */
+ public static String PROP_FLAVOR = "eclipse.prov.flavor"; //$NON-NLS-1$
+
+ /**
+ * Profile property constant indicating the install folder for the profile.
+ */
+ public static final String PROP_INSTALL_FOLDER = "eclipse.prov.installFolder"; //$NON-NLS-1$
+
+ /**
+ * Profile property constant indicating the installed language(s) for the profile.
+ */
+ public static final String PROP_NL = "eclipse.prov.nl"; //$NON-NLS-1$
+
+ /**
+ * Profile property constant for a string property indicating a user visible short
+ * textual description of this profile. May be empty or <code>null</code>, and
+ * generally will be for non-top level install contexts.
+ */
+ public static final String PROP_DESCRIPTION = "eclipse.prov.description"; //$NON-NLS-1$
+
+ /**
+ * Profile property constant for a string property indicating a user visible name of this profile.
+ * May be empty or <code>null</code>, and generally will be for non-top level
+ * install contexts.
+ */
+ public static final String PROP_NAME = "eclipse.prov.name"; //$NON-NLS-1$
+
+ /**
+ * Profile property constant indicating the list of environments
+ * (e.g., OS, WS, ...) in which a profile can operate. The value of the property
+ * is a comma-delimited string of key/value pairs.
+ */
+ public static final String PROP_ENVIRONMENTS = "eclipse.prov.environments"; //$NON-NLS-1$
+
+ /**
+ * Profile property constant for a boolean property indicating if the profiling
+ * is roaming. A roaming profile is one whose physical install location varies
+ * and is updated whenever it runs.
+ */
+ public static final String PROP_ROAMING = "eclipse.prov.roaming"; //$NON-NLS-1$
+
+ /**
+ * Profile property constant indicating the bundle pool cache location.
+ */
+ public static final String PROP_CACHE = "eclipse.prov.cache"; //$NON-NLS-1$
+
+ //Internal id of the profile
+ private String profileId;
+
+ private Profile parentProfile;
+
+ /**
+ * This storage is to be used by the touchpoints to store data. The data must be serializable
+ */
+ private Properties storage = new Properties();
+
+ public Profile(String profileId) {
+ if (profileId == null || profileId.length() == 0) {
+ throw new IllegalArgumentException("Profile id must be set.");
+ }
+ this.profileId = profileId;
+ }
+
+ public String getProfileId() {
+ return profileId;
+ }
+
+ public Profile getParentProfile() {
+ return parentProfile;
+ }
+
+ public String getValue(String key) {
+ return storage.getProperty(key);
+ }
+
+ public void setValue(String key, String value) {
+ storage.setProperty(key, value);
+ }
+
+ public Dictionary getSelectionContext() {
+ Properties result = new Properties(storage);
+ String environments = storage.getProperty(PROP_ENVIRONMENTS);
+ if (environments == null)
+ return result;
+ for (StringTokenizer tokenizer = new StringTokenizer(environments, ","); tokenizer.hasMoreElements();) {
+ String entry = tokenizer.nextToken();
+ int i = entry.indexOf('=');
+ String key = entry.substring(0, i).trim();
+ String value = entry.substring(i + 1).trim();
+ result.put(key, value);
+ }
+ return result;
+ }
+
+ private IInstallableUnit[] getAllInstallableUnits() {
+ IInstallRegistry registry = (IInstallRegistry) ServiceHelper.getService(EngineActivator.getContext(), IInstallRegistry.class.getName());
+ if (registry == null)
+ return null;
+ IProfileInstallRegistry profile = registry.getProfileInstallRegistry(new Profile(profileId));
+ if (profile == null)
+ return null;
+ return profile.getInstallableUnits();
+ }
+
+ public Iterator getIterator(String id, VersionRange range, RequiredCapability[] requirements, boolean and) {
+ return new QueryableArray(getAllInstallableUnits()).getIterator(id, range, requirements, and);
+ }
+
+ public IInstallableUnit[] query(String id, VersionRange range, RequiredCapability[] requirements, boolean and, IProgressMonitor progress) {
+ return new QueryableArray(getAllInstallableUnits()).query(id, range, requirements, and, progress);
+ }
+
+ public Iterator getInstallableUnits() {
+ return Arrays.asList(getAllInstallableUnits()).iterator();
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/ProfileEvent.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/ProfileEvent.java
new file mode 100644
index 000000000..cbb120e67
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/ProfileEvent.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * 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.prov.engine;
+
+import java.util.EventObject;
+
+public class ProfileEvent extends EventObject {
+ private static final long serialVersionUID = 3082402920617281765L;
+
+ public static byte ADDED = 0;
+ public static byte REMOVED = 1;
+
+ private byte reason;
+
+ public ProfileEvent(Profile source, byte reason) {
+ super(source);
+ this.reason = reason;
+ }
+
+ public byte getReason() {
+ return reason;
+ }
+
+ public Profile getProfile() {
+ return (Profile) getSource();
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/ProvisioningConfigurationException.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/ProvisioningConfigurationException.java
new file mode 100644
index 000000000..4c2496080
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/ProvisioningConfigurationException.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * 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.prov.engine;
+
+public class ProvisioningConfigurationException extends RuntimeException {
+
+ private static final long serialVersionUID = -712627437440533809L;
+
+ public ProvisioningConfigurationException(String name) {
+ super(name);
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/RollbackOperationEvent.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/RollbackOperationEvent.java
new file mode 100644
index 000000000..9de0d51c1
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/RollbackOperationEvent.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * 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.prov.engine;
+
+import org.eclipse.core.runtime.IStatus;
+
+public class RollbackOperationEvent extends TransactionEvent {
+
+ private static final long serialVersionUID = -2076492953949691215L;
+ private IStatus cause;
+
+ public RollbackOperationEvent(Profile profile, PhaseSet phaseSet, Operand[] deltas, Engine engine, IStatus cause) {
+ super(profile, phaseSet, deltas, engine);
+ this.cause = cause;
+ }
+
+ public IStatus getStatus() {
+ return cause;
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/SimpleProfileRegistry.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/SimpleProfileRegistry.java
new file mode 100644
index 000000000..ae4c4c622
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/SimpleProfileRegistry.java
@@ -0,0 +1,184 @@
+/*******************************************************************************
+ * 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.prov.engine;
+
+import com.thoughtworks.xstream.XStream;
+import java.io.*;
+import java.net.URL;
+import java.util.LinkedHashMap;
+import java.util.Properties;
+import org.eclipse.equinox.internal.prov.engine.EngineActivator;
+import org.eclipse.equinox.internal.prov.engine.Messages;
+import org.eclipse.equinox.prov.core.eventbus.ProvisioningEventBus;
+import org.eclipse.equinox.prov.core.helpers.ServiceHelper;
+import org.eclipse.equinox.prov.core.location.AgentLocation;
+import org.eclipse.osgi.service.datalocation.Location;
+import org.eclipse.osgi.util.NLS;
+
+public class SimpleProfileRegistry implements IProfileRegistry {
+ private static String STORAGE = "profileRegistry.xml"; //$NON-NLS-1$
+
+ /**
+ * Map of String(Profile id)->Profile.
+ */
+ private LinkedHashMap profiles = new LinkedHashMap(8);
+
+ private Properties properties = new Properties();
+
+ private String self;
+
+ public SimpleProfileRegistry() {
+ self = EngineActivator.getContext().getProperty("eclipse.prov.profile"); //$NON-NLS-1$
+ restore();
+ updateRoamingProfile();
+ }
+
+ /**
+ * If the current profile for self is marked as a roaming profile, we need
+ * to update its install and bundle pool locations.
+ */
+ private void updateRoamingProfile() {
+ Profile selfProfile = getProfile(SELF);
+ if (selfProfile == null)
+ return;
+ //only update if self is a roaming profile
+ if (!Boolean.valueOf(selfProfile.getValue(Profile.PROP_ROAMING)).booleanValue())
+ return;
+ Location installLocation = (Location) ServiceHelper.getService(EngineActivator.getContext(), Location.class.getName(), Location.INSTALL_FILTER);
+ String locationString = installLocation.getURL().getPath();
+ boolean changed = false;
+ if (!locationString.equals(selfProfile.getValue(Profile.PROP_INSTALL_FOLDER))) {
+ selfProfile.setValue(Profile.PROP_INSTALL_FOLDER, locationString);
+ changed = true;
+ }
+ if (!locationString.equals(selfProfile.getValue(Profile.PROP_CACHE))) {
+ selfProfile.setValue(Profile.PROP_CACHE, locationString);
+ changed = true;
+ }
+ if (changed)
+ persist();
+ }
+
+ public String toString() {
+ return this.profiles.toString();
+ }
+
+ public Profile getProfile(String id) {
+ if (SELF.equals(id))
+ id = self;
+ return (Profile) profiles.get(id);
+ }
+
+ public Profile[] getProfiles() {
+ return (Profile[]) profiles.values().toArray(new Profile[profiles.size()]);
+ }
+
+ public void addProfile(Profile toAdd) throws IllegalArgumentException {
+ if (isNamedSelf(toAdd))
+ throw new IllegalArgumentException(NLS.bind(Messages.Profile_Not_Named_Self, toAdd.getProfileId()));
+ String id = toAdd.getProfileId();
+ if (getProfile(id) == null) {
+ profiles.put(id, toAdd);
+ } else
+ throw new IllegalArgumentException(NLS.bind(Messages.Profile_Duplicate_Profile_Id, id));
+ broadcastChangeEvent(toAdd, ProfileEvent.ADDED);
+ persist(); //TODO This is not enough to keep track of the changes that are being done in a profile. This will likely have to be based on some event like commit
+ }
+
+ private void broadcastChangeEvent(Profile profile, byte reason) {
+ ((ProvisioningEventBus) ServiceHelper.getService(EngineActivator.getContext(), ProvisioningEventBus.class.getName())).publishEvent(new ProfileEvent(profile, reason));
+ }
+
+ private void restore() {
+ try {
+ BufferedInputStream bif = null;
+ try {
+ Location agent = (Location) ServiceHelper.getService(EngineActivator.getContext(), AgentLocation.class.getName());
+ if (agent == null)
+ // TODO should likely do something here since we failed to restore.
+ return;
+ bif = new BufferedInputStream(new URL(agent.getURL(), STORAGE).openStream());
+ XStream xml = new XStream();
+ Object[] read = (Object[]) xml.fromXML(bif);
+ properties = (Properties) read[0];
+ profiles = (LinkedHashMap) read[1];
+ } finally {
+ if (bif != null)
+ bif.close();
+ }
+ } catch (FileNotFoundException e) {
+ //This is ok.
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ private void persist() {
+ OutputStream os;
+ try {
+ Location agent = (Location) ServiceHelper.getService(EngineActivator.getContext(), AgentLocation.class.getName());
+ if (agent == null)
+ // TODO should likely do something here since we failed to persist.
+ return;
+ if (!agent.getURL().getProtocol().equals("file"))
+ throw new IOException("can't write at the given location");
+
+ File outputFile = new File(agent.getURL().getFile(), STORAGE);
+ if (!outputFile.getParentFile().exists() && !outputFile.getParentFile().mkdirs())
+ throw new RuntimeException("can't persist profile registry at: " + outputFile);
+ os = new BufferedOutputStream(new FileOutputStream(outputFile));
+ try {
+ XStream xstream = new XStream();
+ xstream.toXML(new Object[] {properties, profiles}, os);
+ } finally {
+ os.close();
+ }
+ } catch (FileNotFoundException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ }
+
+ public void removeProfile(Profile toRemove) {
+ if (isNamedSelf(toRemove))
+ throw new IllegalArgumentException(NLS.bind(Messages.Profile_Not_Named_Self, toRemove.getProfileId()));
+ if (profiles.remove(toRemove.getProfileId()) == null)
+ return;
+ broadcastChangeEvent(toRemove, ProfileEvent.REMOVED);
+ persist();
+ }
+
+ private boolean isNamedSelf(Profile p) {
+ if (SELF.equals(p.getParentProfile()))
+ return true;
+ return false;
+ }
+
+ public Properties getProperties() {
+ return properties;
+ }
+
+ public String getProperty(String key) {
+ return properties.getProperty(key);
+ }
+
+ public void setProperty(String key, String value) {
+ properties.setProperty(key, value);
+ }
+
+ public void removeProperty(String key) {
+ properties.remove(key);
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/TransactionEvent.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/TransactionEvent.java
new file mode 100644
index 000000000..9249735a1
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/TransactionEvent.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * 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.prov.engine;
+
+import java.util.EventObject;
+
+public abstract class TransactionEvent extends EventObject {
+ protected Profile profile;
+ protected PhaseSet phaseSet;
+ protected Operand[] deltas;
+
+ public TransactionEvent(Profile profile, PhaseSet phaseSet, Operand[] deltas, Engine engine) {
+ super(engine);
+ this.profile = profile;
+ this.phaseSet = phaseSet;
+ this.deltas = deltas;
+ }
+
+ public Profile getProfile() {
+ return profile;
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/Utils.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/Utils.java
new file mode 100644
index 000000000..949119d6b
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/Utils.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * 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.prov.engine;
+
+import org.eclipse.core.runtime.IAdaptable;
+
+public class Utils {
+
+ //This method will return the adapter, or will throw an exception
+ public static Object getAdapter(IAdaptable toAdapt, Class toAdaptType) throws ProvisioningConfigurationException {
+ Object result = toAdapt.getAdapter(toAdaptType);
+ if (result == null)
+ throw new ProvisioningConfigurationException("Adaptation failure. Can't adapt :" + toAdapt.getClass().getName() + " into a" + toAdaptType.getName());
+ return result;
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/phases/Collect.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/phases/Collect.java
new file mode 100644
index 000000000..e0cff6d83
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/phases/Collect.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * 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.prov.engine.phases;
+
+import org.eclipse.core.runtime.*;
+import org.eclipse.equinox.internal.prov.engine.TouchpointManager;
+import org.eclipse.equinox.prov.artifact.repository.IArtifactRequest;
+import org.eclipse.equinox.prov.core.helpers.MultiStatus;
+import org.eclipse.equinox.prov.download.DownloadManager;
+import org.eclipse.equinox.prov.engine.*;
+import org.eclipse.equinox.prov.metadata.IInstallableUnit;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * The goal of the collect phase is to ask the touchpoints if the artifacts associated with an IU need to be downloaded.
+ */
+public class Collect extends IUPhase {
+ private static final String PHASE_ID = "collect"; //$NON-NLS-1$
+ private DownloadManager dm = null;
+
+ public Collect(int weight) {
+ super(PHASE_ID, weight, Messages.Engine_Collect_Phase);
+ //re-balance work since postPerform will do almost all the time-consuming work
+ PRE_PERFORM_WORK = 0;
+ PERFORM_WORK = 100;
+ POST_PERFORM_WORK = 1000;
+ }
+
+ protected IStatus performOperand(EngineSession session, Profile profile, Operand operand, IProgressMonitor monitor) {
+ IInstallableUnit unit = operand.second();
+
+ if (unit != null) {
+ monitor.subTask(NLS.bind(Messages.Engine_Collecting_For_IU, unit.getId()));
+
+ // TODO: Need do progress reporting
+
+ // Ask all the touchpoints if they need to download an artifact
+ ITouchpoint touchpoint = TouchpointManager.getInstance().getTouchpoint(unit.getTouchpointType());
+ if (touchpoint.supports(PHASE_ID)) {
+ ITouchpointAction[] actions = touchpoint.getActions(PHASE_ID, profile, operand);
+ for (int i = 0; i < actions.length; i++) {
+ Object result = actions[i].execute();
+ if (result != null)
+ dm.add((IArtifactRequest[]) result);
+ session.record(actions[i]);
+ }
+ }
+
+ if (monitor.isCanceled())
+ return Status.CANCEL_STATUS;
+ }
+
+ return Status.OK_STATUS;
+ }
+
+ protected void postPerform(MultiStatus status, Profile profile, Operand[] deltas, IProgressMonitor monitor) {
+ // Start the download
+ status.add(dm.start(monitor));
+ }
+
+ protected void prePerform(MultiStatus status, Profile profile, Operand[] deltas, IProgressMonitor monitor) {
+ dm = new DownloadManager();
+ }
+
+ protected boolean isApplicable(Operand op) {
+ if (op.second() != null)
+ return true;
+ return false;
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/phases/Install.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/phases/Install.java
new file mode 100644
index 000000000..660d2f74e
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/phases/Install.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * 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.prov.engine.phases;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.equinox.internal.prov.engine.EngineActivator;
+import org.eclipse.equinox.internal.prov.engine.TouchpointManager;
+import org.eclipse.equinox.prov.core.eventbus.ProvisioningEventBus;
+import org.eclipse.equinox.prov.core.helpers.MultiStatus;
+import org.eclipse.equinox.prov.core.helpers.ServiceHelper;
+import org.eclipse.equinox.prov.engine.*;
+import org.eclipse.equinox.prov.metadata.IInstallableUnit;
+import org.eclipse.osgi.util.NLS;
+
+public class Install extends IUPhase {
+
+ private static final String PHASE_ID = "install"; //$NON-NLS-1$
+
+ public Install(int weight) {
+ super(PHASE_ID, weight, Messages.Engine_Install_Phase);
+ }
+
+ protected IStatus performOperand(EngineSession session, Profile profile, Operand operand, IProgressMonitor monitor) {
+ IInstallableUnit unit = operand.second();
+
+ monitor.subTask(NLS.bind(Messages.Engine_Installing_IU, unit.getId()));
+
+ ITouchpoint touchpoint = TouchpointManager.getInstance().getTouchpoint(unit.getTouchpointType());
+ if (!touchpoint.supports(PHASE_ID))
+ ((ProvisioningEventBus) ServiceHelper.getService(EngineActivator.getContext(), ProvisioningEventBus.class.getName())).publishEvent(new InstallableUnitEvent(PHASE_ID, true, profile, operand, touchpoint));
+
+ ITouchpointAction[] actions = touchpoint.getActions(PHASE_ID, profile, operand);
+ MultiStatus result = new MultiStatus();
+ for (int i = 0; i < actions.length; i++) {
+ IStatus actionStatus = (IStatus) actions[i].execute();
+ result.add(actionStatus);
+ if (!actionStatus.isOK())
+ return result;
+
+ session.record(actions[i]);
+ }
+ ((ProvisioningEventBus) ServiceHelper.getService(EngineActivator.getContext(), ProvisioningEventBus.class.getName())).publishEvent(new InstallableUnitEvent(PHASE_ID, false, profile, operand, touchpoint, result));
+ return result;
+ }
+
+ protected boolean isApplicable(Operand op) {
+ if (op.second() != null)
+ return true;
+ return false;
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/phases/Messages.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/phases/Messages.java
new file mode 100644
index 000000000..f35b810e0
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/phases/Messages.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * 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.prov.engine.phases;
+
+import org.eclipse.osgi.util.NLS;
+
+public class Messages extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.equinox.prov.engine.phases.messages"; //$NON-NLS-1$
+
+ static {
+ // initialize resource bundles
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ private Messages() {
+ // Do not instantiate
+ }
+
+ public static String Engine_Collect_Phase;
+ public static String Engine_Collecting_For_IU;
+ public static String Engine_Install_Phase;
+ public static String Engine_Installing_IU;
+ public static String Engine_Uninstall_Phase;
+ public static String Engine_Uninstalling_IU;
+}
diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/phases/Uninstall.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/phases/Uninstall.java
new file mode 100644
index 000000000..0732680e1
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/phases/Uninstall.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * 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.prov.engine.phases;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.equinox.internal.prov.engine.EngineActivator;
+import org.eclipse.equinox.internal.prov.engine.TouchpointManager;
+import org.eclipse.equinox.prov.core.eventbus.ProvisioningEventBus;
+import org.eclipse.equinox.prov.core.helpers.MultiStatus;
+import org.eclipse.equinox.prov.core.helpers.ServiceHelper;
+import org.eclipse.equinox.prov.engine.*;
+import org.eclipse.equinox.prov.metadata.IInstallableUnit;
+import org.eclipse.osgi.util.NLS;
+
+public class Uninstall extends IUPhase {
+
+ private static final String PHASE_ID = "uninstall"; //$NON-NLS-1$
+
+ public Uninstall(int weight) {
+ super(PHASE_ID, weight, Messages.Engine_Uninstall_Phase);
+ }
+
+ protected IStatus performOperand(EngineSession session, Profile profile, Operand operand, IProgressMonitor monitor) {
+ IInstallableUnit unit = operand.first();
+
+ monitor.subTask(NLS.bind(Messages.Engine_Uninstalling_IU, unit.getId()));
+
+ ITouchpoint touchpoint = TouchpointManager.getInstance().getTouchpoint(unit.getTouchpointType());
+ if (touchpoint.supports(PHASE_ID))
+ ((ProvisioningEventBus) ServiceHelper.getService(EngineActivator.getContext(), ProvisioningEventBus.class.getName())).publishEvent(new InstallableUnitEvent(PHASE_ID, true, profile, operand, touchpoint));
+
+ //TODO need to protect the actual operation on a try / catch to ensure the delivery of event.
+ ITouchpointAction[] actions = touchpoint.getActions(PHASE_ID, profile, operand);
+ MultiStatus result = new MultiStatus();
+ for (int i = 0; i < actions.length; i++) {
+ result.add((IStatus) actions[i].execute());
+ session.record(actions[i]);
+ }
+
+ ((ProvisioningEventBus) ServiceHelper.getService(EngineActivator.getContext(), ProvisioningEventBus.class.getName())).publishEvent(new InstallableUnitEvent(PHASE_ID, false, profile, operand, touchpoint, result));
+ return result;
+ }
+
+ protected boolean isApplicable(Operand op) {
+ if (op.first() != null)
+ return true;
+ return false;
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/phases/messages.properties b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/phases/messages.properties
new file mode 100644
index 000000000..9e644e32f
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/prov/engine/phases/messages.properties
@@ -0,0 +1,17 @@
+###############################################################################
+# 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
+###############################################################################
+
+Engine_Collect_Phase=collect
+Engine_Install_Phase=install
+Engine_Uninstall_Phase=uninstall
+Engine_Collecting_For_IU=Collecting for {0}
+Engine_Installing_IU=Installing {0}
+Engine_Uninstalling_IU=Uninstalling {0} \ No newline at end of file

Back to the top