/******************************************************************************* * Copyright (c) 2012, 2016 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.container; import java.util.HashMap; import java.util.Map; import org.eclipse.osgi.internal.container.Capabilities; import org.eclipse.osgi.internal.framework.FilterImpl; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.namespace.*; import org.osgi.framework.wiring.BundleCapability; import org.osgi.framework.wiring.BundleRequirement; import org.osgi.resource.Namespace; /** * An implementation of {@link BundleRequirement}. This requirement implements * the matches method according to the OSGi specification which includes * implementing the mandatory directive for the osgi.wiring.* namespaces. * @since 3.10 * @noextend This class is not intended to be subclassed by clients. */ public class ModuleRequirement implements BundleRequirement { private final String namespace; private final Map<String, String> directives; private final Map<String, Object> attributes; private final ModuleRevision revision; ModuleRequirement(String namespace, Map<String, String> directives, Map<String, ?> attributes, ModuleRevision revision) { this.namespace = namespace; this.directives = ModuleRevisionBuilder.unmodifiableMap(directives); this.attributes = ModuleRevisionBuilder.unmodifiableMap(attributes); this.revision = revision; } @Override public ModuleRevision getRevision() { return revision; } @Override public boolean matches(BundleCapability capability) { if (!namespace.equals(capability.getNamespace())) return false; String filterSpec = directives.get(Namespace.REQUIREMENT_FILTER_DIRECTIVE); FilterImpl f = null; if (filterSpec != null) { try { f = FilterImpl.newInstance(filterSpec); } catch (InvalidSyntaxException e) { return false; } } boolean matchMandatory = PackageNamespace.PACKAGE_NAMESPACE.equals(namespace) || BundleNamespace.BUNDLE_NAMESPACE.equals(namespace) || HostNamespace.HOST_NAMESPACE.equals(namespace); return Capabilities.matches(f, capability, matchMandatory); } @Override public String getNamespace() { return namespace; } @Override public Map<String, String> getDirectives() { return directives; } @Override public Map<String, Object> getAttributes() { return attributes; } @Override public ModuleRevision getResource() { return revision; } public String toString() { return namespace + ModuleRevision.toString(attributes, false) + ModuleRevision.toString(directives, true); } private static final String PACKAGENAME_FILTER_COMPONENT = PackageNamespace.PACKAGE_NAMESPACE + "="; //$NON-NLS-1$ DynamicModuleRequirement getDynamicPackageRequirement(ModuleRevision host, String dynamicPkgName) { if (!PackageNamespace.PACKAGE_NAMESPACE.equals(namespace)) { return null; } if (!PackageNamespace.RESOLUTION_DYNAMIC.equals(directives.get(PackageNamespace.REQUIREMENT_RESOLUTION_DIRECTIVE))) { // not dynamic return null; } String dynamicFilter = directives.get(PackageNamespace.REQUIREMENT_FILTER_DIRECTIVE); // TODO we make some assumptions here on the format of the filter string int packageNameBegin = dynamicFilter.indexOf(PACKAGENAME_FILTER_COMPONENT); if (packageNameBegin == -1) { // not much we can do return null; } packageNameBegin += PACKAGENAME_FILTER_COMPONENT.length(); int packageNameEnd = dynamicFilter.indexOf(')', packageNameBegin); if (packageNameEnd == -1) { // not much we can do return null; } String filterPackageName = dynamicFilter.substring(packageNameBegin, packageNameEnd); String specificPackageFilter = null; if ("*".equals(filterPackageName)) { //$NON-NLS-1$ // matches all specificPackageFilter = dynamicFilter.replace(PACKAGENAME_FILTER_COMPONENT + filterPackageName, PACKAGENAME_FILTER_COMPONENT + dynamicPkgName); } else if (filterPackageName.endsWith(".*")) { //$NON-NLS-1$ if (dynamicPkgName.startsWith(filterPackageName.substring(0, filterPackageName.length() - 1))) { specificPackageFilter = dynamicFilter.replace(PACKAGENAME_FILTER_COMPONENT + filterPackageName, PACKAGENAME_FILTER_COMPONENT + dynamicPkgName); } } else if (dynamicPkgName.equals(filterPackageName)) { specificPackageFilter = dynamicFilter; } if (specificPackageFilter != null) { Map<String, String> dynamicDirectives = new HashMap<>(directives); dynamicDirectives.put(PackageNamespace.REQUIREMENT_FILTER_DIRECTIVE, specificPackageFilter); return new DynamicModuleRequirement(host, dynamicDirectives); } return null; } class DynamicModuleRequirement extends ModuleRequirement { DynamicModuleRequirement(ModuleRevision host, Map<String, String> directives) { super(ModuleRequirement.this.getNamespace(), directives, ModuleRequirement.this.getAttributes(), host); } ModuleRequirement getOriginal() { return ModuleRequirement.this; } } }