You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by mc...@apache.org on 2008/12/03 13:03:13 UTC

svn commit: r722850 [1/3] - /felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/

Author: mcculls
Date: Wed Dec  3 04:03:12 2008
New Revision: 722850

URL: http://svn.apache.org/viewvc?rev=722850&view=rev
Log:
FELIX-760: commit latest bindex code

Modified:
    felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/BundleInfo.java
    felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/CapabilityImpl.java
    felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/FilterImpl.java
    felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/Manifest.java
    felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/ManifestEntry.java
    felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/Parameter.java
    felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/RepositoryImpl.java
    felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/RequirementImpl.java
    felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/ResourceImpl.java
    felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/StringSet.java
    felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/Tag.java
    felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/VersionRange.java

Modified: felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/BundleInfo.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/BundleInfo.java?rev=722850&r1=722849&r2=722850&view=diff
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/BundleInfo.java (original)
+++ felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/BundleInfo.java Wed Dec  3 04:03:12 2008
@@ -1,506 +1,523 @@
-/*
- * $Id: BundleInfo.java 44 2007-07-13 20:49:41Z hargrave@us.ibm.com $
- * 
- * Copyright (c) OSGi Alliance (2002, 2006, 2007). All Rights Reserved.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.osgi.impl.bundle.obr.resource;
-
-import java.io.*;
-import java.net.URL;
-import java.util.*;
-import java.util.zip.*;
-
-import org.osgi.service.obr.Resource;
-
-/**
- * Convert a bundle to a generic resource description and store its local
- * dependencies (like for example a license file in the JAR) in a zip file.
- * 
- * @version $Revision: 44 $
- */
-public class BundleInfo {
-	Manifest	manifest;
-	File		bundleJar;
-	ZipFile		jar;
-	String		license;
-	Properties	localization;
-	RepositoryImpl	repository;
-
-	/**
-	 * Parse a zipFile from the file system. We only need the manifest and the
-	 * localization. So a zip file is used to minimze memory consumption.
-	 * 
-	 * @param bundleJar Path name
-	 * @throws Exception Any errors that occur
-	 */
-	public BundleInfo(RepositoryImpl repository, File bundleJar) throws Exception {
-		this.bundleJar = bundleJar;
-		this.repository = repository;
-		
-		if (!this.bundleJar.exists())
-			throw new FileNotFoundException(bundleJar.toString());
-
-		jar = new ZipFile(bundleJar);
-		ZipEntry entry = jar.getEntry("META-INF/MANIFEST.MF");
-		if (entry == null)
-			throw new FileNotFoundException("No Manifest in "
-					+ bundleJar.toString());
-		manifest = new Manifest(jar.getInputStream(entry));
-	}
-
-	public BundleInfo(Manifest manifest) throws Exception {
-		this.manifest = manifest;
-	}
-
-	/**
-	 * Convert the bundle to a Resource. All URIs are going to be abslute, but
-	 * could be local.
-	 * 
-	 * @return the resource
-	 * @throws Exception
-	 */
-	public ResourceImpl build() throws Exception {
-		ResourceImpl resource;
-		// Setup the manifest
-		// and create a resource
-		resource = new ResourceImpl(repository, manifest.getSymbolicName(), manifest
-				.getVersion());
-
-		try {
-
-			// Calculate the location URL of the JAR
-			URL location = new URL("jar:" + bundleJar.toURL().toString() + "!/");
-			resource.setURL(bundleJar.toURL());
-			resource.setFile(bundleJar);
-
-			doReferences(resource, location);
-			doSize(resource);
-			doCategories(resource);
-			doImportExportServices(resource);
-			doDeclarativeServices(resource);
-			doFragment(resource);
-			doRequires(resource);
-			doBundle(resource);
-			doExports(resource);
-			doImports(resource);
-			doExecutionEnvironment(resource);
-
-			return resource;
-		}
-		finally {
-			try {
-				jar.close();
-			}
-			catch (Exception e) {
-				// ignore
-			}
-		}
-	}
-
-	/**
-	 * Check the size and add it.
-	 * 
-	 * @param resource
-	 */
-	void doSize(ResourceImpl resource) {
-		long size = bundleJar.length();
-		if (size > 0)
-			resource.setSize(size);
-	}
-
-	/**
-	 * Find the categories, break them up and add them.
-	 * 
-	 * @param resource
-	 */
-	void doCategories(ResourceImpl resource) {
-		for (int i = 0; i < manifest.getCategories().length; i++) {
-			String category = manifest.getCategories()[i];
-			resource.addCategory(category);
-		}
-	}
-
-	void doReferences(ResourceImpl resource, URL location) {
-		// Presentation name
-		String name = translated("Bundle-Name");
-		if (name != null)
-			resource.setPresentationName(name);
-
-		// Handle license. -l allows a global license
-		// set when no license is included.
-
-		String license = translated("Bundle-License");
-		if (license != null)
-			resource.setLicense(toURL(location, license));
-		else if (this.license != null)
-			resource.setLicense(toURL(location, this.license));
-
-		String description = translated("Bundle-Description");
-		if (description != null)
-			resource.setDescription(description);
-
-		String copyright = translated("Bundle-Copyright");
-		if (copyright != null)
-			resource.setCopyright(copyright);
-
-		String documentation = translated("Bundle-DocURL");
-		if (documentation != null)
-			resource.setDocumentation(toURL(location, documentation));
-
-		String source = manifest.getValue("Bundle-Source");
-		if (source != null)
-			resource.setSource(toURL(location, source));
-	}
-
-	URL toURL(URL location, String source) {
-		try {
-			return new URL(location, source);
-		}
-		catch (Exception e) {
-			System.err.println("Error in converting url: " + location + " : "
-					+ source);
-			return null;
-		}
-	}
-
-	void doDeclarativeServices(ResourceImpl resource) throws Exception {
-		String serviceComponent = manifest.getValue("service-component");
-		if (serviceComponent == null)
-			return;
-
-		StringTokenizer st = new StringTokenizer(serviceComponent, " ,\t");
-		String parts[] = new String[st.countTokens()];
-		for (int i = 0; i < parts.length; i++)
-			parts[i] = st.nextToken();
-
-		for (int i = 0; i < parts.length; i++) {
-			ZipEntry entry = jar.getEntry(parts[i]);
-			if (entry == null) {
-				System.err.println("Bad Service-Component header: "
-						+ serviceComponent + ", no such file " + parts[i]);
-			}
-			InputStream in = jar.getInputStream(entry);
-			// TODO parse declarative services files.
-			in.close();
-		}
-	}
-
-	void doImportExportServices(ResourceImpl resource) throws IOException {
-		String importServices = manifest.getValue("import-service");
-		if (importServices != null) {
-			List entries = manifest.getEntries(importServices);
-			for (Iterator i = entries.iterator(); i.hasNext();) {
-				ManifestEntry entry = (ManifestEntry) i.next();
-				RequirementImpl ri = new RequirementImpl("service");
-				ri.setFilter(createServiceFilter(entry));
-				ri.setComment("Import Service " + entry.getName());
-
-				// TODO the following is arbitrary
-				ri.setOptional(false);
-				ri.setMultiple(true);
-				resource.addRequirement(ri);
-			}
-		}
-
-		String exportServices = manifest.getValue("export-service");
-		if (exportServices != null) {
-			List entries = manifest.getEntries(exportServices);
-			for (Iterator i = entries.iterator(); i.hasNext();) {
-				ManifestEntry entry = (ManifestEntry) i.next();
-				CapabilityImpl cap = createServiceCapability(entry);
-				resource.addCapability(cap);
-			}
-		}
-	}
-
-	String translated(String key) {
-		return translate(manifest.getValue(key));
-	}
-
-	void doFragment(ResourceImpl resource) {
-		// Check if we are a fragment
-		ManifestEntry entry = manifest.getHost();
-		if (entry == null) {
-			return;
-		}
-		else {
-			// We are a fragment, create a requirement
-			// to our host.
-			RequirementImpl r = new RequirementImpl("bundle");
-			StringBuffer sb = new StringBuffer();
-			sb.append("(&(symbolicname=");
-			sb.append(entry.getName());
-			sb.append(")(version>=");
-			sb.append(entry.getVersion());
-			sb.append("))");
-			r.setFilter(sb.toString());
-			r.setComment("Required Host " + entry.getName() );
-			r.setExtend(true);
-			r.setOptional(false);
-			r.setMultiple(false);
-			resource.addRequirement(r);
-
-			// And insert a capability that we are available
-			// as a fragment. ### Do we need that with extend?
-			CapabilityImpl capability = new CapabilityImpl("fragment");
-			capability.addProperty("host", entry.getName());
-			capability.addProperty("version", entry.getVersion());
-			resource.addCapability(capability);
-		}
-	}
-
-	void doRequires(ResourceImpl resource) {
-		List entries = manifest.getRequire();
-		if (entries == null)
-			return;
-
-		for (Iterator i = entries.iterator(); i.hasNext();) {
-			ManifestEntry entry = (ManifestEntry) i.next();
-			RequirementImpl r = new RequirementImpl("bundle");
-
-			StringBuffer sb = new StringBuffer();
-			sb.append("(&(symbolicname=");
-			sb.append(entry.getName());
-			sb.append(")(version>=");
-			sb.append(entry.getVersion());
-			sb.append("))");
-			r.setFilter(sb.toString());
-			r.setComment("Require Bundle " + entry.getName() + "; "
-					+ entry.getVersion());
-			if (entry.directives == null
-					|| "true".equalsIgnoreCase((String) entry.directives
-							.get("resolution")))
-				r.setOptional(false);
-			else
-				r.setOptional(true);
-			resource.addRequirement(r);
-		}
-	}
-
-	void doExecutionEnvironment(ResourceImpl resource) {
-		String[] parts = manifest.getRequiredExecutionEnvironments();
-		if (parts == null)
-			return;
-
-		StringBuffer sb = new StringBuffer();
-		sb.append("(|");
-		for (int i = 0; i < parts.length; i++) {
-			String part = parts[i];
-			sb.append("(ee=");
-			sb.append(part);
-			sb.append(")");
-		}
-		sb.append(")");
-
-		RequirementImpl req = new RequirementImpl("ee");
-		req.setFilter(sb.toString());
-		req.setComment("Execution Environment " + sb.toString());
-		resource.addRequirement(req);
-	}
-
-	void doImports(ResourceImpl resource) {
-		List requirements = new ArrayList();
-		List packages = manifest.getImports();
-		if (packages == null)
-			return;
-
-		for (Iterator i = packages.iterator(); i.hasNext();) {
-			ManifestEntry pack = (ManifestEntry) i.next();
-			RequirementImpl requirement = new RequirementImpl("package");
-
-			createImportFilter(requirement, "package", pack);
-			requirement.setComment("Import package " + pack);
-			requirements.add(requirement);
-		}
-		for (Iterator i = requirements.iterator(); i.hasNext();)
-			resource.addRequirement((RequirementImpl) i.next());
-	}
-
-	String createServiceFilter(ManifestEntry pack) {
-		StringBuffer filter = new StringBuffer();
-		filter.append("(service=");
-		filter.append(pack.getName());
-		filter.append(")");
-		return filter.toString();
-	}
-
-	void createImportFilter(RequirementImpl req, String name, ManifestEntry pack) {
-		StringBuffer filter = new StringBuffer();
-		filter.append("(&(");
-		filter.append(name);
-		filter.append("=");
-		filter.append(pack.getName());
-		filter.append(")");
-		VersionRange version = pack.getVersion();
-		if (version != null) {
-			if ( version.isRange() ) {
-				filter.append("(version");
-				filter.append(">");
-				if (version.includeLow())
-					filter.append("=");
-				filter.append(version.low);
-				filter.append(")");
-
-				filter.append("(version");
-				filter.append("<");
-				if (version.includeHigh())
-					filter.append("=");
-				filter.append(version.high);
-				filter.append(")");
-			}
-			else {
-				filter.append("(version>=");
-				filter.append(pack.getVersion());
-				filter.append(")");
-			}
-		}
-		Map attributes = pack.getAttributes();
-		Set attrs = doImportPackageAttributes(req, filter, attributes);
-		if (attrs.size() > 0) {
-			String del = "";
-			filter.append("(mandatory:<*");
-			for (Iterator i = attrs.iterator(); i.hasNext();) {
-				filter.append(del);
-				filter.append(i.next());
-				del = ", ";
-			}
-			filter.append(")");
-		}
-		filter.append(")");
-		req.setFilter(filter.toString());
-	}
-
-	Set doImportPackageAttributes(RequirementImpl req, StringBuffer filter,
-			Map attributes) {
-		HashSet set = new HashSet();
-
-		if (attributes != null)
-			for (Iterator i = attributes.keySet().iterator(); i.hasNext();) {
-				String attribute = (String) i.next();
-				String value = (String) attributes.get(attribute);
-				if (attribute.equalsIgnoreCase("specification-version")
-						|| attribute.equalsIgnoreCase("version"))
-					continue;
-				else if (attribute.equalsIgnoreCase("resolution:")) {
-					req.setOptional(value.equalsIgnoreCase("optional"));
-				}
-				if (attribute.endsWith(":")) {
-					// Ignore
-				}
-				else {
-					filter.append("(");
-					filter.append(attribute);
-					filter.append("=");
-					filter.append(attributes.get(attribute));
-					filter.append(")");
-					set.add(attribute);
-				}
-			}
-		return set;
-	}
-
-	void doBundle(ResourceImpl resource) {
-		CapabilityImpl capability = new CapabilityImpl("bundle");
-		capability.addProperty("symbolicname", manifest.getSymbolicName());
-		if (manifest.getValue("Bundle-Name") != null)
-			capability.addProperty(
-					Resource.PRESENTATION_NAME,
-					translated("Bundle-Name"));
-		capability.addProperty("version", manifest.getVersion());
-		capability
-				.addProperty("manifestversion", manifest.getManifestVersion());
-
-		/**
-		 * Is this needed TODO
-		 */
-		ManifestEntry host = manifest.getHost();
-		if (host != null) {
-			capability.addProperty("host", host.getName());
-			if (host.getVersion() != null)
-				capability.addProperty("version", host.getVersion());
-		}
-		resource.addCapability(capability);
-	}
-
-	void doExports(ResourceImpl resource) {
-		List capabilities = new ArrayList();
-		List packages = manifest.getExports();
-		if (packages != null) {
-			for (Iterator i = packages.iterator(); i.hasNext();) {
-				ManifestEntry pack = (ManifestEntry) i.next();
-				CapabilityImpl capability = createCapability("package", pack);
-				capabilities.add(capability);
-			}
-        }
-		for (Iterator i = capabilities.iterator(); i.hasNext();)
-			resource.addCapability((CapabilityImpl) i.next());
-	}
-
-	CapabilityImpl createServiceCapability(ManifestEntry pack) {
-		CapabilityImpl capability = new CapabilityImpl("service");
-		capability.addProperty("service", pack.getName());
-		return capability;
-	}
-
-	CapabilityImpl createCapability(String name, ManifestEntry pack) {
-		CapabilityImpl capability = new CapabilityImpl(name);
-		capability.addProperty(name, pack.getName());
-		capability.addProperty("version", pack.getVersion());
-		Map attributes = pack.getAttributes();
-		if (attributes != null)
-			for (Iterator at = attributes.keySet().iterator(); at.hasNext();) {
-				String key = (String) at.next();
-				if (key.equalsIgnoreCase("specification-version")
-						|| key.equalsIgnoreCase("version"))
-					continue;
-				else {
-					Object value = attributes.get(key);
-					capability.addProperty(key, value);
-				}
-			}
-		return capability;
-	}
-
-	String translate(String s) {
-		if (s == null)
-			return null;
-
-		if (!s.startsWith("%")) {
-			return s;
-		}
-
-		if (localization == null)
-			try {
-				localization = new Properties();
-				String path = manifest
-						.getValue("Bundle-Localization", "bundle");
-				path += ".properties";
-				InputStream in = jar.getInputStream(new ZipEntry(path));
-				if (in != null) {
-					localization.load(in);
-					in.close();
-				}
-			}
-			catch (IOException e) {
-				e.printStackTrace();
-			}
-		s = s.substring(1);
-		return localization.getProperty(s, s);
-	}
-
-	File getZipFile() {
-		return bundleJar;
-	}
+/*
+ * $Id: BundleInfo.java 92 2008-11-06 07:46:37Z peter.kriens@aqute.biz $
+ * 
+ * Copyright (c) OSGi Alliance (2002, 2006, 2007). All Rights Reserved.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.osgi.impl.bundle.obr.resource;
+
+import java.io.*;
+import java.net.URL;
+import java.util.*;
+import java.util.zip.*;
+
+import org.osgi.service.obr.Resource;
+
+/**
+ * Convert a bundle to a generic resource description and store its local
+ * dependencies (like for example a license file in the JAR) in a zip file.
+ * 
+ * @version $Revision: 92 $
+ */
+public class BundleInfo {
+	Manifest manifest;
+	File bundleJar;
+	ZipFile jar;
+	String license;
+	Properties localization;
+	RepositoryImpl repository;
+
+	/**
+	 * Parse a zipFile from the file system. We only need the manifest and the
+	 * localization. So a zip file is used to minimze memory consumption.
+	 * 
+	 * @param bundleJar
+	 *            Path name
+	 * @throws Exception
+	 *             Any errors that occur
+	 */
+	public BundleInfo(RepositoryImpl repository, File bundleJar)
+			throws Exception {
+		this.bundleJar = bundleJar;
+		this.repository = repository;
+
+		if (!this.bundleJar.exists())
+			throw new FileNotFoundException(bundleJar.toString());
+
+		jar = new ZipFile(bundleJar);
+		ZipEntry entry = jar.getEntry("META-INF/MANIFEST.MF");
+		if (entry == null)
+			throw new FileNotFoundException("No Manifest in "
+					+ bundleJar.toString());
+		manifest = new Manifest(jar.getInputStream(entry));
+	}
+
+	public BundleInfo(Manifest manifest) throws Exception {
+		this.manifest = manifest;
+	}
+
+	/**
+	 * Convert the bundle to a Resource. All URIs are going to be abslute, but
+	 * could be local.
+	 * 
+	 * @return the resource
+	 * @throws Exception
+	 */
+	public ResourceImpl build() throws Exception {
+		ResourceImpl resource;
+		// Setup the manifest
+		// and create a resource
+		resource = new ResourceImpl(repository, manifest.getSymbolicName(),
+				manifest.getVersion());
+
+		try {
+
+			// Calculate the location URL of the JAR
+			URL location = new URL("jar:" + bundleJar.toURL().toString() + "!/");
+			resource.setURL(bundleJar.toURL());
+			resource.setFile(bundleJar);
+
+			doReferences(resource, location);
+			doSize(resource);
+			doCategories(resource);
+			doImportExportServices(resource);
+			doDeclarativeServices(resource);
+			doFragment(resource);
+			doRequires(resource);
+			doBundle(resource);
+			doExports(resource);
+			doImports(resource);
+			doExecutionEnvironment(resource);
+
+			return resource;
+		} finally {
+			try {
+				jar.close();
+			} catch (Exception e) {
+				// ignore
+			}
+		}
+	}
+
+	/**
+	 * Check the size and add it.
+	 * 
+	 * @param resource
+	 */
+	void doSize(ResourceImpl resource) {
+		long size = bundleJar.length();
+		if (size > 0)
+			resource.setSize(size);
+	}
+
+	/**
+	 * Find the categories, break them up and add them.
+	 * 
+	 * @param resource
+	 */
+	void doCategories(ResourceImpl resource) {
+		for (int i = 0; i < manifest.getCategories().length; i++) {
+			String category = manifest.getCategories()[i];
+			resource.addCategory(category);
+		}
+	}
+
+	void doReferences(ResourceImpl resource, URL location) {
+		// Presentation name
+		String name = translated("Bundle-Name");
+		if (name != null)
+			resource.setPresentationName(name);
+
+		// Handle license. -l allows a global license
+		// set when no license is included.
+
+		String license = translated("Bundle-License");
+		if (license != null)
+			resource.setLicense(toURL(location, license));
+		else if (this.license != null)
+			resource.setLicense(toURL(location, this.license));
+
+		String description = translated("Bundle-Description");
+		if (description != null)
+			resource.setDescription(description);
+
+		String copyright = translated("Bundle-Copyright");
+		if (copyright != null)
+			resource.setCopyright(copyright);
+
+		String documentation = translated("Bundle-DocURL");
+		if (documentation != null)
+			resource.setDocumentation(toURL(location, documentation));
+
+		String source = manifest.getValue("Bundle-Source");
+		if (source != null)
+			resource.setSource(toURL(location, source));
+	}
+
+	URL toURL(URL location, String source) {
+		try {
+			return new URL(location, source);
+		} catch (Exception e) {
+			System.err.println("Error in converting url: " + location + " : "
+					+ source);
+			return null;
+		}
+	}
+
+	void doDeclarativeServices(ResourceImpl resource) throws Exception {
+		String serviceComponent = manifest.getValue("service-component");
+		if (serviceComponent == null)
+			return;
+
+		StringTokenizer st = new StringTokenizer(serviceComponent, " ,\t");
+		String parts[] = new String[st.countTokens()];
+		for (int i = 0; i < parts.length; i++)
+			parts[i] = st.nextToken();
+
+		for (int i = 0; i < parts.length; i++) {
+			ZipEntry entry = jar.getEntry(parts[i]);
+			if (entry == null) {
+				System.err.println("Bad Service-Component header: "
+						+ serviceComponent + ", no such file " + parts[i]);
+			}
+			InputStream in = jar.getInputStream(entry);
+			// TODO parse declarative services files.
+			in.close();
+		}
+	}
+
+	void doImportExportServices(ResourceImpl resource) throws IOException {
+		String importServices = manifest.getValue("import-service");
+		if (importServices != null) {
+			List entries = manifest.getEntries(importServices);
+			for (Iterator i = entries.iterator(); i.hasNext();) {
+				ManifestEntry entry = (ManifestEntry) i.next();
+				RequirementImpl ri = new RequirementImpl("service");
+				ri.setFilter(createServiceFilter(entry));
+				ri.setComment("Import Service " + entry.getName());
+
+				// TODO the following is arbitrary
+				ri.setOptional(false);
+				ri.setMultiple(true);
+				resource.addRequirement(ri);
+			}
+		}
+
+		String exportServices = manifest.getValue("export-service");
+		if (exportServices != null) {
+			List entries = manifest.getEntries(exportServices);
+			for (Iterator i = entries.iterator(); i.hasNext();) {
+				ManifestEntry entry = (ManifestEntry) i.next();
+				CapabilityImpl cap = createServiceCapability(entry);
+				resource.addCapability(cap);
+			}
+		}
+	}
+
+	String translated(String key) {
+		return translate(manifest.getValue(key));
+	}
+
+	void doFragment(ResourceImpl resource) {
+		// Check if we are a fragment
+		ManifestEntry entry = manifest.getHost();
+		if (entry == null) {
+			return;
+		} else {
+			// We are a fragment, create a requirement
+			// to our host.
+			RequirementImpl r = new RequirementImpl("bundle");
+			StringBuffer sb = new StringBuffer();
+			sb.append("(&(symbolicname=");
+			sb.append(entry.getName());
+			sb.append(")");
+			appendVersion(sb, entry.getVersion());
+			sb.append(")");
+			r.setFilter(sb.toString());
+			r.setComment("Required Host " + entry.getName());
+			r.setExtend(true);
+			r.setOptional(false);
+			r.setMultiple(false);
+			resource.addRequirement(r);
+
+			// And insert a capability that we are available
+			// as a fragment. ### Do we need that with extend?
+			CapabilityImpl capability = new CapabilityImpl("fragment");
+			capability.addProperty("host", entry.getName());
+			capability.addProperty("version", entry.getVersion());
+			resource.addCapability(capability);
+		}
+	}
+
+	void doRequires(ResourceImpl resource) {
+		List entries = manifest.getRequire();
+		if (entries == null)
+			return;
+
+		for (Iterator i = entries.iterator(); i.hasNext();) {
+			ManifestEntry entry = (ManifestEntry) i.next();
+			RequirementImpl r = new RequirementImpl("bundle");
+
+			Map attrs = entry.getAttributes();
+			String version = "0";
+			if (attrs != null) {
+				if (attrs.containsKey("bundle-version"))
+					version = (String) attrs.get("bundle-version");
+				else
+					version = "0";
+			}
+			VersionRange v = new VersionRange(version);
+
+			StringBuffer sb = new StringBuffer();
+			sb.append("(&(symbolicname=");
+			sb.append(entry.getName());
+			sb.append(")");
+			appendVersion(sb, v);
+			sb.append(")");
+			r.setFilter(sb.toString());
+
+			r.setComment("Require Bundle " + entry.getName() + "; " + v);
+			if (entry.directives == null
+					|| "true".equalsIgnoreCase((String) entry.directives
+							.get("resolution")))
+				r.setOptional(false);
+			else
+				r.setOptional(true);
+			resource.addRequirement(r);
+		}
+	}
+
+	void doExecutionEnvironment(ResourceImpl resource) {
+		String[] parts = manifest.getRequiredExecutionEnvironments();
+		if (parts == null)
+			return;
+
+		StringBuffer sb = new StringBuffer();
+		sb.append("(|");
+		for (int i = 0; i < parts.length; i++) {
+			String part = parts[i];
+			sb.append("(ee=");
+			sb.append(part);
+			sb.append(")");
+		}
+		sb.append(")");
+
+		RequirementImpl req = new RequirementImpl("ee");
+		req.setFilter(sb.toString());
+		req.setComment("Execution Environment " + sb.toString());
+		resource.addRequirement(req);
+	}
+
+	void doImports(ResourceImpl resource) {
+		List requirements = new ArrayList();
+		List packages = manifest.getImports();
+		if (packages == null)
+			return;
+
+		for (Iterator i = packages.iterator(); i.hasNext();) {
+			ManifestEntry pack = (ManifestEntry) i.next();
+			RequirementImpl requirement = new RequirementImpl("package");
+
+			createImportFilter(requirement, "package", pack);
+			requirement.setComment("Import package " + pack);
+			String resolution = pack.getDirective("resolution");
+			requirement.setOptional("optional".equals(resolution));
+			requirements.add(requirement);
+		}
+		for (Iterator i = requirements.iterator(); i.hasNext();)
+			resource.addRequirement((RequirementImpl) i.next());
+	}
+
+	String createServiceFilter(ManifestEntry pack) {
+		StringBuffer filter = new StringBuffer();
+		filter.append("(service=");
+		filter.append(pack.getName());
+		filter.append(")");
+		return filter.toString();
+	}
+
+	void createImportFilter(RequirementImpl req, String name, ManifestEntry pack) {
+		StringBuffer filter = new StringBuffer();
+		filter.append("(&(");
+		filter.append(name);
+		filter.append("=");
+		filter.append(pack.getName());
+		filter.append(")");
+		appendVersion(filter, pack.getVersion());
+		Map attributes = pack.getAttributes();
+		Set attrs = doImportPackageAttributes(req, filter, attributes);
+		if (attrs.size() > 0) {
+			String del = "";
+			filter.append("(mandatory:<*");
+			for (Iterator i = attrs.iterator(); i.hasNext();) {
+				filter.append(del);
+				filter.append(i.next());
+				del = ", ";
+			}
+			filter.append(")");
+		}
+		filter.append(")");
+		req.setFilter(filter.toString());
+	}
+
+	private void appendVersion(StringBuffer filter, VersionRange version) {
+		if (version != null) {
+			if (version.isRange()) {
+				filter.append("(version");
+				filter.append(">");
+				if (version.includeLow())
+					filter.append("=");
+				filter.append(version.low);
+				filter.append(")");
+
+				filter.append("(version");
+				filter.append("<");
+				if (version.includeHigh())
+					filter.append("=");
+				filter.append(version.high);
+				filter.append(")");
+			} else {
+				filter.append("(version>=");
+				filter.append(version);
+				filter.append(")");
+			}
+		}
+	}
+
+	Set doImportPackageAttributes(RequirementImpl req, StringBuffer filter,
+			Map attributes) {
+		HashSet set = new HashSet();
+
+		if (attributes != null)
+			for (Iterator i = attributes.keySet().iterator(); i.hasNext();) {
+				String attribute = (String) i.next();
+				String value = (String) attributes.get(attribute);
+				if (attribute.equalsIgnoreCase("specification-version")
+						|| attribute.equalsIgnoreCase("version"))
+					continue;
+				else if (attribute.equalsIgnoreCase("resolution:")) {
+					req.setOptional(value.equalsIgnoreCase("optional"));
+				}
+				if (attribute.endsWith(":")) {
+					// Ignore
+				} else {
+					filter.append("(");
+					filter.append(attribute);
+					filter.append("=");
+					filter.append(attributes.get(attribute));
+					filter.append(")");
+					set.add(attribute);
+				}
+			}
+		return set;
+	}
+
+	void doBundle(ResourceImpl resource) {
+		CapabilityImpl capability = new CapabilityImpl("bundle");
+		capability.addProperty("symbolicname", manifest.getSymbolicName());
+		if (manifest.getValue("Bundle-Name") != null)
+			capability.addProperty(Resource.PRESENTATION_NAME,
+					translated("Bundle-Name"));
+		capability.addProperty("version", manifest.getVersion());
+		capability
+				.addProperty("manifestversion", manifest.getManifestVersion());
+
+		/**
+		 * Is this needed TODO
+		 */
+		ManifestEntry host = manifest.getHost();
+		if (host != null) {
+			capability.addProperty("host", host.getName());
+			if (host.getVersion() != null)
+				capability.addProperty("version", host.getVersion());
+		}
+		resource.addCapability(capability);
+	}
+
+	void doExports(ResourceImpl resource) {
+		List capabilities = new ArrayList();
+		List packages = manifest.getExports();
+		if (packages != null) {
+			for (Iterator i = packages.iterator(); i.hasNext();) {
+				ManifestEntry pack = (ManifestEntry) i.next();
+				CapabilityImpl capability = createCapability("package", pack);
+				capabilities.add(capability);
+			}
+		}
+		for (Iterator i = capabilities.iterator(); i.hasNext();)
+			resource.addCapability((CapabilityImpl) i.next());
+	}
+
+	CapabilityImpl createServiceCapability(ManifestEntry pack) {
+		CapabilityImpl capability = new CapabilityImpl("service");
+		capability.addProperty("service", pack.getName());
+		return capability;
+	}
+
+	CapabilityImpl createCapability(String name, ManifestEntry pack) {
+		CapabilityImpl capability = new CapabilityImpl(name);
+		capability.addProperty(name, pack.getName());
+		capability.addProperty("version", pack.getVersion());
+		Map attributes = pack.getAttributes();
+		if (attributes != null)
+			for (Iterator at = attributes.keySet().iterator(); at.hasNext();) {
+				String key = (String) at.next();
+				if (key.equalsIgnoreCase("specification-version")
+						|| key.equalsIgnoreCase("version"))
+					continue;
+				else {
+					Object value = attributes.get(key);
+					capability.addProperty(key, value);
+				}
+			}
+		Map directives = pack.getDirectives();
+		if (directives != null)
+			for (Iterator at = directives.keySet().iterator(); at.hasNext();) {
+				String key = (String) at.next();
+				Object value = directives.get(key);
+				capability.addProperty(key, value);
+			}
+		return capability;
+	}
+
+	String translate(String s) {
+		if (s == null)
+			return null;
+
+		if (!s.startsWith("%")) {
+			return s;
+		}
+
+		if (localization == null)
+			try {
+				localization = new Properties();
+				String path = manifest
+						.getValue("Bundle-Localization", "bundle");
+				path += ".properties";
+				InputStream in = jar.getInputStream(new ZipEntry(path));
+				if (in != null) {
+					localization.load(in);
+					in.close();
+				}
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+		s = s.substring(1);
+		return localization.getProperty(s, s);
+	}
+
+	File getZipFile() {
+		return bundleJar;
+	}
 }
\ No newline at end of file

Modified: felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/CapabilityImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/CapabilityImpl.java?rev=722850&r1=722849&r2=722850&view=diff
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/CapabilityImpl.java (original)
+++ felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/CapabilityImpl.java Wed Dec  3 04:03:12 2008
@@ -1,109 +1,131 @@
-/*
- * $Id: CapabilityImpl.java 44 2007-07-13 20:49:41Z hargrave@us.ibm.com $
- * 
- * Copyright (c) OSGi Alliance (2002, 2006, 2007). All Rights Reserved.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.osgi.impl.bundle.obr.resource;
-
-import java.util.*;
-
-import org.osgi.service.obr.Capability;
-import org.xmlpull.v1.XmlPullParser;
-
-
-
-public class CapabilityImpl implements Capability {
-	String				name;
-	Map	properties	= new TreeMap();
-
-	public CapabilityImpl(String name) {
-		this.name = name;
-	}
-
-	public CapabilityImpl(XmlPullParser parser) throws Exception {
-		parser.require(XmlPullParser.START_TAG, null, "capability");
-		name = parser.getAttributeValue(null,"name");
-		while ( parser.nextTag() == XmlPullParser.START_TAG ) {
-			if ( parser.getName().equals("p")) {
-				String name = parser.getAttributeValue(null,"n");
-				String value = parser.getAttributeValue(null,"v");
-				String type = parser.getAttributeValue(null,"t");
-				Object v = value;
-
-				if ( "nummeric".equals(type))
-					v = new Long(value);
-				else if ( "version".equals(type))
-					v = new VersionRange(value);
-				addProperty(name,v);
-			}
-			parser.next();
-			parser.require(XmlPullParser.END_TAG, null, "p" );
-		}
-		parser.require(XmlPullParser.END_TAG, null, "capability" );
-	}
-
-
-	public void addProperty(String key, Object value) {
-		List values = (List) properties.get(key);
-		if (values == null) {
-			values = new ArrayList();
-			properties.put(key, values);
-		}
-		values.add(value);
-	}
-
-	public Tag toXML() {
-		return toXML(this);
-	}
-	
-	public static Tag toXML(Capability capability) {
-		Tag tag = new Tag("capability");
-		tag.addAttribute("name", capability.getName());
-		Map properties = capability.getProperties();
-		for ( Iterator k= properties.keySet().iterator(); k.hasNext(); ) {
-			String key = (String) k.next();
-			List values = (List) properties.get(key);
-			for ( Iterator v = values.iterator(); v.hasNext(); ) {
-				Object value = v.next();
-				Tag p = new Tag("p");
-				tag.addContent(p);
-				p.addAttribute("n", key);
-				if ( value != null )
-					p.addAttribute("v", value.toString());
-				else
-					System.out.println("Missing value " + key);
-				String type = null;
-				if (value instanceof Number )
-					type = "number";
-				else if (value.getClass() == VersionRange.class)
-					type = "version";
-				if (type != null)
-					p.addAttribute("t", type);
-			}
-		}
-		return tag;
-	}
-
-
-	public String getName() {
-		return name;
-	}
-
-
-	public Map getProperties() {
-		return properties;
-	}
-
-}
+/*
+ * $Id: CapabilityImpl.java 84 2008-08-28 08:11:30Z peter.kriens@aqute.biz $
+ * 
+ * Copyright (c) OSGi Alliance (2002, 2006, 2007). All Rights Reserved.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.osgi.impl.bundle.obr.resource;
+
+import java.lang.reflect.Array;
+import java.util.*;
+
+import org.osgi.service.obr.Capability;
+import org.xmlpull.v1.XmlPullParser;
+
+
+
+public class CapabilityImpl implements Capability {
+	String				name;
+	Map	properties	= new TreeMap();
+
+	public CapabilityImpl(String name) {
+		this.name = name;
+	}
+
+	public CapabilityImpl(XmlPullParser parser) throws Exception {
+		parser.require(XmlPullParser.START_TAG, null, "capability");
+		name = parser.getAttributeValue(null,"name");
+		while ( parser.nextTag() == XmlPullParser.START_TAG ) {
+			if ( parser.getName().equals("p")) {
+				String name = parser.getAttributeValue(null,"n");
+				String value = parser.getAttributeValue(null,"v");
+				String type = parser.getAttributeValue(null,"t");
+				Object v = value;
+
+				if ( "nummeric".equals(type))
+					v = new Long(value);
+				else if ( "version".equals(type))
+					v = new VersionRange(value);
+				addProperty(name,v);
+			}
+			parser.next();
+			parser.require(XmlPullParser.END_TAG, null, "p" );
+		}
+		parser.require(XmlPullParser.END_TAG, null, "capability" );
+	}
+
+
+	public void addProperty(String key, Object value) {
+		List values = (List) properties.get(key);
+		if (values == null) {
+			values = new ArrayList();
+			properties.put(key, values);
+		}
+		values.add(value);
+	}
+
+	public Tag toXML() {
+		return toXML(this);
+	}
+	
+	public static Tag toXML(Capability capability) {
+		Tag tag = new Tag("capability");
+		tag.addAttribute("name", capability.getName());
+		Map properties = capability.getProperties();
+		for ( Iterator k= properties.keySet().iterator(); k.hasNext(); ) {
+			String key = (String) k.next();
+			List values = (List) properties.get(key);
+			for ( Iterator v = values.iterator(); v.hasNext(); ) {
+				Object value = v.next();
+				Tag p = new Tag("p");
+				tag.addContent(p);
+				p.addAttribute("n", key);
+				if ( value != null ) {
+					p.addAttribute("v", valueString(value));
+					String type = null;
+					if (value instanceof Number )
+						type = "number";
+					else if (value.getClass() == VersionRange.class)
+						type = "version";
+					else if ( value.getClass().isArray() ) {
+						type = "set";
+					}
+					
+					if (type != null)
+						p.addAttribute("t", type);
+				}
+				else
+					System.out.println("Missing value " + key);
+			}
+		}
+		return tag;
+	}
+
+
+	private static String valueString(Object value) {
+		if ( value.getClass().isArray() ) {
+			StringBuffer buf = new StringBuffer();
+			for ( int i = 0; i < Array.getLength(value); i++) {
+				if ( i > 0 ) {
+					buf.append( "," );
+				}
+				buf.append( Array.get(value, i).toString() );
+			}
+			return buf.toString();
+		}
+		else {
+			return value.toString();
+		}
+	}
+
+	public String getName() {
+		return name;
+	}
+
+
+	public Map getProperties() {
+		return properties;
+	}
+
+}

Modified: felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/FilterImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/FilterImpl.java?rev=722850&r1=722849&r2=722850&view=diff
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/FilterImpl.java (original)
+++ felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/FilterImpl.java Wed Dec  3 04:03:12 2008
@@ -1,437 +1,437 @@
-/*
- * $Id: FilterImpl.java 44 2007-07-13 20:49:41Z hargrave@us.ibm.com $
- * 
- * Copyright (c) 2000 Gatespace AB. All Rights Reserved.
- * Copyright (c) OSGi Alliance (2002, 2006, 2007). All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.osgi.impl.bundle.obr.resource;
-
-import java.lang.reflect.*;
-import java.math.BigInteger;
-import java.util.*;
-
-public class FilterImpl {
-	final char		WILDCARD	= 65535;
-
-	final int		EQ			= 0;
-	final int		LE			= 1;
-	final int		GE			= 2;
-	final int		APPROX		= 3;
-	final int		LESS		= 4;
-	final int		GREATER		= 5;
-	final int		SUBSET		= 6;
-	final int		SUPERSET	= 7;
-
-	private String	filter;
-
-	abstract class Query {
-		static final String	GARBAGE		= "Trailing garbage";
-		static final String	MALFORMED	= "Malformed query";
-		static final String	EMPTY		= "Empty list";
-		static final String	SUBEXPR		= "No subexpression";
-		static final String	OPERATOR	= "Undefined operator";
-		static final String	TRUNCATED	= "Truncated expression";
-		static final String	EQUALITY	= "Only equality supported";
-
-		private String		tail;
-
-		boolean match() throws IllegalArgumentException {
-			tail = filter;
-			boolean val = doQuery();
-			if (tail.length() > 0)
-				error(GARBAGE);
-			return val;
-		}
-
-		private boolean doQuery() throws IllegalArgumentException {
-			if (tail.length() < 3 || !prefix("("))
-				error(MALFORMED);
-			boolean val;
-
-			switch (tail.charAt(0)) {
-				case '&' :
-					val = doAnd();
-					break;
-				case '|' :
-					val = doOr();
-					break;
-				case '!' :
-					val = doNot();
-					break;
-				default :
-					val = doSimple();
-					break;
-			}
-
-			if (!prefix(")"))
-				error(MALFORMED);
-			return val;
-		}
-
-		private boolean doAnd() throws IllegalArgumentException {
-			tail = tail.substring(1);
-			boolean val = true;
-			if (!tail.startsWith("("))
-				error(EMPTY);
-			do {
-				if (!doQuery())
-					val = false;
-			} while (tail.startsWith("("));
-			return val;
-		}
-
-		private boolean doOr() throws IllegalArgumentException {
-			tail = tail.substring(1);
-			boolean val = false;
-			if (!tail.startsWith("("))
-				error(EMPTY);
-			do {
-				if (doQuery())
-					val = true;
-			} while (tail.startsWith("("));
-			return val;
-		}
-
-		private boolean doNot() throws IllegalArgumentException {
-			tail = tail.substring(1);
-			if (!tail.startsWith("("))
-				error(SUBEXPR);
-			return !doQuery();
-		}
-
-		private boolean doSimple() throws IllegalArgumentException {
-			int op = 0;
-			Object attr = getAttr();
-
-			if (prefix("="))
-				op = EQ;
-			else if (prefix("<="))
-				op = LE;
-			else if (prefix(">="))
-				op = GE;
-			else if (prefix("~="))
-				op = APPROX;
-			else if (prefix("*>"))
-				op = SUPERSET;
-			else if (prefix("<*"))
-				op = SUBSET;
-			else if (prefix("<"))
-				op = LESS;
-			else if (prefix(">"))
-				op = GREATER;
-			else
-				error(OPERATOR);
-
-			return compare(attr, op, getValue());
-		}
-
-		private boolean prefix(String pre) {
-			if (!tail.startsWith(pre))
-				return false;
-			tail = tail.substring(pre.length());
-			return true;
-		}
-
-		private Object getAttr() {
-			int len = tail.length();
-			int ix = 0;
-			label: for (; ix < len; ix++) {
-				switch (tail.charAt(ix)) {
-					case '(' :
-					case ')' :
-					case '<' :
-					case '>' :
-					case '=' :
-					case '~' :
-					case '*' :
-					case '}' :
-					case '{' :
-					case '\\' :
-						break label;
-				}
-			}
-			String attr = tail.substring(0, ix).toLowerCase();
-			tail = tail.substring(ix);
-			return getProp(attr);
-		}
-
-		abstract Object getProp(String key);
-
-		private String getValue() {
-			StringBuffer sb = new StringBuffer();
-			int len = tail.length();
-			int ix = 0;
-			label: for (; ix < len; ix++) {
-				char c = tail.charAt(ix);
-				switch (c) {
-					case '(' :
-					case ')' :
-						break label;
-					case '*' :
-						sb.append(WILDCARD);
-						break;
-					case '\\' :
-						if (ix == len - 1)
-							break label;
-						sb.append(tail.charAt(++ix));
-						break;
-					default :
-						sb.append(c);
-						break;
-				}
-			}
-			tail = tail.substring(ix);
-			return sb.toString();
-		}
-
-		private void error(String m) throws IllegalArgumentException {
-			throw new IllegalArgumentException(m + " " + tail);
-		}
-
-		private boolean compare(Object obj, int op, String s) {
-			if (obj == null) {
-				// No value is ok for a subset
-				if (op == SUBSET)
-					return true;
-
-				// No value is ok for a superset when the value is
-				// empty
-				if (op == SUPERSET) {
-					return s.trim().length() == 0;
-				}
-
-				return false;
-			}
-			try {
-				Class numClass = obj.getClass();
-				if (numClass == String.class) {
-					return compareString((String) obj, op, s);
-				}
-				else if (numClass == Character.class) {
-					return compareString(obj.toString(), op, s);
-				}
-				else if (numClass == Long.class) {
-					return compareSign(op, Long.valueOf(s)
-							.compareTo((Long) obj));
-				}
-				else if (numClass == Integer.class) {
-					return compareSign(op, Integer.valueOf(s).compareTo(
-							(Integer) obj));
-				}
-				else if (numClass == Short.class) {
-					return compareSign(op, Short.valueOf(s).compareTo(
-							(Short) obj));
-				}
-				else if (numClass == Byte.class) {
-					return compareSign(op, Byte.valueOf(s)
-							.compareTo((Byte) obj));
-				}
-				else if (numClass == Double.class) {
-					return compareSign(op, Double.valueOf(s).compareTo(
-							(Double) obj));
-				}
-				else if (numClass == Float.class) {
-					return compareSign(op, Float.valueOf(s).compareTo(
-							(Float) obj));
-				}
-				else if (numClass == Boolean.class) {
-					if (op != EQ)
-						return false;
-					int a = Boolean.valueOf(s).booleanValue() ? 1 : 0;
-					int b = ((Boolean) obj).booleanValue() ? 1 : 0;
-					return compareSign(op, a - b);
-				}
-				else if (numClass == BigInteger.class) {
-					return compareSign(op, new BigInteger(s)
-							.compareTo((BigInteger) obj));
-				}
-				else if (obj instanceof Collection) {
-					if (op == SUBSET || op == SUPERSET) {
-						StringSet set = new StringSet(s);
-						if (op == SUBSET)
-							return set.containsAll((Collection) obj);
-						else
-							return ((Collection) obj).containsAll(set);
-					}
-
-					for (Iterator i = ((Collection) obj).iterator(); i
-							.hasNext();) {
-						Object element = i.next();
-						if (compare(element, op, s))
-							return true;
-					}
-				}
-				else if (numClass.isArray()) {
-					int len = Array.getLength(obj);
-					for (int i = 0; i < len; i++)
-						if (compare(Array.get(obj, i), op, s))
-							return true;
-				}
-				else {
-					try {
-						if (op == SUPERSET || op == SUBSET) {
-							StringSet set = new StringSet(s);
-							if (op == SUPERSET)
-								return set.contains(obj);
-							else
-								return set.size() == 0
-										|| (set.size() == 1 && set.iterator()
-												.next().equals(obj));
-						}
-						else {
-							Constructor constructor = numClass
-									.getConstructor(new Class[] {String.class});
-							Object instance = constructor
-									.newInstance(new Object[] {s});
-							switch (op) {
-								case EQ :
-									return obj.equals(instance);
-								case LESS :
-									return ((Comparable) obj)
-											.compareTo(instance) < 0;
-								case GREATER :
-									return ((Comparable) obj)
-											.compareTo(instance) > 0;
-								case LE :
-									return ((Comparable) obj)
-											.compareTo(instance) <= 0;
-								case GE :
-									return ((Comparable) obj)
-											.compareTo(instance) >= 0;
-							}
-						}
-					}
-					catch (Exception e) {
-						e.printStackTrace();
-						// Ignore
-					}
-				}
-			}
-			catch (Exception e) {
-			}
-			return false;
-		}
-	}
-
-	class DictQuery extends Query {
-		private Map	dict;
-
-		DictQuery(Map dict) {
-			this.dict = dict;
-		}
-
-		Object getProp(String key) {
-			return dict.get(key);
-		}
-	}
-
-	public FilterImpl(String filter) throws IllegalArgumentException {
-		// NYI: Normalize the filter string?
-		this.filter = filter;
-		if (filter == null || filter.length() == 0)
-			throw new IllegalArgumentException("Null query");
-	}
-
-	public boolean match(Map dict) {
-		try {
-			return new DictQuery(dict).match();
-		}
-		catch (IllegalArgumentException e) {
-			return false;
-		}
-	}
-
-	public String toString() {
-		return filter;
-	}
-
-	public boolean equals(Object obj) {
-		return obj != null && obj instanceof FilterImpl
-				&& filter.equals(((FilterImpl) obj).filter);
-	}
-
-	public int hashCode() {
-		return filter.hashCode();
-	}
-
-	boolean compareString(String s1, int op, String s2) {
-		switch (op) {
-			case EQ :
-				return patSubstr(s1, s2);
-			case APPROX :
-				return patSubstr(fixupString(s1), fixupString(s2));
-			default :
-				return compareSign(op, s2.compareTo(s1));
-		}
-	}
-
-	boolean compareSign(int op, int cmp) {
-		switch (op) {
-			case LE :
-				return cmp >= 0;
-			case GE :
-				return cmp <= 0;
-			case EQ :
-				return cmp == 0;
-			default : /* APPROX */
-				return cmp == 0;
-		}
-	}
-
-	String fixupString(String s) {
-		StringBuffer sb = new StringBuffer();
-		int len = s.length();
-		boolean isStart = true;
-		boolean isWhite = false;
-		for (int i = 0; i < len; i++) {
-			char c = s.charAt(i);
-			if (Character.isWhitespace(c)) {
-				isWhite = true;
-			}
-			else {
-				if (!isStart && isWhite)
-					sb.append(' ');
-				if (Character.isUpperCase(c))
-					c = Character.toLowerCase(c);
-				sb.append(c);
-				isStart = false;
-				isWhite = false;
-			}
-		}
-		return sb.toString();
-	}
-
-	boolean patSubstr(String s, String pat) {
-		if (s == null)
-			return false;
-		if (pat.length() == 0)
-			return s.length() == 0;
-		if (pat.charAt(0) == WILDCARD) {
-			pat = pat.substring(1);
-			for (;;) {
-				if (patSubstr(s, pat))
-					return true;
-				if (s.length() == 0)
-					return false;
-				s = s.substring(1);
-			}
-		}
-		else {
-			if (s.length() == 0 || s.charAt(0) != pat.charAt(0))
-				return false;
-			return patSubstr(s.substring(1), pat.substring(1));
-		}
-	}
-}
+/*
+ * $Id: FilterImpl.java 44 2007-07-13 20:49:41Z hargrave@us.ibm.com $
+ * 
+ * Copyright (c) 2000 Gatespace AB. All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2002, 2006, 2007). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.osgi.impl.bundle.obr.resource;
+
+import java.lang.reflect.*;
+import java.math.BigInteger;
+import java.util.*;
+
+public class FilterImpl {
+	final char		WILDCARD	= 65535;
+
+	final int		EQ			= 0;
+	final int		LE			= 1;
+	final int		GE			= 2;
+	final int		APPROX		= 3;
+	final int		LESS		= 4;
+	final int		GREATER		= 5;
+	final int		SUBSET		= 6;
+	final int		SUPERSET	= 7;
+
+	private String	filter;
+
+	abstract class Query {
+		static final String	GARBAGE		= "Trailing garbage";
+		static final String	MALFORMED	= "Malformed query";
+		static final String	EMPTY		= "Empty list";
+		static final String	SUBEXPR		= "No subexpression";
+		static final String	OPERATOR	= "Undefined operator";
+		static final String	TRUNCATED	= "Truncated expression";
+		static final String	EQUALITY	= "Only equality supported";
+
+		private String		tail;
+
+		boolean match() throws IllegalArgumentException {
+			tail = filter;
+			boolean val = doQuery();
+			if (tail.length() > 0)
+				error(GARBAGE);
+			return val;
+		}
+
+		private boolean doQuery() throws IllegalArgumentException {
+			if (tail.length() < 3 || !prefix("("))
+				error(MALFORMED);
+			boolean val;
+
+			switch (tail.charAt(0)) {
+				case '&' :
+					val = doAnd();
+					break;
+				case '|' :
+					val = doOr();
+					break;
+				case '!' :
+					val = doNot();
+					break;
+				default :
+					val = doSimple();
+					break;
+			}
+
+			if (!prefix(")"))
+				error(MALFORMED);
+			return val;
+		}
+
+		private boolean doAnd() throws IllegalArgumentException {
+			tail = tail.substring(1);
+			boolean val = true;
+			if (!tail.startsWith("("))
+				error(EMPTY);
+			do {
+				if (!doQuery())
+					val = false;
+			} while (tail.startsWith("("));
+			return val;
+		}
+
+		private boolean doOr() throws IllegalArgumentException {
+			tail = tail.substring(1);
+			boolean val = false;
+			if (!tail.startsWith("("))
+				error(EMPTY);
+			do {
+				if (doQuery())
+					val = true;
+			} while (tail.startsWith("("));
+			return val;
+		}
+
+		private boolean doNot() throws IllegalArgumentException {
+			tail = tail.substring(1);
+			if (!tail.startsWith("("))
+				error(SUBEXPR);
+			return !doQuery();
+		}
+
+		private boolean doSimple() throws IllegalArgumentException {
+			int op = 0;
+			Object attr = getAttr();
+
+			if (prefix("="))
+				op = EQ;
+			else if (prefix("<="))
+				op = LE;
+			else if (prefix(">="))
+				op = GE;
+			else if (prefix("~="))
+				op = APPROX;
+			else if (prefix("*>"))
+				op = SUPERSET;
+			else if (prefix("<*"))
+				op = SUBSET;
+			else if (prefix("<"))
+				op = LESS;
+			else if (prefix(">"))
+				op = GREATER;
+			else
+				error(OPERATOR);
+
+			return compare(attr, op, getValue());
+		}
+
+		private boolean prefix(String pre) {
+			if (!tail.startsWith(pre))
+				return false;
+			tail = tail.substring(pre.length());
+			return true;
+		}
+
+		private Object getAttr() {
+			int len = tail.length();
+			int ix = 0;
+			label: for (; ix < len; ix++) {
+				switch (tail.charAt(ix)) {
+					case '(' :
+					case ')' :
+					case '<' :
+					case '>' :
+					case '=' :
+					case '~' :
+					case '*' :
+					case '}' :
+					case '{' :
+					case '\\' :
+						break label;
+				}
+			}
+			String attr = tail.substring(0, ix).toLowerCase();
+			tail = tail.substring(ix);
+			return getProp(attr);
+		}
+
+		abstract Object getProp(String key);
+
+		private String getValue() {
+			StringBuffer sb = new StringBuffer();
+			int len = tail.length();
+			int ix = 0;
+			label: for (; ix < len; ix++) {
+				char c = tail.charAt(ix);
+				switch (c) {
+					case '(' :
+					case ')' :
+						break label;
+					case '*' :
+						sb.append(WILDCARD);
+						break;
+					case '\\' :
+						if (ix == len - 1)
+							break label;
+						sb.append(tail.charAt(++ix));
+						break;
+					default :
+						sb.append(c);
+						break;
+				}
+			}
+			tail = tail.substring(ix);
+			return sb.toString();
+		}
+
+		private void error(String m) throws IllegalArgumentException {
+			throw new IllegalArgumentException(m + " " + tail);
+		}
+
+		private boolean compare(Object obj, int op, String s) {
+			if (obj == null) {
+				// No value is ok for a subset
+				if (op == SUBSET)
+					return true;
+
+				// No value is ok for a superset when the value is
+				// empty
+				if (op == SUPERSET) {
+					return s.trim().length() == 0;
+				}
+
+				return false;
+			}
+			try {
+				Class numClass = obj.getClass();
+				if (numClass == String.class) {
+					return compareString((String) obj, op, s);
+				}
+				else if (numClass == Character.class) {
+					return compareString(obj.toString(), op, s);
+				}
+				else if (numClass == Long.class) {
+					return compareSign(op, Long.valueOf(s)
+							.compareTo((Long) obj));
+				}
+				else if (numClass == Integer.class) {
+					return compareSign(op, Integer.valueOf(s).compareTo(
+							(Integer) obj));
+				}
+				else if (numClass == Short.class) {
+					return compareSign(op, Short.valueOf(s).compareTo(
+							(Short) obj));
+				}
+				else if (numClass == Byte.class) {
+					return compareSign(op, Byte.valueOf(s)
+							.compareTo((Byte) obj));
+				}
+				else if (numClass == Double.class) {
+					return compareSign(op, Double.valueOf(s).compareTo(
+							(Double) obj));
+				}
+				else if (numClass == Float.class) {
+					return compareSign(op, Float.valueOf(s).compareTo(
+							(Float) obj));
+				}
+				else if (numClass == Boolean.class) {
+					if (op != EQ)
+						return false;
+					int a = Boolean.valueOf(s).booleanValue() ? 1 : 0;
+					int b = ((Boolean) obj).booleanValue() ? 1 : 0;
+					return compareSign(op, a - b);
+				}
+				else if (numClass == BigInteger.class) {
+					return compareSign(op, new BigInteger(s)
+							.compareTo((BigInteger) obj));
+				}
+				else if (obj instanceof Collection) {
+					if (op == SUBSET || op == SUPERSET) {
+						StringSet set = new StringSet(s);
+						if (op == SUBSET)
+							return set.containsAll((Collection) obj);
+						else
+							return ((Collection) obj).containsAll(set);
+					}
+
+					for (Iterator i = ((Collection) obj).iterator(); i
+							.hasNext();) {
+						Object element = i.next();
+						if (compare(element, op, s))
+							return true;
+					}
+				}
+				else if (numClass.isArray()) {
+					int len = Array.getLength(obj);
+					for (int i = 0; i < len; i++)
+						if (compare(Array.get(obj, i), op, s))
+							return true;
+				}
+				else {
+					try {
+						if (op == SUPERSET || op == SUBSET) {
+							StringSet set = new StringSet(s);
+							if (op == SUPERSET)
+								return set.contains(obj);
+							else
+								return set.size() == 0
+										|| (set.size() == 1 && set.iterator()
+												.next().equals(obj));
+						}
+						else {
+							Constructor constructor = numClass
+									.getConstructor(new Class[] {String.class});
+							Object instance = constructor
+									.newInstance(new Object[] {s});
+							switch (op) {
+								case EQ :
+									return obj.equals(instance);
+								case LESS :
+									return ((Comparable) obj)
+											.compareTo(instance) < 0;
+								case GREATER :
+									return ((Comparable) obj)
+											.compareTo(instance) > 0;
+								case LE :
+									return ((Comparable) obj)
+											.compareTo(instance) <= 0;
+								case GE :
+									return ((Comparable) obj)
+											.compareTo(instance) >= 0;
+							}
+						}
+					}
+					catch (Exception e) {
+						e.printStackTrace();
+						// Ignore
+					}
+				}
+			}
+			catch (Exception e) {
+			}
+			return false;
+		}
+	}
+
+	class DictQuery extends Query {
+		private Map	dict;
+
+		DictQuery(Map dict) {
+			this.dict = dict;
+		}
+
+		Object getProp(String key) {
+			return dict.get(key);
+		}
+	}
+
+	public FilterImpl(String filter) throws IllegalArgumentException {
+		// NYI: Normalize the filter string?
+		this.filter = filter;
+		if (filter == null || filter.length() == 0)
+			throw new IllegalArgumentException("Null query");
+	}
+
+	public boolean match(Map dict) {
+		try {
+			return new DictQuery(dict).match();
+		}
+		catch (IllegalArgumentException e) {
+			return false;
+		}
+	}
+
+	public String toString() {
+		return filter;
+	}
+
+	public boolean equals(Object obj) {
+		return obj != null && obj instanceof FilterImpl
+				&& filter.equals(((FilterImpl) obj).filter);
+	}
+
+	public int hashCode() {
+		return filter.hashCode();
+	}
+
+	boolean compareString(String s1, int op, String s2) {
+		switch (op) {
+			case EQ :
+				return patSubstr(s1, s2);
+			case APPROX :
+				return patSubstr(fixupString(s1), fixupString(s2));
+			default :
+				return compareSign(op, s2.compareTo(s1));
+		}
+	}
+
+	boolean compareSign(int op, int cmp) {
+		switch (op) {
+			case LE :
+				return cmp >= 0;
+			case GE :
+				return cmp <= 0;
+			case EQ :
+				return cmp == 0;
+			default : /* APPROX */
+				return cmp == 0;
+		}
+	}
+
+	String fixupString(String s) {
+		StringBuffer sb = new StringBuffer();
+		int len = s.length();
+		boolean isStart = true;
+		boolean isWhite = false;
+		for (int i = 0; i < len; i++) {
+			char c = s.charAt(i);
+			if (Character.isWhitespace(c)) {
+				isWhite = true;
+			}
+			else {
+				if (!isStart && isWhite)
+					sb.append(' ');
+				if (Character.isUpperCase(c))
+					c = Character.toLowerCase(c);
+				sb.append(c);
+				isStart = false;
+				isWhite = false;
+			}
+		}
+		return sb.toString();
+	}
+
+	boolean patSubstr(String s, String pat) {
+		if (s == null)
+			return false;
+		if (pat.length() == 0)
+			return s.length() == 0;
+		if (pat.charAt(0) == WILDCARD) {
+			pat = pat.substring(1);
+			for (;;) {
+				if (patSubstr(s, pat))
+					return true;
+				if (s.length() == 0)
+					return false;
+				s = s.substring(1);
+			}
+		}
+		else {
+			if (s.length() == 0 || s.charAt(0) != pat.charAt(0))
+				return false;
+			return patSubstr(s.substring(1), pat.substring(1));
+		}
+	}
+}

Modified: felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/Manifest.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/Manifest.java?rev=722850&r1=722849&r2=722850&view=diff
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/Manifest.java (original)
+++ felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/Manifest.java Wed Dec  3 04:03:12 2008
@@ -1,400 +1,402 @@
-/*
- * $Id: Manifest.java 44 2007-07-13 20:49:41Z hargrave@us.ibm.com $
- * 
- * Copyright (c) OSGi Alliance (2002, 2006, 2007). All Rights Reserved.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.osgi.impl.bundle.obr.resource;
-
-import java.io.*;
-import java.util.*;
-
-
-public class Manifest extends Hashtable {
-	static final long	serialVersionUID	= 1L;
-	List				imports;
-	List				exports;
-	ManifestEntry		name;
-	String				activator;
-	String				classpath[]	= new String[] {"."};
-	int					section;
-	String				location;
-	Native				_native[];
-	Vector				duplicates	= new Vector();
-	final static String	wordparts	= "~!@#$%^&*_:/?><.-+";
-	ManifestEntry		bsn;
-	VersionRange			version;
-	ManifestEntry		host;
-	List				require;
-
-	public Manifest(InputStream in) throws IOException {
-		parse(new InputStreamReader(in, "UTF8"));
-	}
-
-	public Manifest(Reader in) throws IOException {
-		parse(in);
-	}
-
-	public Object put(Object header, Object value) {
-		if (containsKey(header)) {
-			if (!((String) header).equalsIgnoreCase("comment"))
-				duplicates.add(header + ":" + value);
-		}
-		return super.put(header, value);
-	}
-
-	void parse(Reader in) throws IOException {
-		BufferedReader rdr = new BufferedReader(in);
-		String current = " ";
-		String buffer = rdr.readLine();
-		int section = 0;
-		if (buffer != null && !buffer.startsWith("Manifest-Version")) {
-			System.err
-					.println("The first line of a manifest file must be the Manifest-Version attribute");
-			throw new IOException(
-					"The first line of a manifest file must be the Manifest-Version attribute");
-		}
-		while (buffer != null && current != null && section == 0) {
-			if (current.startsWith(" ")) {
-				buffer += current.substring(1);
-			}
-			else {
-				section += entry(buffer);
-				buffer = current;
-			}
-			current = rdr.readLine();
-		}
-		entry(buffer);
-	}
-
-	int entry(String line) throws IOException {
-		if (line.length() < 2)
-			return 1;
-		int colon = line.indexOf(':');
-		if (colon < 1) {
-			error("Invalid header '" + line + "'");
-		}
-		else {
-			String header = line.substring(0, colon).toLowerCase();
-			String alphanum = "abcdefghijklmnopqrstuvwxyz0123456789";
-			String set = alphanum;
-			if (alphanum.indexOf(header.charAt(0)) < 0)
-				error("Header does not start with alphanum: " + header);
-			for (int i = 0; i < header.length(); i++) {
-				if (set.indexOf(header.charAt(i)) < 0)
-					error("Header contains non alphanum, - _: " + header);
-				set = "_-" + alphanum;
-			}
-			String value = "";
-			if (colon + 2 < line.length())
-				value = line.substring(colon + 2);
-			else
-				error("No value for manifest header " + header);
-			if (section == 0) {
-				if (header.equals("bundle-symbolicname")) {
-					bsn = (ManifestEntry) getEntries(value).get(0);
-				}
-				if (header.equals("bundle-version")) {
-					try {
-						version = new VersionRange(value.trim());
-					}
-					catch (Exception e) {
-						version = new VersionRange("0");
-						System.err.println("Invalid version attr for: " + bsn
-								+ " value is " + value);
-					}
-				}
-				if (header.equals("fragment-host"))
-					host = (ManifestEntry) getEntries(value).get(0);
-				if (header.equals("require-bundle"))
-					require = getEntries(value);
-				if (header.equals("import-package"))
-					imports = getEntries(value);
-				else if (header.equals("export-package"))
-					exports = getEntries(value);
-				else if (header.equals("bundle-activator"))
-					activator = value.trim();
-				else if (header.equals("bundle-updatelocation"))
-					location = value.trim();
-				else if (header.equals("bundle-classpath"))
-					classpath = getClasspath(value);
-				else if (header.equals("bundle-nativecode"))
-					_native = getNative(value);
-				put(header, value);
-			}
-		}
-		return 0;
-	}
-
-	void error(String msg) throws IOException {
-		System.err.println("Reading manifest: " + msg);
-	}
-
-	void warning(String msg) throws IOException {
-		System.err.println("Reading manifest: " + msg);
-	}
-
-	StreamTokenizer getStreamTokenizer(String line) {
-		StreamTokenizer st = new StreamTokenizer(new StringReader(line));
-		st.resetSyntax();
-		st.wordChars('a', 'z');
-		st.wordChars('A', 'Z');
-		st.wordChars('0', '9');
-		st.whitespaceChars(0, ' ');
-		st.quoteChar('"');
-		for (int i = 0; i < wordparts.length(); i++)
-			st.wordChars(wordparts.charAt(i), wordparts.charAt(i));
-		return st;
-	}
-
-	String word(StreamTokenizer st) throws IOException {
-		switch (st.nextToken()) {
-			case '"' :
-			case StreamTokenizer.TT_WORD :
-				String result = st.sval;
-				st.nextToken();
-				return result;
-		}
-		return null;
-	}
-
-	Parameter getParameter(StreamTokenizer st) throws IOException {
-
-		Parameter parameter = new Parameter();
-		parameter.key = word(st);
-		if (st.ttype == ':') {
-			st.nextToken();
-			parameter.type = Parameter.DIRECTIVE;
-		}
-		else {
-			parameter.type = Parameter.ATTRIBUTE;
-		}
-
-		if (st.ttype == '=') {
-			parameter.value = word(st);
-			while (st.ttype == StreamTokenizer.TT_WORD || st.ttype == '"') {
-				parameter.value += " " + st.sval;
-				st.nextToken();
-			}
-		}
-
-		return parameter;
-	}
-
-	public List getEntries(String line) throws IOException {
-		List v = new Vector();
-		Set aliases = new HashSet();
-
-		StreamTokenizer st = getStreamTokenizer(line);
-		do {
-			Parameter parameter = getParameter(st);
-			ManifestEntry p = new ManifestEntry(parameter.key);
-			while (st.ttype == ';') {
-				parameter = getParameter(st);
-				if (parameter.value == null) {
-					aliases.add(parameter.key);
-				}
-				else {
-					if (parameter.type == Parameter.ATTRIBUTE)
-						p.addParameter(parameter);
-					else
-						p.addParameter(parameter);
-				}
-			}
-			v.add(p);
-			for (Iterator a = aliases.iterator(); a.hasNext();) {
-				v.add(p.getAlias((String) a.next()));
-			}
-		} while (st.ttype == ',');
-		return v;
-	}
-
-	Native[] getNative(String line) throws IOException {
-		Vector v = new Vector();
-		StreamTokenizer st = getStreamTokenizer(line);
-		do {
-			Native spec = new Native();
-			Vector names = new Vector();
-			do {
-				Parameter parameter = getParameter(st);
-				if (parameter.value == null)
-					names.add(parameter.key);
-				else if (parameter.is("processor", Parameter.ATTRIBUTE))
-					spec.processor = parameter.value;
-				else if (parameter.is("osname", Parameter.ATTRIBUTE))
-					spec.osname = parameter.value;
-				else if (parameter.is("osversion", Parameter.ATTRIBUTE))
-					spec.osversion = parameter.value;
-				else if (parameter.is("language", Parameter.ATTRIBUTE))
-					spec.language = parameter.value;
-				else if (parameter.is("selection-filter", Parameter.DIRECTIVE))
-					spec.filter = parameter.value;
-				else
-					warning("Unknown parameter for native code : " + parameter);
-			} while (st.ttype == ';');
-			spec.paths = new String[names.size()];
-			names.copyInto(spec.paths);
-			v.add(spec);
-		} while (st.ttype == ',');
-		Native[] result = new Native[v.size()];
-		v.copyInto(result);
-		return result;
-	}
-
-	String[] getClasspath(String line) throws IOException {
-		StringTokenizer st = new StringTokenizer(line, " \t,");
-		String result[] = new String[st.countTokens()];
-		for (int i = 0; i < result.length; i++)
-			result[i] = st.nextToken();
-		return result;
-	}
-
-	public List getImports() {
-		return imports;
-	}
-
-	public List getExports() {
-		return exports;
-	}
-
-	public String getActivator() {
-		return activator;
-	}
-
-	public String getLocation() {
-		return location;
-	}
-
-	public String[] getClasspath() {
-		return classpath;
-	}
-
-	public Native[] getNative() {
-		return _native;
-	}
-
-	public Object get(Object key) {
-		if (key instanceof String)
-			return super.get(((String) key).toLowerCase());
-		else
-			return null;
-	}
-
-	public String getValue(String key) {
-		return (String) super.get(key.toLowerCase());
-	}
-
-	public String getValue(String key, String deflt) {
-		String s = getValue(key);
-		if (s == null)
-			return deflt;
-		else
-			return s;
-	}
-
-	public String[] getRequiredExecutionEnvironments() {
-		String ees = getValue("Bundle-RequiredExecutionEnvironment");
-		if (ees != null)
-			return ees.trim().split("\\s*,\\s*");
-		else
-			return null;
-	}
-
-	public VersionRange getVersion() {
-		if (version == null)
-			return new VersionRange("0");
-		return version;
-	}
-
-	public String getSymbolicName() {
-		ManifestEntry bsn = getBsn();
-
-		if (bsn == null) {
-			String name = getValue("Bundle-Name");
-			if (name == null)
-				name = "Untitled-" + hashCode();
-			return name;
-		}
-		else
-			return bsn.getName();
-	}
-
-	public String getManifestVersion() {
-		return getValue("Bundle-ManifestVersion", "1");
-	}
-
-	public String getCopyright() {
-		return getValue("Bundle-Copyright");
-	}
-
-	public String getDocumentation() {
-		return getValue("Bundle-DocURL");
-	}
-
-	public String[] getCategories() {
-		String cats = getValue("Bundle-Category");
-		if (cats == null)
-			return new String[0];
-		else
-			return cats.split("\\s*,\\s*");
-	}
-
-	public Native[] get_native() {
-		return _native;
-	}
-
-	public void set_native(Native[] _native) {
-		this._native = _native;
-	}
-
-	public ManifestEntry getBsn() {
-		return bsn;
-	}
-
-	public void setBsn(ManifestEntry bsn) {
-		this.bsn = bsn;
-	}
-
-	public Vector getDuplicates() {
-		return duplicates;
-	}
-
-	public void setDuplicates(Vector duplicates) {
-		this.duplicates = duplicates;
-	}
-
-	public ManifestEntry getHost() {
-		return host;
-	}
-
-	public void setHost(ManifestEntry host) {
-		this.host = host;
-	}
-
-	public List getRequire() {
-		return require;
-	}
-
-}
-
-class Native {
-	String	filter;
-	int		index	= -1;
-	String	paths[];
-	String	osname;
-	String	osversion;
-	String	language;
-	String	processor;
-
-}
+/*
+ * $Id: Manifest.java 84 2008-08-28 08:11:30Z peter.kriens@aqute.biz $
+ * 
+ * Copyright (c) OSGi Alliance (2002, 2006, 2007). All Rights Reserved.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.osgi.impl.bundle.obr.resource;
+
+import java.io.*;
+import java.util.*;
+
+
+public class Manifest extends Hashtable {
+	static final long	serialVersionUID	= 1L;
+	List				imports;
+	List				exports;
+	ManifestEntry		name;
+	String				activator;
+	String				classpath[]	= new String[] {"."};
+	int					section;
+	String				location;
+	Native				_native[];
+	Vector				duplicates	= new Vector();
+	final static String	wordparts	= "~!@#$%^&*_/?><.-+";
+	ManifestEntry		bsn;
+	VersionRange			version;
+	ManifestEntry		host;
+	List				require;
+
+	public Manifest(InputStream in) throws IOException {
+		parse(new InputStreamReader(in, "UTF8"));
+	}
+
+	public Manifest(Reader in) throws IOException {
+		parse(in);
+	}
+
+	public Object put(Object header, Object value) {
+		if (containsKey(header)) {
+			if (!((String) header).equalsIgnoreCase("comment"))
+				duplicates.add(header + ":" + value);
+		}
+		return super.put(header, value);
+	}
+
+	void parse(Reader in) throws IOException {
+		BufferedReader rdr = new BufferedReader(in);
+		String current = " ";
+		String buffer = rdr.readLine();
+		int section = 0;
+		if (buffer != null && !buffer.startsWith("Manifest-Version")) {
+			System.err
+					.println("The first line of a manifest file must be the Manifest-Version attribute");
+			throw new IOException(
+					"The first line of a manifest file must be the Manifest-Version attribute");
+		}
+		while (buffer != null && current != null && section == 0) {
+			if (current.startsWith(" ")) {
+				buffer += current.substring(1);
+			}
+			else {
+				section += entry(buffer);
+				buffer = current;
+			}
+			current = rdr.readLine();
+		}
+		entry(buffer);
+	}
+
+	int entry(String line) throws IOException {
+		if (line.length() < 2)
+			return 1;
+		int colon = line.indexOf(':');
+		if (colon < 1) {
+			error("Invalid header '" + line + "'");
+		}
+		else {
+			String header = line.substring(0, colon).toLowerCase();
+			String alphanum = "abcdefghijklmnopqrstuvwxyz0123456789";
+			String set = alphanum;
+			if (alphanum.indexOf(header.charAt(0)) < 0)
+				error("Header does not start with alphanum: " + header);
+			for (int i = 0; i < header.length(); i++) {
+				if (set.indexOf(header.charAt(i)) < 0)
+					error("Header contains non alphanum, - _: " + header);
+				set = "_-" + alphanum;
+			}
+			String value = "";
+			if (colon + 2 < line.length())
+				value = line.substring(colon + 2);
+			else
+				error("No value for manifest header " + header);
+			if (section == 0) {
+				if (header.equals("bundle-symbolicname")) {
+					bsn = (ManifestEntry) getEntries(value).get(0);
+				}
+				if (header.equals("bundle-version")) {
+					try {
+						version = new VersionRange(value.trim());
+					}
+					catch (Exception e) {
+						version = new VersionRange("0");
+						System.err.println("Invalid version attr for: " + bsn
+								+ " value is " + value);
+					}
+				}
+				if (header.equals("fragment-host"))
+					host = (ManifestEntry) getEntries(value).get(0);
+				if (header.equals("require-bundle"))
+					require = getEntries(value);
+				if (header.equals("import-package"))
+					imports = getEntries(value);
+				else if (header.equals("export-package"))
+					exports = getEntries(value);
+				else if (header.equals("bundle-activator"))
+					activator = value.trim();
+				else if (header.equals("bundle-updatelocation"))
+					location = value.trim();
+				else if (header.equals("bundle-classpath"))
+					classpath = getClasspath(value);
+				else if (header.equals("bundle-nativecode"))
+					_native = getNative(value);
+				put(header, value);
+			}
+		}
+		return 0;
+	}
+
+	void error(String msg) throws IOException {
+		System.err.println("Reading manifest: " + msg);
+	}
+
+	void warning(String msg) throws IOException {
+		System.err.println("Reading manifest: " + msg);
+	}
+
+	StreamTokenizer getStreamTokenizer(String line) {
+		StreamTokenizer st = new StreamTokenizer(new StringReader(line));
+		st.resetSyntax();
+		st.wordChars('a', 'z');
+		st.wordChars('A', 'Z');
+		st.wordChars('0', '9');
+		st.whitespaceChars(0, ' ');
+		st.quoteChar('"');
+		for (int i = 0; i < wordparts.length(); i++)
+			st.wordChars(wordparts.charAt(i), wordparts.charAt(i));
+		return st;
+	}
+
+	String word(StreamTokenizer st) throws IOException {
+		switch (st.nextToken()) {
+			case '"' :
+			case StreamTokenizer.TT_WORD :
+				String result = st.sval;
+				st.nextToken();
+				return result;
+		}
+		return null;
+	}
+
+	Parameter getParameter(StreamTokenizer st) throws IOException {
+
+		Parameter parameter = new Parameter();
+		parameter.key = word(st);
+		if (st.ttype == ':') {
+			st.nextToken();
+			parameter.type = Parameter.DIRECTIVE;
+		}
+		else {
+			parameter.type = Parameter.ATTRIBUTE;
+		}
+
+		if (st.ttype == '=') {
+			parameter.value = word(st);
+			while (st.ttype == StreamTokenizer.TT_WORD || st.ttype == '"') {
+				parameter.value += " " + st.sval;
+				st.nextToken();
+			}
+		}
+
+		return parameter;
+	}
+
+	public List getEntries(String line) throws IOException {
+		List v = new Vector();
+		Set aliases = new HashSet();
+
+		StreamTokenizer st = getStreamTokenizer(line);
+		do {
+			Parameter parameter = getParameter(st);
+			ManifestEntry p = new ManifestEntry(parameter.key);
+			while (st.ttype == ';') {
+				parameter = getParameter(st);
+				if (parameter.value == null) {
+					aliases.add(parameter.key);
+				}
+				else {
+					if (parameter.type == Parameter.ATTRIBUTE)
+						p.addParameter(parameter);
+					else if ( parameter.type == Parameter.DIRECTIVE )
+						p.addParameter(parameter);
+					else
+						p.addParameter(parameter);
+				}
+			}
+			v.add(p);
+			for (Iterator a = aliases.iterator(); a.hasNext();) {
+				v.add(p.getAlias((String) a.next()));
+			}
+		} while (st.ttype == ',');
+		return v;
+	}
+
+	Native[] getNative(String line) throws IOException {
+		Vector v = new Vector();
+		StreamTokenizer st = getStreamTokenizer(line);
+		do {
+			Native spec = new Native();
+			Vector names = new Vector();
+			do {
+				Parameter parameter = getParameter(st);
+				if (parameter.value == null)
+					names.add(parameter.key);
+				else if (parameter.is("processor", Parameter.ATTRIBUTE))
+					spec.processor = parameter.value;
+				else if (parameter.is("osname", Parameter.ATTRIBUTE))
+					spec.osname = parameter.value;
+				else if (parameter.is("osversion", Parameter.ATTRIBUTE))
+					spec.osversion = parameter.value;
+				else if (parameter.is("language", Parameter.ATTRIBUTE))
+					spec.language = parameter.value;
+				else if (parameter.is("selection-filter", Parameter.DIRECTIVE))
+					spec.filter = parameter.value;
+				else
+					warning("Unknown parameter for native code : " + parameter);
+			} while (st.ttype == ';');
+			spec.paths = new String[names.size()];
+			names.copyInto(spec.paths);
+			v.add(spec);
+		} while (st.ttype == ',');
+		Native[] result = new Native[v.size()];
+		v.copyInto(result);
+		return result;
+	}
+
+	String[] getClasspath(String line) throws IOException {
+		StringTokenizer st = new StringTokenizer(line, " \t,");
+		String result[] = new String[st.countTokens()];
+		for (int i = 0; i < result.length; i++)
+			result[i] = st.nextToken();
+		return result;
+	}
+
+	public List getImports() {
+		return imports;
+	}
+
+	public List getExports() {
+		return exports;
+	}
+
+	public String getActivator() {
+		return activator;
+	}
+
+	public String getLocation() {
+		return location;
+	}
+
+	public String[] getClasspath() {
+		return classpath;
+	}
+
+	public Native[] getNative() {
+		return _native;
+	}
+
+	public Object get(Object key) {
+		if (key instanceof String)
+			return super.get(((String) key).toLowerCase());
+		else
+			return null;
+	}
+
+	public String getValue(String key) {
+		return (String) super.get(key.toLowerCase());
+	}
+
+	public String getValue(String key, String deflt) {
+		String s = getValue(key);
+		if (s == null)
+			return deflt;
+		else
+			return s;
+	}
+
+	public String[] getRequiredExecutionEnvironments() {
+		String ees = getValue("Bundle-RequiredExecutionEnvironment");
+		if (ees != null)
+			return ees.trim().split("\\s*,\\s*");
+		else
+			return null;
+	}
+
+	public VersionRange getVersion() {
+		if (version == null)
+			return new VersionRange("0");
+		return version;
+	}
+
+	public String getSymbolicName() {
+		ManifestEntry bsn = getBsn();
+
+		if (bsn == null) {
+			String name = getValue("Bundle-Name");
+			if (name == null)
+				name = "Untitled-" + hashCode();
+			return name;
+		}
+		else
+			return bsn.getName();
+	}
+
+	public String getManifestVersion() {
+		return getValue("Bundle-ManifestVersion", "1");
+	}
+
+	public String getCopyright() {
+		return getValue("Bundle-Copyright");
+	}
+
+	public String getDocumentation() {
+		return getValue("Bundle-DocURL");
+	}
+
+	public String[] getCategories() {
+		String cats = getValue("Bundle-Category");
+		if (cats == null)
+			return new String[0];
+		else
+			return cats.split("\\s*,\\s*");
+	}
+
+	public Native[] get_native() {
+		return _native;
+	}
+
+	public void set_native(Native[] _native) {
+		this._native = _native;
+	}
+
+	public ManifestEntry getBsn() {
+		return bsn;
+	}
+
+	public void setBsn(ManifestEntry bsn) {
+		this.bsn = bsn;
+	}
+
+	public Vector getDuplicates() {
+		return duplicates;
+	}
+
+	public void setDuplicates(Vector duplicates) {
+		this.duplicates = duplicates;
+	}
+
+	public ManifestEntry getHost() {
+		return host;
+	}
+
+	public void setHost(ManifestEntry host) {
+		this.host = host;
+	}
+
+	public List getRequire() {
+		return require;
+	}
+
+}
+
+class Native {
+	String	filter;
+	int		index	= -1;
+	String	paths[];
+	String	osname;
+	String	osversion;
+	String	language;
+	String	processor;
+
+}