| /******************************************************************************* |
| * Copyright (c) 2007, 2008 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.equinox.internal.p2.resolution; |
| |
| import java.util.*; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.equinox.internal.p2.core.helpers.LogHelper; |
| import org.eclipse.equinox.internal.p2.director.*; |
| import org.eclipse.equinox.internal.provisional.p2.metadata.*; |
| import org.eclipse.osgi.service.resolver.*; |
| import org.osgi.framework.InvalidSyntaxException; |
| |
| public class Transformer { |
| 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 DirectorActivator.context.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++) { |
| visitRequiredCapability(requires[i]); |
| } |
| |
| //Do the capabilities |
| ProvidedCapability[] capabilities = toTransform.getProvidedCapabilities(); |
| iuCapabilities = new ArrayList(requires.length + 1); |
| for (int i = 0; i < capabilities.length; i++) { |
| visitCapability(capabilities[i]); |
| } |
| |
| //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, DirectorActivator.PI_DIRECTOR, "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; |
| } |
| } |