| /******************************************************************************* |
| * 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(); |
| } |
| } |