/*******************************************************************************
* 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
* and Eclipse Distribution License v1.0 which accompany this distribution.
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Jan S. Rellermeyer, IBM Research - initial API and implementation
*******************************************************************************/
package org.eclipse.concierge.compat.service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.concierge.BundleImpl.Revision;
import org.eclipse.concierge.Concierge;
import org.eclipse.concierge.ConciergeCollections.ParseResult;
import org.eclipse.concierge.ConciergeCollections.Tuple;
import org.eclipse.concierge.Resources.BundleCapabilityImpl;
import org.eclipse.concierge.Resources.BundleRequirementImpl;
import org.eclipse.concierge.Utils;
import org.eclipse.concierge.compat.LegacyBundleProcessing;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
import org.osgi.framework.Version;
import org.osgi.framework.namespace.AbstractWiringNamespace;
import org.osgi.framework.namespace.BundleNamespace;
import org.osgi.framework.namespace.ExecutionEnvironmentNamespace;
import org.osgi.framework.namespace.HostNamespace;
import org.osgi.framework.namespace.IdentityNamespace;
import org.osgi.framework.namespace.PackageNamespace;
import org.osgi.framework.wiring.BundleCapability;
import org.osgi.framework.wiring.BundleRequirement;
import org.osgi.resource.Namespace;
public class BundleManifestTwo implements LegacyBundleProcessing {
@SuppressWarnings("deprecation")
private static final String SPECIFICATION_VERSION = Constants.PACKAGE_SPECIFICATION_VERSION;
@SuppressWarnings("deprecation")
private static final String BUNDLE_REQUIREDEXECUTIONENVIRONMENT = Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT;
@SuppressWarnings("deprecation")
private static final String FRAMEWORK_EXECUTIONENVIRONMENT = Constants.FRAMEWORK_EXECUTIONENVIRONMENT;
private static final Pattern PARSE_EE = Pattern
.compile("([^-|\\.]*)(?:\\-(\\d\\.\\d))(?:\\/([^\\d|\\.|\\/]*))|([^\\d|\\.|\\/]*)(?:\\/([^-|\\.]*)(?:\\-(\\d\\.\\d)))|([^\\.|\\d]*)");
private static final Pattern PARSE_EE2 = Pattern
.compile("([^-|\\.]*)(?:\\-(\\d\\.\\d))?(?:\\/([^-|\\.]*)(?:\\-(\\d\\.\\d))?)?");
public Tuple<List<BundleCapability>, List<BundleRequirement>> processManifest(
final Revision revision, final Manifest manifest)
throws BundleException {
final Attributes mfAttrs = manifest.getMainAttributes();
final List<BundleCapability> caps = new ArrayList<BundleCapability>();
final List<BundleRequirement> reqs = new ArrayList<BundleRequirement>();
final String bundleSymbolicName;
final Version bundleVersion;
final HashMap<String, Object> symbolicNameAttrs;
{
final String symNameStr = mfAttrs
.getValue(Constants.BUNDLE_SYMBOLICNAME);
if (symNameStr == null) {
throw new BundleException("Bundle with "
+ Constants.BUNDLE_MANIFESTVERSION + "=2 must specify "
+ Constants.BUNDLE_SYMBOLICNAME);
}
final String[] parts = Utils.splitString(symNameStr, ';');
if (parts[0].contains(";")) {
throw new IllegalArgumentException(symNameStr);
}
final ParseResult parseResult = Utils.parseLiterals(parts, 1);
symbolicNameAttrs = parseResult.getAttributes();
final String fragHostStr = mfAttrs
.getValue(Constants.FRAGMENT_HOST);
// identity namespace and bundle namespace capability
{
final Map<String, Object> attrs = new HashMap<String, Object>(
symbolicNameAttrs);
final Map<String, String> dirs = new HashMap<String, String>();
bundleSymbolicName = parts[0].trim();
attrs.put(BundleNamespace.BUNDLE_NAMESPACE, bundleSymbolicName);
try {
bundleVersion = Version.parseVersion(mfAttrs
.getValue(Constants.BUNDLE_VERSION));
attrs.put(
BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE,
bundleVersion);
} catch (final IllegalArgumentException e) {
throw new BundleException(
"Syntactic error in bundle manifest", e);
}
final String singletonStr = (String) parseResult
.getDirectives().get(Constants.SINGLETON_DIRECTIVE);
dirs.put(IdentityNamespace.CAPABILITY_SINGLETON_DIRECTIVE,
singletonStr == null ? "false" : singletonStr.trim());
final String mandatory = parseResult.getDirectives().get(
Constants.MANDATORY_DIRECTIVE);
if (mandatory != null) {
dirs.put(BundleNamespace.CAPABILITY_MANDATORY_DIRECTIVE,
mandatory);
}
if (fragHostStr == null) {
final BundleCapability bundle = new BundleCapabilityImpl(
revision, BundleNamespace.BUNDLE_NAMESPACE, dirs,
attrs, "Bundle " + bundleSymbolicName + ' '
+ bundleVersion);
caps.add(bundle);
}
final Map<String, Object> attrs2 = new HashMap<String, Object>(
attrs);
final Map<String, String> dirs2 = new HashMap<String, String>(
dirs);
attrs2.remove(BundleNamespace.BUNDLE_NAMESPACE);
attrs2.put(IdentityNamespace.IDENTITY_NAMESPACE,
bundleSymbolicName);
attrs2.remove(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE);
attrs2.put(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE,
bundleVersion);
// TODO: handle unknown
attrs2.put(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE,
fragHostStr != null ? IdentityNamespace.TYPE_FRAGMENT
: IdentityNamespace.TYPE_BUNDLE);
addAttributeIfPresent(attrs2,
IdentityNamespace.CAPABILITY_COPYRIGHT_ATTRIBUTE,
mfAttrs, Constants.BUNDLE_COPYRIGHT);
addAttributeIfPresent(attrs2,
IdentityNamespace.CAPABILITY_DESCRIPTION_ATTRIBUTE,
mfAttrs, Constants.BUNDLE_DESCRIPTION);
addAttributeIfPresent(attrs2,
IdentityNamespace.CAPABILITY_DOCUMENTATION_ATTRIBUTE,
mfAttrs, Constants.BUNDLE_DOCURL);
addAttributeIfPresent(attrs2,
IdentityNamespace.CAPABILITY_LICENSE_ATTRIBUTE,
mfAttrs, "Bundle-License");
final BundleCapability identity = new BundleCapabilityImpl(
revision, IdentityNamespace.IDENTITY_NAMESPACE, dirs2,
attrs2, "Identity " + bundleSymbolicName + ' '
+ bundleVersion);
caps.add(identity);
}
// host namespace
{
if (fragHostStr != null) {
final Map<String, String> dirs2 = new HashMap<String, String>();
final String[] parts2 = Utils.splitString(fragHostStr, ';');
if (parts2[0].contains(";")) {
throw new IllegalArgumentException(fragHostStr);
}
final ParseResult parseResult2 = Utils.parseLiterals(
parts2, 1);
if (parseResult2.getDirectives() != null) {
dirs2.putAll(parseResult2.getDirectives());
}
// must not have uses directive
dirs2.remove(AbstractWiringNamespace.CAPABILITY_USES_DIRECTIVE);
// must not have effective directive
dirs2.remove(AbstractWiringNamespace.CAPABILITY_EFFECTIVE_DIRECTIVE);
dirs2.put(Namespace.REQUIREMENT_FILTER_DIRECTIVE, Utils
.createFilter(HostNamespace.HOST_NAMESPACE,
parts2[0], parseResult2.getAttributes()));
// fragments can attach to multiple hosts
dirs2.put(Namespace.REQUIREMENT_CARDINALITY_DIRECTIVE,
Namespace.CARDINALITY_MULTIPLE);
// some attributes for convenience
dirs2.put(HostNamespace.HOST_NAMESPACE, parts2[0]);
final String versionRange = (String) parseResult2
.getAttributes().get(
Constants.BUNDLE_VERSION_ATTRIBUTE);
if (versionRange != null) {
dirs2.put(
HostNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE,
versionRange);
}
final boolean extension = parts2[0]
.equals(Constants.SYSTEM_BUNDLE_SYMBOLICNAME)
|| parts2[0]
.equals(Concierge.FRAMEWORK_SYMBOLIC_NAME);
// check if the framework supports extensions at all
if (!Concierge.SUPPORTS_EXTENSIONS) {
throw new BundleException(
"Framework does not support extensions");
}
// check if fragment is a framework extension
if (HostNamespace.EXTENSION_FRAMEWORK
.equals(dirs2
.get(HostNamespace.REQUIREMENT_EXTENSION_DIRECTIVE))
|| extension) {
// host must be the system bundle
if (!extension) {
throw new BundleException("wrong host " + parts2[0]
+ " for an extension bundle");
}
// cannot have package imports
if (mfAttrs.getValue(Constants.IMPORT_PACKAGE) != null) {
throw new BundleException(
"Framework extension bundle must not declare package imports");
}
// cannot have require bundle
if (mfAttrs.getValue(Constants.REQUIRE_BUNDLE) != null) {
throw new BundleException(
"Framework extension bundle must not declare require bundle");
}
// cannot have native code
if (mfAttrs.getValue(Constants.BUNDLE_NATIVECODE) != null) {
throw new BundleException(
"Framework extension bundle must not declare native code");
}
}
final BundleRequirement hostReq = new BundleRequirementImpl(
revision,
HostNamespace.HOST_NAMESPACE,
dirs2,
null,
Constants.FRAGMENT_HOST
+ ' '
+ parts2[0]
+ ' '
+ (versionRange == null ? "" : versionRange));
reqs.add(hostReq);
} else {
if (!Constants.FRAGMENT_ATTACHMENT_NEVER.equals(parseResult
.getDirectives().get(
Constants.FRAGMENT_ATTACHMENT_DIRECTIVE))) {
final Map<String, Object> attrs = new HashMap<String, Object>();
final Map<String, String> dirs = new HashMap<String, String>();
if (parseResult.getDirectives() != null) {
dirs.putAll(parseResult.getDirectives());
}
attrs.putAll(symbolicNameAttrs);
attrs.put(HostNamespace.HOST_NAMESPACE,
bundleSymbolicName);
attrs.put(
HostNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE,
bundleVersion);
// must not have uses directive
dirs.remove(AbstractWiringNamespace.CAPABILITY_USES_DIRECTIVE);
// must not have effective directive
dirs.remove(AbstractWiringNamespace.CAPABILITY_EFFECTIVE_DIRECTIVE);
final BundleCapability hostCap = new BundleCapabilityImpl(
revision, HostNamespace.HOST_NAMESPACE, dirs,
attrs, "Host " + bundleSymbolicName + ' '
+ bundleVersion);
caps.add(hostCap);
}
}
}
}
// execution environment
final String requiredEEStr = mfAttrs
.getValue(BUNDLE_REQUIREDEXECUTIONENVIRONMENT);
if (requiredEEStr != null) {
final String[] requiredEEs = requiredEEStr.split(",");
final StringBuffer buffer = new StringBuffer();
buffer.append("osgi.ee; filter:=\"");
if (requiredEEs.length > 1) {
buffer.append("(|");
}
for (int i = 0; i < requiredEEs.length; i++) {
final String requiredEE = requiredEEs[i].trim();
final Matcher matcher = PARSE_EE.matcher(requiredEE);
final String ee1;
final String ee2;
final String version;
if (matcher.matches()) {
if (matcher.group(1) != null) {
ee1 = matcher.group(1);
ee2 = matcher.group(3);
version = matcher.group(2);
} else if (matcher.group(4) != null) {
ee1 = matcher.group(4);
ee2 = matcher.group(5);
version = matcher.group(6);
} else {
final String s = matcher.group(7);
final int pos = s.indexOf('/');
ee1 = pos > -1 ? s.substring(0, pos) : s;
ee2 = pos > -1 ? s.substring(pos + 1, s.length())
: null;
version = null;
}
} else {
final Matcher matcher2 = PARSE_EE2.matcher(requiredEE);
if (matcher2.matches()) {
if (matcher2.group(4) == null
|| matcher2.group(2).equals(matcher2.group(4))) {
ee1 = matcher2.group(1);
version = matcher2.group(2);
ee2 = matcher2.group(3);
} else {
ee1 = matcher2.group(1) + "-" + matcher2.group(2);
ee2 = matcher2.group(3) + "-" + matcher2.group(4);
version = null;
}
} else {
throw new BundleException("invalid bree string "
+ requiredEE);
}
}
if (version != null) {
buffer.append("(&(");
} else {
buffer.append('(');
}
buffer.append(ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE);
buffer.append('=');
buffer.append("J2SE".equals(ee1) ? "JavaSE" : ee1);
if (ee2 != null) {
buffer.append('/');
buffer.append(ee2);
}
if (version != null) {
buffer.append(")(version=");
buffer.append(version);
buffer.append("))");
} else {
buffer.append(')');
}
}
if (requiredEEs.length > 1) {
buffer.append(')');
}
buffer.append('\"');
reqs.add(new BundleRequirementImpl(revision, buffer.toString()));
}
// package namespace
{
final Set<String> importSet = new HashSet<String>();
// package imports
final String importStr = mfAttrs.getValue(Constants.IMPORT_PACKAGE);
if (importStr != null) {
final String[] imports = Utils.splitString(importStr, ',');
for (int i = 0; i < imports.length; i++) {
final String[] literals = Utils
.splitString(imports[i], ';');
if (literals[0].startsWith("java.")) {
throw new BundleException(
"Explicit import of java.* packages is not permitted",
BundleException.MANIFEST_ERROR);
}
if (importSet.contains(literals[0])) {
throw new BundleException("Duplicate import "
+ literals[0], BundleException.MANIFEST_ERROR);
}
importSet.add(literals[0]);
final ParseResult parseResult = Utils.parseLiterals(
literals, 1);
final HashMap<String, String> dirs = parseResult
.getDirectives();
dirs.put(Namespace.REQUIREMENT_FILTER_DIRECTIVE, Utils
.createFilter(PackageNamespace.PACKAGE_NAMESPACE,
literals[0], parseResult.getAttributes()));
dirs.put(Concierge.DIR_INTERNAL, literals[0]);
reqs.add(new BundleRequirementImpl(revision,
PackageNamespace.PACKAGE_NAMESPACE, dirs, null,
Constants.IMPORT_PACKAGE + ' ' + imports[i]));
}
}
}
{
// dynamic imports
final String dynImportStr = mfAttrs
.getValue(Constants.DYNAMICIMPORT_PACKAGE);
if (dynImportStr != null) {
final String[] dynImports = Utils
.splitString(dynImportStr, ',');
for (int i = 0; i < dynImports.length; i++) {
final String[] literals = Utils.splitString(dynImports[i],
';');
final ParseResult parseResult = Utils.parseLiterals(
literals, 1);
final HashMap<String, String> dirs = parseResult
.getDirectives();
dirs.put(Namespace.REQUIREMENT_FILTER_DIRECTIVE, Utils
.createFilter(PackageNamespace.PACKAGE_NAMESPACE,
literals[0], parseResult.getAttributes()));
dirs.put(PackageNamespace.REQUIREMENT_RESOLUTION_DIRECTIVE,
PackageNamespace.RESOLUTION_DYNAMIC);
dirs.put(PackageNamespace.REQUIREMENT_EFFECTIVE_DIRECTIVE,
PackageNamespace.EFFECTIVE_ACTIVE);
dirs.put(Concierge.DIR_INTERNAL, literals[0].trim());
if (literals[0].contains("*")) {
dirs.put(
PackageNamespace.REQUIREMENT_CARDINALITY_DIRECTIVE,
PackageNamespace.CARDINALITY_MULTIPLE);
}
reqs.add(new BundleRequirementImpl(revision,
PackageNamespace.PACKAGE_NAMESPACE, dirs, null,
Constants.DYNAMICIMPORT_PACKAGE + ' '
+ dynImports[i]));
}
}
}
{
// package exports
final String exportStr = mfAttrs.getValue(Constants.EXPORT_PACKAGE);
if (exportStr != null) {
final String[] exports = Utils.splitString(exportStr, ',');
for (int i = 0; i < exports.length; i++) {
final String[] literals = Utils
.splitString(exports[i], ';');
final ParseResult parseResult = Utils.parseLiterals(
literals, 1);
final HashMap<String, Object> attrs = parseResult
.getAttributes();
if (attrs
.containsKey(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE)
|| attrs.containsKey(Constants.BUNDLE_VERSION_ATTRIBUTE)) {
throw new BundleException(
"Export statement contains illegal attributes");
}
final String specVer = (String) attrs
.get(SPECIFICATION_VERSION);
if (specVer != null) {
final Version ver = (Version) attrs
.get(Constants.VERSION_ATTRIBUTE);
final Version specVerV = new Version(
Utils.unQuote(specVer));
if (ver != null) {
// make sure they are identical
if (!specVerV.equals(ver)) {
throw new BundleException(
"Both version and specificationVersion are given but versions are not identical");
}
} else {
attrs.put(Constants.VERSION_ATTRIBUTE, specVerV);
}
}
attrs.put(PackageNamespace.PACKAGE_NAMESPACE,
literals[0].trim());
if (literals[0].startsWith("java.")) {
throw new BundleException(
"Bundle must not export a java.* package");
}
attrs.put(
PackageNamespace.CAPABILITY_BUNDLE_SYMBOLICNAME_ATTRIBUTE,
bundleSymbolicName);
attrs.put(
PackageNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE,
bundleVersion);
caps.add(new BundleCapabilityImpl(revision,
PackageNamespace.PACKAGE_NAMESPACE, parseResult
.getDirectives(), attrs,
Constants.EXPORT_PACKAGE + ' ' + exports[i]));
}
}
}
{
// bundle namespace
final String requireBundleStr = mfAttrs
.getValue(Constants.REQUIRE_BUNDLE);
// require bundle
if (requireBundleStr != null) {
final String[] requires = Utils.splitString(requireBundleStr,
',');
for (int i = 0; i < requires.length; i++) {
final String[] literals = Utils.splitString(requires[i],
';');
final String requiredBundle = literals[0].trim();
final ParseResult parseResult = Utils.parseLiterals(
literals, 1);
final Map<String, String> dirs = parseResult
.getDirectives();
final String visibility = parseResult.getDirectives().get(
Constants.VISIBILITY_DIRECTIVE);
if (Constants.VISIBILITY_REEXPORT.equals(visibility)) {
dirs.put(
BundleNamespace.REQUIREMENT_VISIBILITY_DIRECTIVE,
BundleNamespace.VISIBILITY_REEXPORT);
} else {
dirs.put(
BundleNamespace.REQUIREMENT_VISIBILITY_DIRECTIVE,
BundleNamespace.VISIBILITY_PRIVATE);
}
if (Constants.RESOLUTION_OPTIONAL.equals(parseResult
.getDirectives()
.get(Constants.RESOLUTION_DIRECTIVE))) {
dirs.put(
BundleNamespace.REQUIREMENT_RESOLUTION_DIRECTIVE,
BundleNamespace.RESOLUTION_OPTIONAL);
}
dirs.put(
Namespace.REQUIREMENT_FILTER_DIRECTIVE,
Utils.createFilter(
BundleNamespace.BUNDLE_NAMESPACE,
requiredBundle, parseResult.getAttributes()));
dirs.put(Concierge.DIR_INTERNAL, literals[0]);
reqs.add(new BundleRequirementImpl(revision,
BundleNamespace.BUNDLE_NAMESPACE, dirs, null,
Constants.REQUIRE_BUNDLE + ' ' + requires[i]));
}
}
}
return new Tuple<List<BundleCapability>, List<BundleRequirement>>(caps,
reqs);
}
void addAttributeIfPresent(final Map<String, Object> attributes,
final String name, final Attributes mfAttrs, final String header) {
final String str = mfAttrs.getValue(header);
if (str != null) {
attributes.put(name, str);
}
}
public static String parse(final String requiredEEStr)
throws BundleException {
final String[] requiredEEs = requiredEEStr.split(",");
final StringBuffer buffer = new StringBuffer();
if (requiredEEs.length > 1) {
buffer.append("(|");
}
for (int i = 0; i < requiredEEs.length; i++) {
final String requiredEE = requiredEEs[i].trim();
final Matcher matcher = PARSE_EE.matcher(requiredEE);
final String ee1;
final String ee2;
final String version;
if (matcher.matches()) {
if (matcher.group(1) != null) {
ee1 = matcher.group(1);
ee2 = matcher.group(3);
version = matcher.group(2);
} else if (matcher.group(4) != null) {
ee1 = matcher.group(4);
ee2 = matcher.group(5);
version = matcher.group(6);
} else {
final String s = matcher.group(7);
final int pos = s.indexOf('/');
ee1 = pos > -1 ? s.substring(0, pos) : s;
ee2 = pos > -1 ? s.substring(pos + 1, s.length()) : null;
version = null;
}
} else {
final Matcher matcher2 = PARSE_EE2.matcher(requiredEE);
if (matcher2.matches()) {
if (matcher2.group(4) == null
|| matcher2.group(2).equals(matcher2.group(4))) {
ee1 = matcher2.group(1);
version = matcher2.group(2);
ee2 = matcher2.group(3);
} else {
ee1 = matcher2.group(1) + "-" + matcher2.group(2);
ee2 = matcher2.group(3) + "-" + matcher2.group(4);
version = null;
}
} else {
throw new BundleException("invalid bree string "
+ requiredEE);
}
}
if (version != null) {
buffer.append("(&(");
} else {
buffer.append('(');
}
buffer.append(ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE);
buffer.append('=');
buffer.append("J2SE".equals(ee1) ? "JavaSE" : ee1);
if (ee2 != null) {
buffer.append('/');
buffer.append(ee2);
}
if (version != null) {
buffer.append(")(version=");
buffer.append(version);
buffer.append("))");
} else {
buffer.append(')');
}
}
if (requiredEEs.length > 1) {
buffer.append(')');
}
return buffer.toString();
}
public List<BundleCapability> translateToCapability(
final Concierge framework, final String attributeName,
final String valueStr) {
if (FRAMEWORK_EXECUTIONENVIRONMENT.equals(attributeName)) {
final String[] fees = Utils.splitString(valueStr, ',');
final List<BundleCapability> caps = new ArrayList<BundleCapability>();
for (final String fee : fees) {
final String requiredEE = fee.trim();
final Matcher matcher = PARSE_EE.matcher(requiredEE);
final String ee1;
final String ee2;
final String version;
if (matcher.matches()) {
if (matcher.group(1) != null) {
ee1 = matcher.group(1);
ee2 = matcher.group(3);
version = matcher.group(2);
} else if (matcher.group(4) != null) {
ee1 = matcher.group(4);
ee2 = matcher.group(5);
version = matcher.group(6);
} else {
final String s = matcher.group(7);
final int pos = s.indexOf('/');
ee1 = pos > -1 ? s.substring(0, pos) : s;
ee2 = pos > -1 ? s.substring(pos + 1, s.length())
: null;
version = null;
}
} else {
final Matcher matcher2 = PARSE_EE2.matcher(requiredEE);
if (matcher2.matches()) {
if (matcher2.group(4) == null
|| matcher2.group(2).equals(matcher2.group(4))) {
ee1 = matcher2.group(1);
version = matcher2.group(2);
ee2 = matcher2.group(3);
} else {
ee1 = matcher2.group(1) + "-" + matcher2.group(2);
ee2 = matcher2.group(3) + "-" + matcher2.group(4);
version = null;
}
} else {
throw new IllegalStateException(
"invalid framework execution environment "
+ requiredEE);
}
}
final Map<String, Object> attrs = new HashMap<String, Object>();
final String eeStr = ee2 == null ? ee1 : ee1 + "/" + ee2;
attrs.put(
ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE,
eeStr);
if (version != null) {
attrs.put(
ExecutionEnvironmentNamespace.CAPABILITY_VERSION_ATTRIBUTE,
new Version(version));
}
final BundleCapability cap = new BundleCapabilityImpl(
framework,
ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE,
null, attrs, "ExecutionEnvironment " + eeStr
+ (version == null ? "" : ' ' + version));
caps.add(cap);
}
return caps;
}
return null;
}
}