blob: dbf45aba4d1227dba54eb7c07fbf3e9dc533840f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013 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.osgi.compatibility.state;
import java.util.*;
import java.util.Map.Entry;
import org.eclipse.osgi.compatibility.state.FilterParser.FilterComponent;
import org.eclipse.osgi.service.resolver.*;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.Version;
import org.osgi.framework.namespace.*;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.resource.*;
class StateConverter {
private final State state;
StateConverter(State state) {
this.state = state;
}
BundleDescription createDescription(BundleRevision resource) {
Collection<Capability> idList = resource.getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE);
if (idList.size() != 1)
throw new IllegalArgumentException("Bogus osgi.identity: " + idList); //$NON-NLS-1$
Capability id = idList.iterator().next();
Map<String, Object> idAttrs = new HashMap<String, Object>(id.getAttributes());
String symbolicName = (String) idAttrs.remove(IdentityNamespace.IDENTITY_NAMESPACE);
Version version = (Version) idAttrs.remove(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE);
String symbolicNameSpecification = symbolicName + toString(idAttrs, "=", true) + toString(id.getDirectives(), ":=", true); //$NON-NLS-1$ //$NON-NLS-2$
List<ExportPackageDescription> exportPackages = new ArrayList<ExportPackageDescription>();
List<GenericDescription> provideCapabilities = new ArrayList<GenericDescription>();
List<ImportPackageSpecification> importPackages = new ArrayList<ImportPackageSpecification>();
List<GenericSpecification> requireCapabilities = new ArrayList<GenericSpecification>();
List<HostSpecification> fragmentHost = new ArrayList<HostSpecification>(0);
List<BundleSpecification> requireBundles = new ArrayList<BundleSpecification>();
Collection<Capability> capabilities = resource.getCapabilities(null);
Capability osgiIdentity = null;
for (Capability capability : capabilities) {
String namespace = capability.getNamespace();
if (IdentityNamespace.IDENTITY_NAMESPACE.equals(namespace)) {
osgiIdentity = capability;
} else if (BundleRevision.HOST_NAMESPACE.equals(namespace) || BundleRevision.BUNDLE_NAMESPACE.equals(namespace)) {
continue;
} else if (BundleRevision.PACKAGE_NAMESPACE.equals(namespace)) {
exportPackages.addAll(creatExportPackage(capability));
} else {
provideCapabilities.addAll(createProvideCapability(capability));
}
}
Collection<Requirement> requirements = resource.getRequirements(null);
for (Requirement requirement : requirements) {
String namespace = requirement.getNamespace();
if (BundleRevision.BUNDLE_NAMESPACE.equals(namespace)) {
requireBundles.addAll(createRequireBundle(requirement));
} else if (BundleRevision.HOST_NAMESPACE.equals(namespace)) {
fragmentHost.addAll(createFragmentHost(requirement));
} else if (BundleRevision.PACKAGE_NAMESPACE.equals(namespace)) {
importPackages.addAll(createImportPackage(requirement));
} else {
requireCapabilities.addAll(createRequireCapability(requirement));
}
}
BundleDescription result = state.getFactory().createBundleDescription(resource.getBundle().getBundleId(), symbolicNameSpecification, version, resource.getBundle().getLocation(), requireBundles.toArray(new BundleSpecification[requireBundles.size()]), fragmentHost.size() == 0 ? null : fragmentHost.get(0), importPackages.toArray(new ImportPackageSpecification[importPackages.size()]), exportPackages.toArray(new ExportPackageDescription[exportPackages.size()]), null, null, requireCapabilities.toArray(new GenericSpecification[requireCapabilities.size()]), provideCapabilities.toArray(new GenericDescription[provideCapabilities.size()]), null);
result.setUserObject(resource);
GenericDescription[] genericDescs = result.getGenericCapabilities();
for (GenericDescription genericDesc : genericDescs) {
if (IdentityNamespace.IDENTITY_NAMESPACE.equals(genericDesc.getType()))
genericDesc.setUserObject(osgiIdentity);
}
return result;
}
private List<ExportPackageDescription> creatExportPackage(Capability capability) {
Map<String, Object> attributes = new HashMap<String, Object>(capability.getAttributes());
Map<String, String> directives = capability.getDirectives();
String packageName = (String) attributes.remove(PackageNamespace.PACKAGE_NAMESPACE);
// remove invalid attributes
attributes.remove(PackageNamespace.CAPABILITY_BUNDLE_SYMBOLICNAME_ATTRIBUTE);
attributes.remove(AbstractWiringNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE);
String declaration = packageName + toString(attributes, "=", true) + toString(directives, ":=", true); //$NON-NLS-1$//$NON-NLS-2$
List<ExportPackageDescription> result = state.getFactory().createExportPackageDescriptions(declaration);
for (ExportPackageDescription export : result) {
export.setUserObject(capability);
}
return result;
}
private List<GenericDescription> createProvideCapability(Capability capability) {
Map<String, Object> attributes = capability.getAttributes();
Map<String, String> directives = capability.getDirectives();
String declaration = capability.getNamespace() + toString(attributes, "=", false) + toString(directives, ":=", true); //$NON-NLS-1$//$NON-NLS-2$
List<GenericDescription> result = state.getFactory().createGenericDescriptions(declaration);
for (GenericDescription genericDescription : result) {
genericDescription.setUserObject(capability);
}
return result;
}
private List<BundleSpecification> createRequireBundle(Requirement requirement) {
String declaration = createOSGiRequirement(requirement, BundleNamespace.BUNDLE_NAMESPACE, BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE);
List<BundleSpecification> result = state.getFactory().createBundleSpecifications(declaration);
for (BundleSpecification bundleSpecification : result) {
bundleSpecification.setUserObject(requirement);
}
return result;
}
private List<HostSpecification> createFragmentHost(Requirement requirement) {
String declaration = createOSGiRequirement(requirement, HostNamespace.HOST_NAMESPACE, HostNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE);
List<HostSpecification> result = state.getFactory().createHostSpecifications(declaration);
for (HostSpecification hostSpecification : result) {
hostSpecification.setUserObject(requirement);
}
return result;
}
private List<ImportPackageSpecification> createImportPackage(Requirement requirement) {
String declaration = createOSGiRequirement(requirement, PackageNamespace.PACKAGE_NAMESPACE, PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE, PackageNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE);
List<ImportPackageSpecification> result = state.getFactory().createImportPackageSpecifications(declaration);
for (ImportPackageSpecification importPackageSpecification : result) {
importPackageSpecification.setUserObject(requirement);
}
return result;
}
private List<GenericSpecification> createRequireCapability(Requirement requirement) {
String declaration = requirement.getNamespace() + toString(requirement.getAttributes(), "=", false) + toString(requirement.getDirectives(), ":=", true); //$NON-NLS-1$ //$NON-NLS-2$
List<GenericSpecification> result = state.getFactory().createGenericSpecifications(declaration);
for (GenericSpecification genericSpecification : result) {
genericSpecification.setUserObject(requirement);
}
return result;
}
private String createOSGiRequirement(Requirement requirement, String namespace, String... versions) {
Map<String, String> directives = new HashMap<String, String>(requirement.getDirectives());
String filter = directives.remove(Namespace.REQUIREMENT_FILTER_DIRECTIVE);
if (filter == null)
throw new IllegalArgumentException("No filter directive found:" + requirement); //$NON-NLS-1$
FilterParser parser = new FilterParser(filter);
FilterComponent component = null;
try {
component = parser.parse();
} catch (InvalidSyntaxException e) {
throw new IllegalArgumentException("Invalid filter directive", e); //$NON-NLS-1$
}
Map<String, String> matchingAttributes = component.getStandardOSGiAttributes(versions);
String name = matchingAttributes.remove(namespace);
if (name == null)
throw new IllegalArgumentException("Invalid requirement: " + requirement); //$NON-NLS-1$
return name + toString(matchingAttributes, "=", true) + toString(directives, ":=", true); //$NON-NLS-1$ //$NON-NLS-2$
}
static <V> String toString(Map<String, V> map, String assignment, boolean stringsOnly) {
if (map.isEmpty())
return ""; //$NON-NLS-1$
Set<Entry<String, V>> set = map.entrySet();
StringBuffer sb = new StringBuffer();
for (Entry<String, V> entry : set) {
sb.append("; "); //$NON-NLS-1$
String key = entry.getKey();
Object value = entry.getValue();
if (value instanceof List) {
@SuppressWarnings("unchecked")
List<Object> list = (List<Object>) value;
if (list.size() == 0)
continue;
Object component = list.get(0);
String className = component.getClass().getName();
String type = className.substring(className.lastIndexOf('.') + 1);
sb.append(key).append(':').append("List<").append(type).append(">").append(assignment).append('"'); //$NON-NLS-1$ //$NON-NLS-2$
for (Object object : list)
sb.append(object).append(',');
sb.setLength(sb.length() - 1);
sb.append('"');
} else {
String type = ""; //$NON-NLS-1$
if (!(value instanceof String) && !stringsOnly) {
String className = value.getClass().getName();
type = ":" + className.substring(className.lastIndexOf('.') + 1); //$NON-NLS-1$
}
sb.append(key).append(type).append(assignment).append('"').append(value).append('"');
}
}
return sb.toString();
}
}