blob: 8c6ac9fad606ccbb22bd6ce3a4763c8ca13bf835 [file] [log] [blame]
/*******************************************************************************
* 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;
}
}