diff options
author | John Arthorne | 2007-09-30 18:11:02 +0000 |
---|---|---|
committer | John Arthorne | 2007-09-30 18:11:02 +0000 |
commit | 2ccb446cc885495686cc9eb430c4a98031b3cfc5 (patch) | |
tree | 207e30d5f61856ece926ed3548297aa3958132c9 /bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse | |
parent | c4f6662ccd02bb75cba95a6ae56a2da38c6cadde (diff) | |
download | rt.equinox.p2-2ccb446cc885495686cc9eb430c4a98031b3cfc5.tar.gz rt.equinox.p2-2ccb446cc885495686cc9eb430c4a98031b3cfc5.tar.xz rt.equinox.p2-2ccb446cc885495686cc9eb430c4a98031b3cfc5.zip |
Renamed prov bundles to p2
Diffstat (limited to 'bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse')
33 files changed, 2189 insertions, 0 deletions
diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/prov/metadata/ArtifactKey.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/prov/metadata/ArtifactKey.java new file mode 100644 index 000000000..71546915b --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/prov/metadata/ArtifactKey.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * 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.prov.metadata; + +import org.eclipse.equinox.prov.metadata.IArtifactKey; +import org.osgi.framework.Version; + +/** + * The concrete type for representing IArtifactKey's. + * <p> + * See {link IArtifact for a description of the lifecycle of artifact keys) + */ +public class ArtifactKey implements IArtifactKey { + + static final int NO_SEGMENTS = 5; + private static final char SEP_CHAR = ','; + + private String namespace; + private String id; + private String classifier; + private transient Version versionObject; + private String version; + + public ArtifactKey(String namespace, String classifier, String id, Version aVersion) { + super(); + if (namespace.indexOf(SEP_CHAR) != -1) + throw new IllegalArgumentException("comma not allowed in namespace"); //$NON-NLS-1$ + if (classifier.indexOf(SEP_CHAR) != -1) + throw new IllegalArgumentException("comma not allowed in classifier"); //$NON-NLS-1$ + if (id.indexOf(SEP_CHAR) != -1) + throw new IllegalArgumentException("comma not allowed in id"); //$NON-NLS-1$ + this.namespace = namespace; + this.classifier = classifier; + this.id = id; + this.versionObject = aVersion; + this.version = aVersion == null ? null : aVersion.toString(); + } + + public String getNamespace() { + return namespace; + } + + public String getClassifier() { + return classifier; + } + + public Version getVersion() { + if (versionObject == null) + versionObject = version == null ? Version.emptyVersion : new Version(version); + return versionObject; + } + + public int hashCode() { + int hash = id.hashCode(); + hash = 17 * hash + getVersion().hashCode(); + hash = 17 * hash + namespace.hashCode(); + hash = 17 * hash + classifier.hashCode(); + return hash; + } + + public String toString() { + return "ArtifactKey=" + id + '/' + namespace + '/' + classifier + '/' + getVersion(); //$NON-NLS-1$ + } + + public boolean equals(Object obj) { + if (!(obj instanceof ArtifactKey)) + return false; + ArtifactKey ak = (ArtifactKey) obj; + return ak.id.equals(id) && ak.getVersion().equals(getVersion()) && ak.namespace.equals(namespace) && ak.classifier.equals(classifier); + } + + public String getId() { + return id; + } + +} diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/prov/metadata/InternalInstallableUnit.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/prov/metadata/InternalInstallableUnit.java new file mode 100644 index 000000000..6ab875e14 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/prov/metadata/InternalInstallableUnit.java @@ -0,0 +1,16 @@ +/******************************************************************************* + * 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.prov.metadata; + +import org.eclipse.equinox.prov.metadata.IInstallableUnit; +import org.eclipse.equinox.prov.metadata.IResolvedInstallableUnit; + +public interface InternalInstallableUnit extends IInstallableUnit { + public IResolvedInstallableUnit getResolved(); +} diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/prov/metadata/Messages.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/prov/metadata/Messages.java new file mode 100644 index 000000000..00c7aef16 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/prov/metadata/Messages.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.internal.prov.metadata; + +import org.eclipse.osgi.util.NLS; + +public class Messages extends NLS { + + private static final String BUNDLE_NAME = "org.eclipse.equinox.internal.prov.metadata.messages"; //$NON-NLS-1$ + + static { + // load message values from bundle file and assign to fields below + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + public static String QUERY_PROGRESS; + +} diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/prov/metadata/MetadataActivator.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/prov/metadata/MetadataActivator.java new file mode 100644 index 000000000..9e717f490 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/prov/metadata/MetadataActivator.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * 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.prov.metadata; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +public class MetadataActivator implements BundleActivator { + public static final String PI_METADATA = "org.eclipse.equinox.prov.metadata"; //$NON-NLS-1$ + public static BundleContext context; + + public static BundleContext getContext() { + return context; + } + + public void start(BundleContext context) throws Exception { + MetadataActivator.context = context; + } + + public void stop(BundleContext context) throws Exception { + MetadataActivator.context = null; + } + +} diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/prov/metadata/messages.properties b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/prov/metadata/messages.properties new file mode 100644 index 000000000..138d56215 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/prov/metadata/messages.properties @@ -0,0 +1,14 @@ +############################################################################### +# 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 +############################################################################### + +QUERY_PROGRESS=Executing query. + + diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/ConstrainableElement.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/ConstrainableElement.java new file mode 100644 index 000000000..a45c91031 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/ConstrainableElement.java @@ -0,0 +1,14 @@ +/******************************************************************************* + * 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.metadata; + +public class ConstrainableElement { +} diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/IArtifactKey.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/IArtifactKey.java new file mode 100644 index 000000000..3f45b9f9c --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/IArtifactKey.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * 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.metadata; + +import org.osgi.framework.Version; + +/** + * Provide standardized artifact information to uniquely identify the + * corresponding bytes (perhaps not stored as a file). + * <p> + * Artifact keys represent both a unique opaque identifier as well as structured + * and standardized pieces of information. + */ + +public interface IArtifactKey { + + /** + * The namespace. + * @return This returns the namespace segment of the artifact. Never + * null or empty. + */ + String getNamespace(); + + /** + * The classifier. + * @return This returns the classifier segment of the key. Never + * null. Can be empty. + */ + String getClassifier(); + + /** + * The identity of the artifact. + * @return This returns the id segment of the artifact. Can + * be empty. + * + * TODO: consider renaming this to getIdentity. + */ + String getId(); + + /** + * The version of the artifact. + * @return This returns the version of the artifact. Never null. Can + * be empty (Version.emptyVersion). + */ + Version getVersion(); +} diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/IInstallableUnit.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/IInstallableUnit.java new file mode 100644 index 000000000..399747f34 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/IInstallableUnit.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * 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.metadata; + +import org.osgi.framework.Version; + +public interface IInstallableUnit extends Comparable { + + /** + * A capability namespace representing a particular kind of installable unit. + * For example, an InstallableUnit may specify that it provides the "group" kind + * capability to express that it represents a group of instalable units. + */ + public static final String IU_KIND_NAMESPACE = "org.eclipse.equinox.prov.type"; //$NON-NLS-1$ + /** + * A capability namespace representing a particular InstallableUnit by name. + * Each InstallableUnit automatically provides an instance of this namespace representing + * itself, and other InstallableUnits can require such a capability to state that they + * require a particular InstallableUnit to be present. + */ + public static final String IU_NAMESPACE = "org.eclipse.equinox.prov.iunamespace"; //$NON-NLS-1$ + /** + * A capability namespace representing a particular profile flavor. + */ + public static final String FLAVOR_NAMESPACE = "flavor"; //$NON-NLS-1$ + //These two constants needs to be moved somewhere more appropriate... + public static final String CAPABILITY_ECLIPSE_TYPES = "org.eclipse.equinox.prov.eclipsetouchpoint.types"; //$NON-NLS-1$ + public static final String CAPABILITY_ECLIPSE_BUNDLE = "bundle"; //$NON-NLS-1$ + + public abstract TouchpointType getTouchpointType(); + + public abstract String getId(); + + /** + * Returns the filter on this installable unit. The filter is matched against + * the selection context of the profile the unit is installed into. An IU will not + * be installed if it has a filter condition that is not satisfied by the context. + * + * See Profile#getSelectionContext. + */ + public abstract String getFilter(); + + public abstract Version getVersion(); + + public abstract IArtifactKey[] getArtifacts(); + + public abstract RequiredCapability[] getRequiredCapabilities(); + + // public ProvidedCapability[] getProvidedCapabilities() { + // return providedCapabilities; + // } + // + public abstract ProvidedCapability[] getProvidedCapabilities(); + + public abstract boolean isSingleton(); + + public abstract String getProperty(String key); + + public abstract TouchpointData[] getTouchpointData(); + + public abstract boolean isFragment(); + + public abstract String getApplicabilityFilter(); + + public abstract void accept(IMetadataVisitor visitor); +}
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/IInstallableUnitConstants.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/IInstallableUnitConstants.java new file mode 100644 index 000000000..36c73a0b8 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/IInstallableUnitConstants.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.metadata; + +/** + * Definitions for constants associated with InstallableUnits. + */ +public interface IInstallableUnitConstants { + + /* + * Keys for common properties that optionally + * be defined in InstallableUnits. + */ + public String NAME = "equinox.prov.name"; //$NON-NLS-1$ + public String DESCRIPTION = "equinox.prov.description"; //$NON-NLS-1$ + public String DOC_URL = "equinox.prov.doc.url"; //$NON-NLS-1$ + public String PROVIDER = "equinox.prov.provider"; //$NON-NLS-1$ + public String CONTACT = "equinox.prov.contact"; //$NON-NLS-1$ + public String LICENSE = "equinox.prov.license"; //$NON-NLS-1$ + public String COPYRIGHT = "equinox.prov.copyright"; //$NON-NLS-1$ + public String UPDATE_SITE = "equinox.prov.update.site"; //$NON-NLS-1$ + public String UPDATE_FROM = "equinox.prov.update.from"; //$NON-NLS-1$ + public String UPDATE_RANGE = "equinox.prov.update.range"; //$NON-NLS-1$ + + //TODO This is not the ideal location for these constants + public String ENTRYPOINT_IU_KEY = "entryPoint"; //$NON-NLS-1$ + public static final String PROFILE_IU_KEY = "profileIU"; //$NON-NLS-1$ + +} diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/IInstallableUnitFragment.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/IInstallableUnitFragment.java new file mode 100644 index 000000000..5f11ed83b --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/IInstallableUnitFragment.java @@ -0,0 +1,19 @@ +/******************************************************************************* + * 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.metadata; + +import org.eclipse.osgi.service.resolver.VersionRange; + +public interface IInstallableUnitFragment extends IInstallableUnit { + + public abstract String getHostId(); + + public abstract VersionRange getHostVersionRange(); + +}
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/IMetadataVisitor.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/IMetadataVisitor.java new file mode 100644 index 000000000..737afd742 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/IMetadataVisitor.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.metadata; + +public interface IMetadataVisitor { + public void visitInstallableUnit(IInstallableUnit iu); + + public void visitCapability(ProvidedCapability capability); + + public void visitRequiredCapability(RequiredCapability capability); + +} diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/IResolvedInstallableUnit.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/IResolvedInstallableUnit.java new file mode 100644 index 000000000..e73ad5565 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/IResolvedInstallableUnit.java @@ -0,0 +1,16 @@ +/******************************************************************************* + * 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.metadata; + +public interface IResolvedInstallableUnit extends IInstallableUnit { + + public abstract IInstallableUnitFragment[] getFragments(); + + public abstract IInstallableUnit getOriginal(); +}
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/IResolvedInstallableUnitFragment.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/IResolvedInstallableUnitFragment.java new file mode 100644 index 000000000..eb1b34e6a --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/IResolvedInstallableUnitFragment.java @@ -0,0 +1,13 @@ +/******************************************************************************* + * 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.metadata; + +public interface IResolvedInstallableUnitFragment extends IInstallableUnitFragment, IResolvedInstallableUnit { + +} diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/Inclusion.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/Inclusion.java new file mode 100644 index 000000000..7ba050b2d --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/Inclusion.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.metadata; + +public abstract class Inclusion { + String selectorId; + + public String getSelectorId() { + return selectorId; + } + + public abstract void accept(IMetadataVisitor visitor); +} diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/InstallableUnit.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/InstallableUnit.java new file mode 100644 index 000000000..000911032 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/InstallableUnit.java @@ -0,0 +1,217 @@ +/******************************************************************************* + * 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.metadata; + +import org.eclipse.equinox.internal.prov.metadata.InternalInstallableUnit; +import org.eclipse.equinox.prov.core.helpers.OrderedProperties; +import org.eclipse.equinox.prov.core.helpers.UnmodifiableProperties; +import org.osgi.framework.Version; + +public class InstallableUnit implements IInstallableUnitConstants, IInstallableUnit, InternalInstallableUnit { + private static final RequiredCapability[] NO_REQUIRES = new RequiredCapability[0]; + private static final OrderedProperties NO_PROPERTIES = new OrderedProperties(); + + private String id; + private transient Version versionObject; + private String version; + private boolean singleton; + + private OrderedProperties properties; + + private IArtifactKey[] artifacts; + private TouchpointType touchpointType; + private TouchpointData immutableTouchpointData; + + private RequiredCapability[] requires; + + private String filter; + + String applicabilityFilter; + + ProvidedCapability[] providedCapabilities = new ProvidedCapability[0]; + + public InstallableUnit() { + super(); + } + + public TouchpointType getTouchpointType() { + return touchpointType == null ? TouchpointType.NONE : touchpointType; + } + + public String getId() { + return id; + } + + public String getFilter() { + return filter; + } + + public Version getVersion() { + if (versionObject == null) + versionObject = version == null ? Version.emptyVersion : new Version(version); + return versionObject; + } + + public IArtifactKey[] getArtifacts() { + return artifacts; + } + + public void setId(String id) { + this.id = id; + } + + public void setVersion(Version newVersion) { + this.versionObject = newVersion; + this.version = newVersion == null ? null : newVersion.toString(); + } + + public void setTouchpointType(TouchpointType type) { + this.touchpointType = type == TouchpointType.NONE ? null : type; + } + + public void setArtifacts(IArtifactKey[] value) { + artifacts = value; + } + + public RequiredCapability[] getRequiredCapabilities() { + return requires != null ? requires : NO_REQUIRES; + + } + + public ProvidedCapability[] getProvidedCapabilities() { + ProvidedCapability self = new ProvidedCapability(IU_NAMESPACE, id, getVersion()); + if (providedCapabilities == null) + return new ProvidedCapability[] {self}; + + ProvidedCapability[] result = new ProvidedCapability[providedCapabilities.length + 1]; + result[0] = self; + System.arraycopy(providedCapabilities, 0, result, 1, providedCapabilities.length); + return result; + } + + public void setRequiredCapabilities(RequiredCapability[] capabilities) { + if (capabilities == NO_REQUIRES) { + this.requires = null; + } else { + //copy array for safety + this.requires = (RequiredCapability[]) capabilities.clone(); + } + } + + public void accept(IMetadataVisitor visitor) { + visitor.visitInstallableUnit(this); + } + + public boolean isSingleton() { + return singleton; + } + + public void setSingleton(boolean singleton) { + this.singleton = singleton; + } + + public String getProperty(String key) { + return getProperties().getProperty(key); + } + + public String setProperty(String key, String value) { + if (properties == null) + properties = new OrderedProperties(); + return (String) properties.setProperty(key, value); + } + + public String toString() { + return id + ' ' + getVersion(); + } + + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + result = prime * result + ((getVersion() == null) ? 0 : getVersion().hashCode()); + return result; + } + + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (!(obj instanceof IInstallableUnit)) + return false; + final IInstallableUnit other = (IInstallableUnit) obj; + if (id == null) { + if (other.getId() != null) + return false; + } else if (!id.equals(other.getId())) + return false; + if (getVersion() == null) { + if (other.getVersion() != null) + return false; + } else if (!getVersion().equals(other.getVersion())) + return false; + return true; + } + + public void setFilter(String filter) { + this.filter = filter; + } + + public TouchpointData[] getTouchpointData() { + return immutableTouchpointData == null ? TouchpointData.NO_TOUCHPOINT_DATA : new TouchpointData[] {immutableTouchpointData}; + } + + public void setImmutableTouchpointData(TouchpointData immutableData) { + this.immutableTouchpointData = immutableData; + } + + OrderedProperties getProperties() { + return properties == null ? NO_PROPERTIES : properties; + } + + /** + * Get an <i>unmodifiable copy</i> of the properties + * associated with the installable unit. + * + * @return an <i>unmodifiable copy</i> of the IU properties. + */ + public OrderedProperties copyProperties() { + return (properties != null ? new UnmodifiableProperties(getProperties()) : new UnmodifiableProperties(new OrderedProperties())); + } + + public boolean isFragment() { + return false; + } + + public void setCapabilities(ProvidedCapability[] exportedCapabilities) { + providedCapabilities = exportedCapabilities; + } + + public void setApplicabilityFilter(String ldapFilter) { + applicabilityFilter = ldapFilter; + } + + public String getApplicabilityFilter() { + return applicabilityFilter; + } + + public IResolvedInstallableUnit getResolved() { + return new ResolvedInstallableUnit(this); + } + + public int compareTo(Object toCompareTo) { + if (!(toCompareTo instanceof IInstallableUnit)) { + return -1; + } + IInstallableUnit other = (IInstallableUnit) toCompareTo; + if (getId().compareTo(other.getId()) == 0) + return (getVersion().compareTo(other.getVersion())); + return getId().compareTo(other.getId()); + } +} diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/InstallableUnitFragment.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/InstallableUnitFragment.java new file mode 100644 index 000000000..74180a9c8 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/InstallableUnitFragment.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * 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.metadata; + +import org.eclipse.osgi.service.resolver.VersionRange; +import org.osgi.framework.Version; + +public class InstallableUnitFragment extends InstallableUnit implements IInstallableUnitFragment, IInstallableUnit { + public static ProvidedCapability FRAGMENT_CAPABILITY = new ProvidedCapability(IU_KIND_NAMESPACE, "iu.fragment", new Version(1, 0, 0)); + + private String hostId; + private transient VersionRange hostRangeObject; + private String hostRange; + + public ProvidedCapability[] getProvidedCapabilities() { + ProvidedCapability[] otherCapabilities = super.getProvidedCapabilities(); + if (otherCapabilities.length == 0) + return new ProvidedCapability[] {FRAGMENT_CAPABILITY}; + ProvidedCapability[] result = new ProvidedCapability[otherCapabilities.length + 1]; + System.arraycopy(otherCapabilities, 0, result, 1, otherCapabilities.length); + result[0] = FRAGMENT_CAPABILITY; + return result; + } + + public void setHost(String iuId, VersionRange versionRange) { + if (iuId == null || versionRange == null) + throw new IllegalArgumentException(); + hostId = iuId; + hostRangeObject = versionRange; + hostRange = versionRange == null ? null : versionRange.toString(); + addRequiredCapability(RequiredCapability.createRequiredCapabilityForName(iuId, versionRange, false)); + } + + public String getHostId() { + return hostId; + } + + public VersionRange getHostVersionRange() { + if (hostRangeObject == null) + hostRangeObject = hostRange == null ? VersionRange.emptyRange : new VersionRange(hostRange); + return hostRangeObject; + } + + private void addRequiredCapability(RequiredCapability toAdd) { + RequiredCapability[] current = super.getRequiredCapabilities(); + RequiredCapability[] result = new RequiredCapability[current.length + 1]; + System.arraycopy(current, 0, result, 0, current.length); + result[current.length] = toAdd; + setRequiredCapabilities(result); + } + + public boolean isFragment() { + return true; + } + + public IResolvedInstallableUnit getResolved() { + return new ResolvedInstallableUnitFragment(this); + } +} diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/ProvidedCapability.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/ProvidedCapability.java new file mode 100644 index 000000000..ffe074ded --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/ProvidedCapability.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * 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.metadata; + +import org.osgi.framework.Version; + +/** + * Describes a capability as exposed or required by an installable unit + */ +public class ProvidedCapability { + String namespace; + String name; + transient Version versionObject; + String version; + + public String getNamespace() { + return namespace; + } + + public String getName() { + return name; + } + + public Version getVersion() { + if (versionObject == null) + versionObject = version == null ? Version.emptyVersion : new Version(version); + return versionObject; + } + + public ProvidedCapability(String namespace, String name, Version newVersion) { + this.name = name; + this.versionObject = newVersion; + this.version = newVersion == null ? null : newVersion.toString(); + this.namespace = namespace; + } + + public boolean isSatisfiedBy(RequiredCapability candidate) { + if (getName() == null || !getName().equals(candidate.getName())) + return false; + if (getNamespace() == null || !getNamespace().equals(candidate.getNamespace())) + return false; + return candidate.getRange().isIncluded(getVersion()); + } + + public void accept(IMetadataVisitor visitor) { + visitor.visitCapability(this); + } + + public boolean equals(Object other) { + if (other instanceof ProvidedCapability) { + ProvidedCapability otherCapability = (ProvidedCapability) other; + return otherCapability.namespace.equals(namespace) && otherCapability.name.equals(name) && otherCapability.getVersion().equals(getVersion()); + } + return false; + } + + public int hashCode() { + return namespace.hashCode() * name.hashCode() * getVersion().hashCode(); + } + + public String toString() { + return namespace + '/' + name + '/' + getVersion(); + } + +} diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/Recommendation.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/Recommendation.java new file mode 100644 index 000000000..e3ff45ca4 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/Recommendation.java @@ -0,0 +1,125 @@ +/******************************************************************************* + * 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.metadata; + +import org.eclipse.osgi.service.resolver.VersionRange; +import org.osgi.framework.Version; + +public class Recommendation { + private RequiredCapability applyOn; + private RequiredCapability newValue; + + public Recommendation(RequiredCapability applyOn2, RequiredCapability newValue2) { + this.applyOn = applyOn2; + this.newValue = newValue2; + } + + public RequiredCapability applyOn() { + return applyOn; + } + + public RequiredCapability newValue() { + return newValue; + } + + public boolean matches(RequiredCapability toMatch) { + if (!toMatch.getNamespace().equals(applyOn.getNamespace())) + return false; + if (!toMatch.getName().equals(applyOn.getName())) + return false; + if (toMatch.getRange().equals(applyOn.getRange())) + return true; + + //TODO Here, in the long run we want to be smarter .for example we could check that the range of the match is a subset of the range specified on applyOn. + return false; + } + + boolean matches(Recommendation toMatch) { + return matches(toMatch.applyOn()); + } + + protected Recommendation merge(Recommendation r2) { + VersionRange result = intersect(newValue().getRange(), r2.newValue().getRange()); + if (result == null) + return null; + return new Recommendation(applyOn, new RequiredCapability(applyOn.getNamespace(), applyOn.getName(), result)); + } + + private VersionRange intersect(VersionRange r1, VersionRange r2) { + Version resultMin = null; + boolean resultMinIncluded = false; + Version resultMax = null; + boolean resultMaxIncluded = false; + + int minCompare = r1.getMinimum().compareTo(r2.getMinimum()); + if (minCompare < 0) { + resultMin = r2.getMinimum(); + resultMinIncluded = r2.getIncludeMinimum(); + } else if (minCompare > 0) { + resultMin = r1.getMinimum(); + resultMinIncluded = r1.getIncludeMinimum(); + } else if (minCompare == 0) { + resultMin = r1.getMinimum(); + resultMinIncluded = r1.getIncludeMinimum() && r2.getIncludeMinimum(); + } + + int maxCompare = r1.getMaximum().compareTo(r2.getMaximum()); + if (maxCompare > 0) { + resultMax = r2.getMaximum(); + resultMaxIncluded = r2.getIncludeMaximum(); + } else if (maxCompare < 0) { + resultMax = r1.getMaximum(); + resultMaxIncluded = r1.getIncludeMaximum(); + } else if (maxCompare == 0) { + resultMax = r1.getMaximum(); + resultMaxIncluded = r1.getIncludeMaximum() && r2.getIncludeMaximum(); + } + + int resultRangeComparison = resultMin.compareTo(resultMax); + if (resultRangeComparison < 0) + return new VersionRange(resultMin, resultMinIncluded, resultMax, resultMaxIncluded); + else if (resultRangeComparison == 0 && resultMinIncluded == resultMaxIncluded) + return new VersionRange(resultMin, resultMinIncluded, resultMax, resultMaxIncluded); + else + return null; + } + + public boolean isCompatible(Recommendation other) { + return intersect(newValue.getRange(), other.newValue.getRange()) != null; + } + + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((applyOn == null) ? 0 : applyOn.hashCode()); + result = prime * result + ((newValue == null) ? 0 : newValue.hashCode()); + return result; + } + + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final Recommendation other = (Recommendation) obj; + if (applyOn == null) { + if (other.applyOn != null) + return false; + } else if (!applyOn.equals(other.applyOn)) + return false; + if (newValue == null) { + if (other.newValue != null) + return false; + } else if (!newValue.equals(other.newValue)) + return false; + return true; + } +}
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/RecommendationDescriptor.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/RecommendationDescriptor.java new file mode 100644 index 000000000..4a6722074 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/RecommendationDescriptor.java @@ -0,0 +1,116 @@ +/******************************************************************************* + * 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.metadata; + +import java.util.*; +import org.eclipse.core.runtime.*; +import org.eclipse.equinox.internal.prov.metadata.MetadataActivator; +import org.eclipse.osgi.service.resolver.VersionRange; + +public class RecommendationDescriptor { + public static final String TOUCHPOINT_DATA_KEY = "recommendations"; + public static final String KIND = "recommendation"; + + private Set recommendations; + + public RecommendationDescriptor(Set recommendations) { + this.recommendations = recommendations; + } + + public Set getRecommendations() { + return recommendations; + } + + public Recommendation findRecommendation(RequiredCapability toMatch) { + for (Iterator iterator = recommendations.iterator(); iterator.hasNext();) { + Recommendation name = (Recommendation) iterator.next(); + if (name.matches(toMatch)) + return name; + } + return null; + } + + public Recommendation findRecommendation(Recommendation toMatch) { + for (Iterator iterator = recommendations.iterator(); iterator.hasNext();) { + Recommendation name = (Recommendation) iterator.next(); + if (name.matches(toMatch)) + return name; + } + return null; + } + + //Merge the other descriptor into this one. Return an OK Status is the merged succeeded, otherwise return an INFO Status + public IStatus merge(RecommendationDescriptor other) { + MultiStatus result = null; + for (Iterator it = other.recommendations.iterator(); it.hasNext();) { + Recommendation otherRecommendation = (Recommendation) it.next(); + Recommendation matchInThis = findRecommendation(otherRecommendation); + if (matchInThis == null) { + recommendations.add(otherRecommendation); + continue; + } + Recommendation newRec = otherRecommendation.merge(matchInThis); + if (newRec != null) { + recommendations.remove(matchInThis); + recommendations.add(newRec); + continue; + } else { + if (result == null) + result = new MultiStatus(MetadataActivator.PI_METADATA, 0, "Conflict between recommendations", null); + result.add(new Status(IStatus.INFO, MetadataActivator.PI_METADATA, "can't merge " + otherRecommendation + " with " + matchInThis)); + } + } + if (result == null) + return Status.OK_STATUS; + return result; + + } + + public static RecommendationDescriptor parse(String descriptor) { + StringTokenizer entries = new StringTokenizer(descriptor, "\n"); + Set recommendations = new HashSet(entries.countTokens()); + while (entries.hasMoreElements()) { + StringTokenizer oneRec = new StringTokenizer((String) entries.nextElement(), "/"); + if (oneRec.countTokens() != 4) { + //format error, ignore and continue + + continue; + } + String ns = oneRec.nextToken().trim(); + String name = oneRec.nextToken().trim(); + String oldRange = oneRec.nextToken().trim(); + String newRange = oneRec.nextToken().trim(); + recommendations.add(new Recommendation(new RequiredCapability(ns, name, new VersionRange(oldRange)), new RequiredCapability(ns, name, new VersionRange(newRange)))); + } + return new RecommendationDescriptor(recommendations); + } + + public static String serialize(RecommendationDescriptor toSerialize) { + StringBuffer result = new StringBuffer(); + for (Iterator iterator = toSerialize.recommendations.iterator(); iterator.hasNext();) { + Recommendation entry = (Recommendation) iterator.next(); + result.append(entry.applyOn().getNamespace() + '/' + entry.applyOn().getName() + '/' + entry.applyOn().getRange().toString() + '/' + entry.newValue().getRange().toString() + '\n'); + } + return result.toString(); + } + + public boolean isCompatible(RecommendationDescriptor other) { + for (Iterator it = other.recommendations.iterator(); it.hasNext();) { + Recommendation otherRecommendation = (Recommendation) it.next(); + Recommendation matchInThis = findRecommendation(otherRecommendation); + if (matchInThis == null) { + continue; + } + if (!otherRecommendation.isCompatible(matchInThis)) + return false; + } + return true; + + } +} diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/RequiredCapability.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/RequiredCapability.java new file mode 100644 index 000000000..3ad8a8ee8 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/RequiredCapability.java @@ -0,0 +1,158 @@ +/******************************************************************************* + * 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.metadata; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.osgi.service.resolver.VersionRange; + +/** + * A required capability represents some external constraint on an {@link InstallableUnit}. + * Each capability represents something an {@link InstallableUnit} needs that + * it expects to be provided by another {@link InstallableUnit}. Capabilities are + * entirely generic, and are intended to be capable of representing anything that + * an {@link InstallableUnit} may need either at install time, or at runtime. + * <p> + * Capabilities are segmented into namespaces. Anyone can introduce new + * capability namespaces. Some well-known namespaces are introduced directly + * by the provisioning framework. + * + * @see InstallableUnit#IU_KIND_NAMESPACE + * @see InstallableUnit#IU_NAMESPACE + */ +public class RequiredCapability { + private String filter; + + private boolean multiple; + private String name; + private String namespace; + boolean optional; + private String range; + private String[] selectors; + private transient VersionRange rangeObject; + + /** + * Returns a {@link RequiredCapability} on the installable unit with the given name + * and version range. + */ + public static RequiredCapability createRequiredCapabilityForName(String name, VersionRange versionRange, boolean optional) { + return new RequiredCapability(IInstallableUnit.IU_NAMESPACE, name, versionRange, null, optional, false); + } + + public RequiredCapability(String namespace, String name, VersionRange range) { + this(namespace, name, range, null, false, false); + } + + public RequiredCapability(String namespace, String name, VersionRange range, String filter, boolean optional, boolean multiple) { + this(namespace, name, range, null, filter, optional, multiple); + } + + public RequiredCapability(String namespace, String name, VersionRange range, String[] selectors, String filter, boolean optional, boolean multiple) { + Assert.isNotNull(namespace); + Assert.isNotNull(name); + this.namespace = namespace; + this.name = name; + this.rangeObject = range; + this.range = rangeObject == null ? null : rangeObject.toString(); + this.selectors = selectors == null ? new String[0] : selectors; + this.optional = optional; + this.filter = filter; + this.multiple = multiple; + } + + public void accept(IMetadataVisitor visitor) { + visitor.visitRequiredCapability(this); + } + + public String getFilter() { + return filter; + } + + public String getName() { + return name; + } + + public String getNamespace() { + return namespace; + } + + public VersionRange getRange() { + if (rangeObject == null) + rangeObject = range == null ? VersionRange.emptyRange : new VersionRange(range); + return rangeObject; + } + + public boolean isMultiple() { + return multiple; + } + + public boolean isOptional() { + return optional; + } + + public String toString() { + return "requiredCapability: " + namespace + '/' + name + '/' + range; + } + + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((filter == null) ? 0 : filter.hashCode()); + result = prime * result + (multiple ? 1231 : 1237); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((namespace == null) ? 0 : namespace.hashCode()); + result = prime * result + (optional ? 1231 : 1237); + result = prime * result + ((rangeObject == null) ? 0 : rangeObject.hashCode()); + return result; + } + + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final RequiredCapability other = (RequiredCapability) obj; + if (filter == null) { + if (other.filter != null) + return false; + } else if (!filter.equals(other.filter)) + return false; + if (multiple != other.multiple) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (namespace == null) { + if (other.namespace != null) + return false; + } else if (!namespace.equals(other.namespace)) + return false; + if (optional != other.optional) + return false; + if (rangeObject == null) { + if (other.rangeObject != null) + return false; + } else if (!rangeObject.equals(other.rangeObject)) + return false; + return true; + } + + /** + * Returns the properties to use for evaluating required capability filters + * downstream from this capability. For example, if the selector "doc" + * is provided, then a downstream InstallableUnit with a required capability + * filtered with "doc=true" will be included. + */ + public String[] getSelectors() { + return selectors; + } +} diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/ResolvedInstallableUnit.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/ResolvedInstallableUnit.java new file mode 100644 index 000000000..f6f5bc034 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/ResolvedInstallableUnit.java @@ -0,0 +1,148 @@ +/******************************************************************************* + * 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.metadata; + +import java.util.ArrayList; +import java.util.Arrays; +import org.eclipse.equinox.internal.prov.metadata.InternalInstallableUnit; +import org.osgi.framework.Version; + +public class ResolvedInstallableUnit implements IResolvedInstallableUnit, InternalInstallableUnit { + private static IInstallableUnit[] NO_IU = new IInstallableUnit[0]; + + private IInstallableUnit[] fragments = NO_IU; + protected InstallableUnit resolved; + + public ResolvedInstallableUnit(InstallableUnit resolved) { + this.resolved = resolved; + } + + public void setFragments(IResolvedInstallableUnit[] fragments) { + this.fragments = fragments; + } + + public IInstallableUnitFragment[] getFragments() { + ArrayList result = new ArrayList(); + if (fragments != null) + result.addAll(Arrays.asList(fragments)); + for (int i = 0; i < result.size(); i++) { + result.addAll(Arrays.asList(((IResolvedInstallableUnit) result.get(i)).getFragments())); + } + return (IInstallableUnitFragment[]) result.toArray(new IInstallableUnitFragment[result.size()]); + } + + public String getApplicabilityFilter() { + return resolved.getApplicabilityFilter(); + } + + public IArtifactKey[] getArtifacts() { + return resolved.getArtifacts(); + } + + public String getFilter() { + return resolved.getFilter(); + } + + public String getId() { + return resolved.getId(); + } + + public String getProperty(String key) { + return resolved.getProperty(key); + } + + public ProvidedCapability[] getProvidedCapabilities() { + ArrayList result = new ArrayList(); + result.addAll(Arrays.asList(resolved.getProvidedCapabilities())); + for (int i = 0; i < fragments.length; i++) { + result.addAll(Arrays.asList(fragments[i].getProvidedCapabilities())); + } + return resolved.getProvidedCapabilities(); + } + + public RequiredCapability[] getRequiredCapabilities() { + ArrayList result = new ArrayList(); + result.addAll(Arrays.asList(resolved.getRequiredCapabilities())); + for (int i = 0; i < fragments.length; i++) { + result.addAll(Arrays.asList(fragments[i].getRequiredCapabilities())); + } + return (RequiredCapability[]) result.toArray(new RequiredCapability[result.size()]); + + } + + public TouchpointData[] getTouchpointData() { + ArrayList result = new ArrayList(); + result.addAll(Arrays.asList(resolved.getTouchpointData())); + for (int i = 0; i < fragments.length; i++) { + TouchpointData[] data = fragments[i].getTouchpointData(); + for (int j = 0; j < data.length; j++) { + result.add(data[j]); + } + } + return (TouchpointData[]) result.toArray(new TouchpointData[result.size()]); + } + + public TouchpointType getTouchpointType() { + return resolved.getTouchpointType(); + } + + public Version getVersion() { + return resolved.getVersion(); + } + + public boolean isFragment() { + return resolved.isFragment(); + } + + public boolean isSingleton() { + return resolved.isSingleton(); + } + + public void accept(IMetadataVisitor visitor) { + visitor.visitInstallableUnit(this); + } + + public boolean equals(Object obj) { + //TODO This is pretty ugly.... + boolean result = resolved.equals(obj); + if (result) + return true; + if (obj instanceof ResolvedInstallableUnit) + return resolved.equals(((ResolvedInstallableUnit) obj).resolved); + return false; + } + + public int hashCode() { + // TODO Auto-generated method stub + return resolved.hashCode(); + } + + public String toString() { + return "[R]" + resolved.toString(); + } + + public IInstallableUnit getOriginal() { + return resolved; + } + + public int compareTo(Object toCompareTo) { + if (!(toCompareTo instanceof IInstallableUnit)) { + return -1; + } + IInstallableUnit other = (IInstallableUnit) toCompareTo; + if (getId().compareTo(other.getId()) == 0) + return (getVersion().compareTo(other.getVersion())); + return getId().compareTo(other.getId()); + } + + public IResolvedInstallableUnit getResolved() { + return this; + } + +} diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/ResolvedInstallableUnitFragment.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/ResolvedInstallableUnitFragment.java new file mode 100644 index 000000000..f7532d2a9 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/ResolvedInstallableUnitFragment.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.metadata; + +import org.eclipse.osgi.service.resolver.VersionRange; + +public class ResolvedInstallableUnitFragment extends ResolvedInstallableUnit implements IResolvedInstallableUnitFragment { + + public ResolvedInstallableUnitFragment(InstallableUnitFragment resolved) { + super(resolved); + } + + public String getHostId() { + return ((InstallableUnitFragment) resolved).getHostId(); + } + + public VersionRange getHostVersionRange() { + return ((InstallableUnitFragment) resolved).getHostVersionRange(); + } +} diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/Selector.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/Selector.java new file mode 100644 index 000000000..a63f39bc3 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/Selector.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * 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.metadata; + +import java.util.Dictionary; +import org.eclipse.equinox.internal.prov.metadata.MetadataActivator; +import org.osgi.framework.InvalidSyntaxException; + +public class Selector { + private String id; + private String filter; + private boolean internal; + + public Selector(String id, String filter, boolean internal) { + this.id = id; + this.filter = filter; + this.internal = internal; + } + + public String getId() { + return id; + } + + public boolean eval(Dictionary context) { + try { + return MetadataActivator.context.createFilter(filter).match(context); + } catch (InvalidSyntaxException e) { + //TODO log something. though that should not happen + return false; + } + } + + public boolean isInternal() { + return internal; + } +} diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/TouchpointData.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/TouchpointData.java new file mode 100644 index 000000000..67b56c6de --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/TouchpointData.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * 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.metadata; + +import java.util.Map; + +public class TouchpointData { + public static TouchpointData[] NO_TOUCHPOINT_DATA = new TouchpointData[0]; + + /** + * Map of (String->String). The values represent the instructions. The set + * of keys supported is up to the touchpoint that will process these + * instructions + */ + private Map instructions; + + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((instructions == null) ? 0 : instructions.hashCode()); + return result; + } + + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final TouchpointData other = (TouchpointData) obj; + if (instructions == null) { + if (other.instructions != null) + return false; + } else if (!instructions.equals(other.instructions)) + return false; + return true; + } + + public TouchpointData(Map instructions) { + this.instructions = instructions; + } + + public String getInstructions(String instructionKey) { + return (String) instructions.get(instructionKey); + } +} diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/TouchpointType.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/TouchpointType.java new file mode 100644 index 000000000..1a99d8a2a --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/metadata/TouchpointType.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * 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.metadata; + +import org.osgi.framework.Version; + +/** + * Identifies a particular touchpoint. A touchpoint is identified by an id + * and a version. + */ +public class TouchpointType { + /** + * A touchpoint type indicating that the "null" touchpoint should be used. + * The null touchpoint does not participate in any install phase. + */ + public static final TouchpointType NONE = new TouchpointType("null", new Version("0")); //$NON-NLS-1$//$NON-NLS-2$ + private String id; + private Version versionObject; + private String version; + + public TouchpointType(String id, Version aVersion) { + this.id = id; + this.versionObject = aVersion; + this.version = aVersion == null ? null : aVersion.toString(); + } + + public String getId() { + return id; + } + + public Version getVersion() { + if (versionObject == null) + versionObject = version == null ? Version.emptyVersion : new Version(version); + return versionObject; + } + + public String toString() { + return "Touchpoint: " + id + ' ' + getVersion(); + } + + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + result = prime * result + ((getVersion() == null) ? 0 : getVersion().hashCode()); + return result; + } + + public boolean equals(Object obj) { + if (this == obj) + return true; + if (super.equals(obj)) + return true; + if (getClass() != obj.getClass()) + return false; + final TouchpointType other = (TouchpointType) obj; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + if (getVersion() == null) { + if (other.getVersion() != null) + return false; + } else if (!getVersion().equals(other.getVersion())) + return false; + return true; + } + +} diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/query/CompoundIterator.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/query/CompoundIterator.java new file mode 100644 index 000000000..73dfaa3dd --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/query/CompoundIterator.java @@ -0,0 +1,98 @@ +/******************************************************************************* + * 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.query; + +import java.util.*; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.equinox.internal.prov.metadata.Messages; +import org.eclipse.equinox.prov.metadata.IInstallableUnit; +import org.eclipse.equinox.prov.metadata.RequiredCapability; +import org.eclipse.osgi.service.resolver.VersionRange; + +public class CompoundIterator implements Iterator { + private Iterator[] iterators; + private String id; + private VersionRange range; + private RequiredCapability[] requirements; + private boolean and; + private int index = 0; + private boolean filtered = false; + private IInstallableUnit lookahead = null; + + public static IInstallableUnit[] asArray(Iterator i, IProgressMonitor progress) { + if (progress == null) + progress = new NullProgressMonitor(); + progress.beginTask(Messages.QUERY_PROGRESS, IProgressMonitor.UNKNOWN); + HashSet result = new HashSet(); + while (i.hasNext()) { + result.add(i.next()); + progress.worked(IProgressMonitor.UNKNOWN); + } + progress.done(); + return (IInstallableUnit[]) result.toArray(new IInstallableUnit[result.size()]); + } + + public CompoundIterator(Iterator[] iterators) { + this.iterators = iterators; + } + + public CompoundIterator(Iterator[] iterators, String id, VersionRange range, RequiredCapability[] requirements, boolean and) { + this(iterators); + this.id = id; + this.range = range; + this.requirements = requirements; + this.and = and; + filtered = true; + } + + public boolean hasNext() { + if (lookahead != null) + return true; + if (index >= iterators.length) + return false; + if (filtered) { + while (iterators[index].hasNext()) { + IInstallableUnit next = (IInstallableUnit) iterators[index].next(); + if (Query.match(next, id, range, requirements, and)) { + lookahead = next; + return true; + } + } + } else { + if (iterators[index].hasNext()) + return true; + } + index++; + return hasNext(); + } + + public Object next() { + if (lookahead != null) { + IInstallableUnit result = lookahead; + lookahead = null; + return result; + } + if (index >= iterators.length) + throw new NoSuchElementException(); + while (iterators[index].hasNext()) { + IInstallableUnit next = (IInstallableUnit) iterators[index].next(); + if (!filtered) + return next; + if (Query.match(next, id, range, requirements, and)) + return next; + } + index++; + return next(); + } + + public void remove() { + throw new UnsupportedOperationException(); + } +} diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/query/IQueryable.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/query/IQueryable.java new file mode 100644 index 000000000..7811a750a --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/query/IQueryable.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.query; + +import java.util.Iterator; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.equinox.prov.metadata.IInstallableUnit; +import org.eclipse.equinox.prov.metadata.RequiredCapability; +import org.eclipse.osgi.service.resolver.VersionRange; + +public interface IQueryable { + + IInstallableUnit[] query(String id, VersionRange range, RequiredCapability[] requirements, boolean and, IProgressMonitor progress); + + Iterator getIterator(String id, VersionRange range, RequiredCapability[] requirements, boolean and); + +} diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/query/Query.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/query/Query.java new file mode 100644 index 000000000..ac91489ed --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/query/Query.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * 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.query; + +import java.util.ArrayList; +import java.util.Iterator; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.equinox.internal.prov.metadata.Messages; +import org.eclipse.equinox.prov.metadata.*; +import org.eclipse.osgi.service.resolver.VersionRange; + +public class Query { + + public static boolean match(IInstallableUnit source, String id, VersionRange range, RequiredCapability[] requirements, boolean and) { + if (id != null && !source.getId().equals(id)) + return false; + if (range != null && !range.isIncluded(source.getVersion())) + return false; + if (requirements == null) + return true; + // if any of the requirements are met by any of the capabilities of the source... + for (int k = 0; k < requirements.length; k++) { + boolean valid = false; + ProvidedCapability[] capabilities = source.getProvidedCapabilities(); + for (int j = 0; j < capabilities.length; j++) + //TODO Need to deal with option and multiplicity flag + if ((requirements[k].getName().equals(capabilities[j].getName()) && requirements[k].getNamespace().equals(capabilities[j].getNamespace()) && (requirements[k].getRange() == null ? true : requirements[k].getRange().isIncluded(capabilities[j].getVersion())))) { + valid = true; + } + // if we are OR'ing then the first time we find a requirement that is met, return success + if (valid && !and) + return true; + // if we are AND'ing then the first time we find a requirement that is NOT met, return failure + if (!valid && and) + return false; + } + // if we get past the requirements check and we are AND'ing then return true + // since all requirements must have been met. If we are OR'ing then return false + // since none of the requirements were met. + return and; + } + + public static IInstallableUnit[] query(IQueryable[] sources, String id, VersionRange range, RequiredCapability[] requirements, boolean and, IProgressMonitor progress) { + if (progress == null) + progress = new NullProgressMonitor(); + + progress.beginTask(Messages.QUERY_PROGRESS, sources.length); + ArrayList result = new ArrayList(); + for (int i = 0; i < sources.length; i++) { + IQueryable source = sources[i]; + IInstallableUnit[] list = source.query(id, range, requirements, and, progress); + for (int j = 0; j < list.length; j++) + result.add(list[j]); + progress.worked(1); + } + progress.done(); + return (IInstallableUnit[]) result.toArray(new IInstallableUnit[result.size()]); + } + + public static Iterator getIterator(IQueryable[] sources, String id, VersionRange range, RequiredCapability[] requirements, boolean and) { + Iterator[] result = new Iterator[sources.length]; + for (int i = 0; i < sources.length; i++) + result[i] = sources[i].getIterator(id, range, requirements, and); + return new CompoundIterator(result); + } +} diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/query/QueryableArray.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/query/QueryableArray.java new file mode 100644 index 000000000..01177285e --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/query/QueryableArray.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * 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.query; + +import java.util.*; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.equinox.internal.prov.metadata.Messages; +import org.eclipse.equinox.prov.metadata.IInstallableUnit; +import org.eclipse.equinox.prov.metadata.RequiredCapability; +import org.eclipse.osgi.service.resolver.VersionRange; + +public class QueryableArray implements IQueryable { + private IInstallableUnit[] source; + + public QueryableArray(IInstallableUnit[] source) { + this.source = source; + } + + public Iterator getIterator(String id, VersionRange range, RequiredCapability[] requirements, boolean and) { + Iterator i = Arrays.asList(source).iterator(); + return new CompoundIterator(new Iterator[] {i}, id, range, requirements, and); + } + + public IInstallableUnit[] query(String id, VersionRange range, RequiredCapability[] requirements, boolean and, IProgressMonitor progress) { + if (progress == null) + progress = new NullProgressMonitor(); + progress.beginTask(Messages.QUERY_PROGRESS, source.length); + Set result = new HashSet(); + for (int i = 0; i < source.length; i++) { + if (Query.match(source[i], id, range, requirements, and)) + result.add(source[i]); + progress.worked(1); + } + progress.done(); + return (IInstallableUnit[]) result.toArray(new IInstallableUnit[result.size()]); + + } +} diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/resolution/ResolutionHelper.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/resolution/ResolutionHelper.java new file mode 100644 index 000000000..5eceae0d1 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/resolution/ResolutionHelper.java @@ -0,0 +1,171 @@ +/******************************************************************************* + * 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.resolution; + +import java.util.*; +import org.eclipse.equinox.internal.prov.metadata.InternalInstallableUnit; +import org.eclipse.equinox.internal.prov.metadata.MetadataActivator; +import org.eclipse.equinox.prov.metadata.*; +import org.eclipse.osgi.service.resolver.*; +import org.osgi.framework.ServiceReference; + +public class ResolutionHelper { + private static boolean DEBUG = false; + + private Transformer transformer; + private State state; + private Dictionary selectionContext; + private RecommendationDescriptor recommendations; + + public ResolutionHelper(Dictionary selectionContext, RecommendationDescriptor recommendations) { + this.selectionContext = selectionContext; + this.recommendations = recommendations; + } + + private void initialize() { + ServiceReference sr = MetadataActivator.context.getServiceReference(PlatformAdmin.class.getName()); + PlatformAdmin pa = (PlatformAdmin) MetadataActivator.context.getService(sr); + transformer = new Transformer(pa.getFactory(), selectionContext, recommendations); + state = pa.getFactory().createState(true); + if (selectionContext != null) + state.setPlatformProperties(selectionContext); + } + + private void addToState(BundleDescription bd) { + state.addBundle(bd); + } + + private BundleDescription addInResolution(IInstallableUnit toAdd) { + toAdd.accept(transformer); + // transformer.visitInstallableUnit(toAdd); + BundleDescription descriptionToAdd = transformer.getResult(); + // bundleDescriptionToIU.put(descriptionToAdd, toAdd); + addToState(descriptionToAdd); + return descriptionToAdd; + } + + /** + * Indicates if the installable unit to install will have all their constraints satisfied when installed with other installable units. + * @param toInstall the installable units to install + * @param existingState the other installable units to resolve against + * @return true if the installable unit to install resolves, return false otherwise. + */ + public UnsatisfiedCapability[] install(Set toInstall, Set existingState) { + initialize(); + BundleDescription[] addedBundle = new BundleDescription[toInstall.size()]; + int j = 0; + for (Iterator iterator = toInstall.iterator(); iterator.hasNext();) { + addedBundle[j++] = addInResolution((IInstallableUnit) iterator.next()); + } + + for (Iterator iterator = existingState.iterator(); iterator.hasNext();) { + addInResolution((IInstallableUnit) iterator.next()); + } + + state.resolve(); //We may want to resolve in two times. first the existing state, then add the toInstall. This would allow to see what changes when dropping the new iu. + //Also it could allow us to do an incremental resolution. however the results may differ + + ArrayList results = new ArrayList(); + for (int i = 0; i < addedBundle.length; i++) { + results.addAll(createUnsatisfiedCapabilities(state.getStateHelper().getUnsatisfiedConstraints(addedBundle[i]), addedBundle[i])); + } + return (UnsatisfiedCapability[]) results.toArray(new UnsatisfiedCapability[results.size()]); + + } + + private ArrayList createUnsatisfiedCapabilities(VersionConstraint[] unsatisfied, BundleDescription description) { + ArrayList results = new ArrayList(); + for (int i = 0; i < unsatisfied.length; i++) { + RequiredCapability originalDependency = (RequiredCapability) ((StateMetadataMap) description.getUserObject()).getGenericSpecifications().get(unsatisfied[i]); + results.add(new UnsatisfiedCapability(originalDependency, ((StateMetadataMap) description.getUserObject()).getUnit())); + } + return results; + } + + /** + * Associates installable unit fragments to each IU being installed. + * + * TODO: This method should probably be renamed to attachFragments + */ + public Collection attachCUs(Collection toAttach) { + initialize(); + Collection result = new HashSet(toAttach.size()); + for (Iterator iterator = toAttach.iterator(); iterator.hasNext();) { + IResolvedInstallableUnit tmp = ((InternalInstallableUnit) iterator.next()).getResolved(); + result.add(tmp); + addInResolution(tmp); + } + state.resolve(); + BundleDescription[] bds = state.getBundles(); + for (int i = 0; i < bds.length; i++) { + if (DEBUG) { + ResolverError[] re = state.getResolverErrors(bds[i]); + for (int j = 0; j < re.length; j++) { + System.out.println(re[j]); + } + } + BundleDescription[] potentialIUFragments = state.getStateHelper().getDependentBundles(new BundleDescription[] {bds[i]}); + // TODO: We need to define a way to allow IUFragments to work together to do configuration work. + // For now we will select just one fragment by preferring a fragment that matches the host + + IInstallableUnit hostIU = ((StateMetadataMap) bds[i].getUserObject()).getUnit(); + IResolvedInstallableUnitFragment selectedFragment = null; + for (int k = 0; k < potentialIUFragments.length; k++) { + IInstallableUnit dependentIU = ((StateMetadataMap) potentialIUFragments[k].getUserObject()).getUnit(); + if (hostIU.equals(dependentIU)) + continue; + + if (dependentIU.isFragment()) { + IResolvedInstallableUnitFragment potentialFragment = (IResolvedInstallableUnitFragment) dependentIU; + + if (potentialFragment.getHostId() == null) { + // default fragment - we'll mark it selected but keep looking for a fragment that matches the host + selectedFragment = potentialFragment; + } else if (potentialFragment.getHostId().equals(hostIU.getId()) && potentialFragment.getHostVersionRange().isIncluded(hostIU.getVersion())) { + // matches host - we're done + selectedFragment = potentialFragment; + break; + } // otherwise keep looking + } + } + if (selectedFragment != null) + ((ResolvedInstallableUnit) hostIU).setFragments(new IResolvedInstallableUnit[] {selectedFragment}); + } + return result; + } + + public boolean isResolved(IInstallableUnit iu) { + return state.getBundle(iu.getId(), iu.getVersion()).isResolved(); + } + + public ArrayList getAllResolved() { + BundleDescription[] bd = state.getResolvedBundles(); + ArrayList result = new ArrayList(bd.length); + for (int i = 0; i < bd.length; i++) { + result.add(extractIU(bd[i])); + } + return result; + } + + private IInstallableUnit extractIU(BundleDescription bd) { + return ((StateMetadataMap) bd.getUserObject()).getUnit(); + } + + public List getSorted() { + BundleDescription[] toSort = state.getResolvedBundles(); + state.getStateHelper().sortBundles(toSort); + List result = new ArrayList(toSort.length); + for (int i = 0; i < toSort.length; i++) { + result.add(extractIU(toSort[i])); + } + return result; + } +} diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/resolution/StateMetadataMap.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/resolution/StateMetadataMap.java new file mode 100644 index 000000000..1fc262c5e --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/resolution/StateMetadataMap.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * 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.resolution; + +import java.util.Map; +import org.eclipse.equinox.prov.metadata.IInstallableUnit; + +//Instances of this class are stored in the user object slot of bundlescriptions to ease navigation between the two models. +public class StateMetadataMap { + private IInstallableUnit unit; + private Map correspondingSpecifications; //indexes in this array maps to the ones in the dependencies array. This is gross. TODO + + public StateMetadataMap(IInstallableUnit unit, Map correspondingSpecifications) { + super(); + this.unit = unit; + this.correspondingSpecifications = correspondingSpecifications; + } + + public IInstallableUnit getUnit() { + return unit; + } + + public Map getGenericSpecifications() { + return correspondingSpecifications; + } +} diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/resolution/Transformer.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/resolution/Transformer.java new file mode 100644 index 000000000..d9afe1cfa --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/resolution/Transformer.java @@ -0,0 +1,141 @@ +/******************************************************************************* + * 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.resolution; + +import java.util.*; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.equinox.internal.prov.metadata.MetadataActivator; +import org.eclipse.equinox.prov.core.helpers.LogHelper; +import org.eclipse.equinox.prov.metadata.*; +import org.eclipse.osgi.service.resolver.*; +import org.osgi.framework.InvalidSyntaxException; + +public class Transformer implements IMetadataVisitor { + private static final byte IU_KIND = 0; + private static final String IU_NAMESPACE = "iu.namespace"; + static long iuInternalId = 0; + + private Dictionary context = null; + private StateObjectFactory factory = null; + private ArrayList iuCapabilities; + private Map iuDependencies; + private byte kind = IU_KIND; + + private BundleDescription result = null; + + private RecommendationDescriptor recommendations = null; + + public Transformer(StateObjectFactory factory) { + this(factory, null, null); + } + + public Transformer(StateObjectFactory factory, Dictionary context, RecommendationDescriptor recommendations) { + this.factory = factory; + this.context = context; + this.recommendations = recommendations; + } + + private String getNamespace() { + switch (kind) { + case IU_KIND : + return IU_NAMESPACE; + default : + throw new IllegalStateException("unknown kind"); //This should not happen + } + } + + public BundleDescription getResult() { + return result; + } + + private boolean isEnabled(RequiredCapability capability) { + // If there is no context then be optimistic + if (context == null) + return true; + String filter = capability.getFilter(); + if (filter == null) + return true; + try { + return MetadataActivator.getContext().createFilter(filter).match(context); + } catch (InvalidSyntaxException e) { + // If we fail to parse the filter treat it as invalid and be optimistic + return true; + } + } + + private String toFilter(VersionRange range) { + if (range == null) + return null; + StringBuffer buf = new StringBuffer(); + buf.append("(&"); //$NON-NLS-1$ + buf.append("(version>=").append(range.getMinimum().toString()).append(')'); //$NON-NLS-1$ + if (!range.getIncludeMinimum()) + buf.append("(!(version=").append(range.getMinimum().toString()).append("))"); + buf.append("(version<=").append(range.getMaximum().toString()).append(')'); //$NON-NLS-1$ + if (!range.getIncludeMaximum()) + buf.append("(!(version=").append(range.getMaximum().toString()).append("))"); + buf.append(')'); + return buf.toString(); + } + + public void visitCapability(ProvidedCapability capability) { + iuCapabilities.add(factory.createGenericDescription(capability.getName(), capability.getNamespace(), capability.getVersion(), null)); + } + + public void visitInstallableUnit(IInstallableUnit toTransform) { + kind = IU_KIND; + + //Start with the dependencies + RequiredCapability[] requires = toTransform.getRequiredCapabilities(); + iuDependencies = new HashMap(requires.length); + for (int i = 0; i < requires.length; i++) { + requires[i].accept(this); + } + + //Do the capabilities + ProvidedCapability[] capabilities = toTransform.getProvidedCapabilities(); + iuCapabilities = new ArrayList(requires.length + 1); + for (int i = 0; i < capabilities.length; i++) { + capabilities[i].accept(this); + } + + //Add a capability representing the IU itself + iuCapabilities.add(factory.createGenericDescription(toTransform.getId(), getNamespace(), toTransform.getVersion(), null)); + + GenericSpecification[] genericSpecifications = new GenericSpecification[iuDependencies.size()]; + iuDependencies.keySet().toArray(genericSpecifications); + + GenericDescription[] genericDescriptions = new GenericDescription[iuCapabilities.size()]; + iuCapabilities.toArray(genericDescriptions); + + //Finally create the bundle description + //TODO Need to create the filter for the IU itself + result = factory.createBundleDescription(iuInternalId++, toTransform.getId(), toTransform.getVersion(), (String) null, (BundleSpecification[]) null, (HostSpecification) null, (ImportPackageSpecification[]) null, (ExportPackageDescription[]) null, toTransform.isSingleton(), true, true, toTransform.getFilter(), (String[]) null, genericSpecifications, genericDescriptions); + result.setUserObject(new StateMetadataMap(toTransform, iuDependencies)); + } + + public void visitRequiredCapability(RequiredCapability capability) { + try { + if (isEnabled(capability)) { + capability = rewrite(capability); + iuDependencies.put(factory.createGenericSpecification(capability.getName(), capability.getNamespace(), toFilter(capability.getRange()), capability.isOptional(), capability.isMultiple()), capability); + } + } catch (InvalidSyntaxException e) { + LogHelper.log(new Status(IStatus.ERROR, MetadataActivator.PI_METADATA, "Invalid filter: " + e.getFilter(), e)); //$NON-NLS-1$ + } + } + + private RequiredCapability rewrite(RequiredCapability match) { + if (recommendations == null) + return match; + Recommendation foundRecommendation = recommendations.findRecommendation(match); + return foundRecommendation != null ? foundRecommendation.newValue() : match; + } +} diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/resolution/UnsatisfiedCapability.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/resolution/UnsatisfiedCapability.java new file mode 100644 index 000000000..29d6c244d --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/prov/resolution/UnsatisfiedCapability.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * 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.resolution; + +import org.eclipse.equinox.prov.metadata.IInstallableUnit; +import org.eclipse.equinox.prov.metadata.RequiredCapability; + +/** + * Represents a provisioning dependency that was not satisfied during + * resolution. + */ +public class UnsatisfiedCapability { + private IInstallableUnit owner; + private RequiredCapability require; + + /** + * Creates a new unresolved dependency + * @param required The dependency that was not satisfied. + * @param owner The installable unit whose dependency was not satisfied. + */ + public UnsatisfiedCapability(RequiredCapability required, IInstallableUnit owner) { + this.require = required; + this.owner = owner; + } + + public IInstallableUnit getOwner() { + return owner; + } + + /** + * Returns the specific dependency that was not satisfied. + */ + public RequiredCapability getRequiredCapability() { + return require; + } + + /** + * Returns the installable unit whose dependency was not satisfied. + */ + public IInstallableUnit getUnsatisfiedUnit() { + return owner; + } + + /** + * For debugging purposes only. + */ + public String toString() { + return "[" + owner + "] " + require.toString(); //$NON-NLS-1$ //$NON-NLS-2$ + } +} |