blob: 330a2407b2fac8076bec9c0e0db6fc753029db00 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012, 2016 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* 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;
}
}
}