FELIX-760: commit latest bindex code

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@722850 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/BundleInfo.java b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/BundleInfo.java
index 2e68a9a..4374fd5 100644
--- a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/BundleInfo.java
+++ b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/BundleInfo.java
@@ -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
diff --git a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/CapabilityImpl.java b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/CapabilityImpl.java
index 45d2d1b..6d2ce8a 100644
--- a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/CapabilityImpl.java
+++ b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/CapabilityImpl.java
@@ -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;
+	}
+
+}
diff --git a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/FilterImpl.java b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/FilterImpl.java
index bc12314..b0feb87 100644
--- a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/FilterImpl.java
+++ b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/FilterImpl.java
@@ -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));
+		}
+	}
+}
diff --git a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/Manifest.java b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/Manifest.java
index 01c3f51..8d991e6 100644
--- a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/Manifest.java
+++ b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/Manifest.java
@@ -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;
+
+}
diff --git a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/ManifestEntry.java b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/ManifestEntry.java
index 2dc3e69..b4bbf79 100644
--- a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/ManifestEntry.java
+++ b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/ManifestEntry.java
@@ -1,111 +1,125 @@
-/*

- * $Id: ManifestEntry.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.*;

-

-

-public class ManifestEntry implements Comparable {

-	String		name;

-	VersionRange	version;

-	Map			attributes;

-	public Map	directives;

-	public Set	uses;

-

-	public ManifestEntry(String name) {

-		this.name = name;

-	}

-

-	public ManifestEntry(String name, VersionRange version) {

-		this.name = name;

-		this.version = version;

-	}

-

-	public String toString() {

-		if (version == null)

-			return name;

-		return name + " ;version=" + version;

-	}

-

-	public String getName() {

-		return name;

-	}

-

-	public VersionRange getVersion() {

-		if (version != null)

-			return version;

-		return new VersionRange("0");

-	}

-

-	/*

-	 * (non-Javadoc)

-	 * 

-	 * @see java.lang.Comparable#compareTo(java.lang.Object)

-	 */

-	public int compareTo(Object o) {

-		ManifestEntry p = (ManifestEntry) o;

-		return name.compareTo(p.name);

-	}

-

-	/**

-	 * @return

-	 */

-	public Object getPath() {

-		return getName().replace('.', '/');

-	}

-

-	public Map getDirectives() {

-		return directives;

-	}

-

-	public Map getAttributes() {

-		return attributes;

-	}

-

-	/**

-	 * @param parameter

-	 */

-	public void addParameter(Parameter parameter) {

-		switch (parameter.type) {

-			case Parameter.ATTRIBUTE :

-				if (attributes == null)

-					attributes = new HashMap();

-				attributes.put(parameter.key, parameter.value);

-				if (parameter.key.equalsIgnoreCase("version")

-						|| parameter.key

-								.equalsIgnoreCase("specification-version"))

-					this.version = new VersionRange(parameter.value);

-				break;

-

-			case Parameter.DIRECTIVE :

-				if (directives == null)

-					directives = new HashMap();

-				directives.put(parameter.key, parameter.value);

-				break;

-		}

-	}

-

-	public ManifestEntry getAlias(String key) {

-		ManifestEntry me = new ManifestEntry(key);

-		me.attributes = attributes;

-		me.directives = directives;

-		me.version = version;

-		return me;

-	}

-

-}

+/*
+ * $Id: ManifestEntry.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.util.*;
+
+
+public class ManifestEntry implements Comparable {
+	String		name;
+	VersionRange	version;
+	Map			attributes;
+	public Map	directives;
+	public Set	uses;
+
+	public ManifestEntry(String name) {
+		this.name = name;
+	}
+
+	public ManifestEntry(String name, VersionRange version) {
+		this.name = name;
+		this.version = version;
+	}
+
+	public String toString() {
+		if (version == null)
+			return name;
+		return name + " ;version=" + version;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public VersionRange getVersion() {
+		if (version != null)
+			return version;
+		return new VersionRange("0");
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.lang.Comparable#compareTo(java.lang.Object)
+	 */
+	public int compareTo(Object o) {
+		ManifestEntry p = (ManifestEntry) o;
+		return name.compareTo(p.name);
+	}
+
+	/**
+	 * @return
+	 */
+	public Object getPath() {
+		return getName().replace('.', '/');
+	}
+
+	public Map getDirectives() {
+		return directives;
+	}
+
+	public Map getAttributes() {
+		return attributes;
+	}
+
+	/**
+	 * @param parameter
+	 */
+	public void addParameter(Parameter parameter) {
+		switch (parameter.type) {
+			case Parameter.ATTRIBUTE :
+				if (attributes == null)
+					attributes = new HashMap();
+				attributes.put(parameter.key, parameter.value);
+				if (parameter.key.equalsIgnoreCase("version")
+						|| parameter.key
+								.equalsIgnoreCase("specification-version"))
+					this.version = new VersionRange(parameter.value);
+				break;
+
+			case Parameter.DIRECTIVE :
+				if (directives == null)
+					directives = new HashMap();
+				directives.put(parameter.key, parameter.value);
+				break;
+		}
+	}
+
+	public ManifestEntry getAlias(String key) {
+		ManifestEntry me = new ManifestEntry(key);
+		me.attributes = attributes;
+		me.directives = directives;
+		me.version = version;
+		return me;
+	}
+
+	public String getDirective(String directive) {
+		if ( directives == null )
+			return null;
+		
+		return (String) directives.get(directive);
+	}
+
+	public String getAttribute(String attribute) {
+		if ( attributes == null )
+			return null;
+		
+		return (String) attributes.get(attribute);
+	}
+
+}
diff --git a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/Parameter.java b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/Parameter.java
index 5038132..8601dc2 100644
--- a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/Parameter.java
+++ b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/Parameter.java
@@ -1,49 +1,49 @@
-/*

- * $Id: Parameter.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;

-

-class Parameter {

-	final static int	ATTRIBUTE	= 1;

-	final static int	DIRECTIVE	= 2;

-	final static int	SINGLE		= 0;

-

-	int					type;

-	String				key;

-	String				value;

-

-	public String toString() {

-		StringBuffer sb = new StringBuffer();

-		sb.append(key);

-		switch (type) {

-			case ATTRIBUTE :

-				sb.append("=");

-				break;

-			case DIRECTIVE :

-				sb.append(":=");

-				break;

-			case SINGLE :

-				return sb.toString();

-		}

-		sb.append(value);

-		return sb.toString();

-	}

-

-	boolean is(String s, int type) {

-		return this.type == type && key.equalsIgnoreCase(s);

-	}

-}

+/*
+ * $Id: Parameter.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;
+
+class Parameter {
+	final static int	ATTRIBUTE	= 1;
+	final static int	DIRECTIVE	= 2;
+	final static int	SINGLE		= 0;
+
+	int					type;
+	String				key;
+	String				value;
+
+	public String toString() {
+		StringBuffer sb = new StringBuffer();
+		sb.append(key);
+		switch (type) {
+			case ATTRIBUTE :
+				sb.append("=");
+				break;
+			case DIRECTIVE :
+				sb.append(":=");
+				break;
+			case SINGLE :
+				return sb.toString();
+		}
+		sb.append(value);
+		return sb.toString();
+	}
+
+	boolean is(String s, int type) {
+		return this.type == type && key.equalsIgnoreCase(s);
+	}
+}
diff --git a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/RepositoryImpl.java b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/RepositoryImpl.java
index bc6953b..b7ebeb4 100644
--- a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/RepositoryImpl.java
+++ b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/RepositoryImpl.java
@@ -1,375 +1,375 @@
-/*

- * $Id: RepositoryImpl.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.*;

-import java.util.*;

-import java.util.zip.*;

-

-import org.kxml2.io.KXmlParser;

-import org.osgi.service.obr.*;

-import org.xmlpull.v1.*;

-

-/**

- * Implements the basic repository. A repository holds a set of resources.

- * 

- * 

- * @version $Revision: 44 $

- */

-public class RepositoryImpl implements Repository {

-	transient Set			resources		= new HashSet();

-	URL						url;

-	String					date;

-	Set						visited			= new HashSet();

-	final static Resource[]	EMPTY_RESOURCE	= new Resource[0];

-	String					name			= "Untitled";

-	long					lastModified;

-	Exception				exception;

-	int						ranking=0;

-

-	/**

-	 * Each repository is identified by a single URL.

-	 * 

-	 * A repository can hold referrals to other repositories. These referred

-	 * repositories are included at the point of referall.

-	 * 

-	 * @param url

-	 */

-	public RepositoryImpl(URL url) {

-		this.url = url;

-	}

-

-	/**

-	 * Refresh the repository from the URL.

-	 * 

-	 * @throws Exception

-	 */

-	public boolean refresh() {

-		exception = null;

-		try {

-			resources.clear();

-			parseDocument(url);

-			visited = null;

-			return true;

-		}

-		catch (Exception e) {

-			e.printStackTrace();

-			exception = e;

-		}

-		return false;

-	}

-

-	/**

-	 * Parse the repository.

-	 * 

-	 * @param parser

-	 * @throws Exception

-	 */

-	private void parseRepository(XmlPullParser parser) throws Exception {

-		try {

-			parser.require(XmlPullParser.START_DOCUMENT, null, null);

-			parser.nextTag();

-			if (parser.getName().equals("bundles"))

-				parseOscar(parser);

-			else {

-				parser.require(XmlPullParser.START_TAG, null, "repository");

-				date = parser.getAttributeValue(null, "lastmodified");

-				name = parser.getAttributeValue(null, "name");

-				if (name == null)

-					name = "Untitled";

-

-				while (parser.nextTag() == XmlPullParser.START_TAG) {

-					if (parser.getName().equals("resource")) {

-						ResourceImpl resource = new ResourceImpl(this, parser);

-						resources.add(resource);

-					}

-					else if (parser.getName().equals("referral"))

-						referral(parser);

-					else

-						throw new IllegalArgumentException(

-								"Invalid tag in repository: " + url + " "

-										+ parser.getName());

-				}

-				parser.require(XmlPullParser.END_TAG, null, "repository");

-			}

-		}

-		catch (XmlPullParserException e) {

-			e.printStackTrace();

-			throw new IllegalArgumentException("XML unregognized around: "

-					+ e.getLineNumber() + " " + e.getMessage());

-		}

-	}

-

-	/**

-	 * Parse an old style OBR repository.

-	 * 

-	 * <dtd-version>1.0</dtd-version> <repository> <name>Oscar Bundle

-	 * Repository</name> <url>http://oscar-osgi.sourceforge.net/</url>

-	 * <date>Fri May 07 16:45:07 CEST 2004</date> <extern-repositories> <!--

-	 * Stefano Lenzi (kismet@interfree.it) -->

-	 * <url>http://domoware.isti.cnr.it/osgi-obr/niche-osgi-obr.xml</url>

-	 * <!--Manuel Palencia (santillan@dit.upm.es) --> <!--

-	 * <url>http://jmood.forge.os4os.org/repository.xml</url> --> <!-- Enrique

-	 * Rodriguez (erodriguez@apache.org) -->

-	 * <url>http://update.cainenable.org/repository.xml</url>

-	 * </extern-repositories> </repository> <bundle> <bundle-name>Bundle

-	 * Repository</bundle-name> <bundle-description> A bundle repository

-	 * service for Oscar. </bundle-description> <bundle-updatelocation>

-	 * http://oscar-osgi.sf.net/repo/bundlerepository/bundlerepository.jar

-	 * </bundle-updatelocation> <bundle-sourceurl>

-	 * http://oscar-osgi.sf.net/repo/bundlerepository/bundlerepository-src.jar

-	 * </bundle-sourceurl> <bundle-version>1.1.3</bundle-version>

-	 * <bundle-docurl> http://oscar-osgi.sf.net/repo/bundlerepository/

-	 * </bundle-docurl> <bundle-category>General</bundle-category>

-	 * <import-package package="org.osgi.framework"/> <export-package

-	 * package="org.ungoverned.osgi.service.bundlerepository"

-	 * specification-version="1.1.0"/> </bundle> *

-	 */

-	private void parseOscar(XmlPullParser parser) throws Exception {

-		parser.require(XmlPullParser.START_TAG, null, "bundles");

-		while (true) {

-			int event = parser.next();

-

-			// Error ..

-			if (event == XmlPullParser.TEXT)

-				event = parser.next();

-

-			if (event != XmlPullParser.START_TAG)

-				break;

-

-			ResourceImpl resource = new ResourceImpl(this);

-

-			if (parser.getName().equals("bundle")) {

-				while (parser.nextTag() == XmlPullParser.START_TAG) {

-					String key = parser.getName();

-					if (key.equals("import-package")) {

-						RequirementImpl requirement = new RequirementImpl(

-								"package");

-						

-						requirement.setOptional(false);

-						requirement.setMultiple(false);

-						

-						String p = parser.getAttributeValue(null, "package");

-						StringBuffer sb = new StringBuffer();

-						sb.append("(&(package=");

-						sb.append(p);

-						sb.append(")");

-						String version = parser.getAttributeValue(null,

-								"specification-version");

-						VersionRange v = new VersionRange("0");

-						if (version != null) {

-							sb.append("(version=");

-							sb.append(v= new VersionRange(version));

-							sb.append(")");

-						}

-						sb.append(")");

-						requirement.setFilter(sb.toString());

-						requirement.setComment("Import-Package: " + p + ";" + v );

-						resource.addRequirement(requirement);

-						

-						parser.nextTag();

-					}

-					else if (key.equals("export-package")) {

-						CapabilityImpl capability = new CapabilityImpl(

-								"package");

-						capability.addProperty("package", parser

-								.getAttributeValue(null, "package"));

-						String version = parser.getAttributeValue(null,

-								"specification-version");

-						if (version != null) {

-							capability.addProperty("version", new VersionRange(

-									version));

-						}

-						resource.addCapability(capability);

-						parser.nextTag();

-					}

-					else {

-						String value = parser.nextText().trim();

-						if (key.equals("bundle-sourceurl"))

-							resource.setSource(new URL(value));

-						else if (key.equals("bundle-docurl"))

-							resource.setDocumentation(new URL(value));

-						else if (key.equals("bundle-updatelocation"))

-							resource.setURL(new URL(value));

-						else if (key.equals("bundle-description"))

-							resource.setDescription(value);

-						else if (key.equals("bundle-category"))

-							resource.addCategory(value);

-						else if (key.equals("bundle-name")) {

-							resource.setName(value);

-							resource.setPresentationName(value);

-						}

-						else if (key.equals("bundle-version"))

-							resource.setVersion(new VersionRange(value));

-						else {

-							resource.put(key, value);

-						}

-					}

-				}

-				resources.add(resource);

-				parser.require(XmlPullParser.END_TAG, null, "bundle");

-			}

-			else if (parser.getName().equals("repository")) {

-				parser.require(XmlPullParser.START_TAG, null, "repository");

-				while (parser.nextTag() == XmlPullParser.START_TAG) {

-					String tag = parser.getName();

-					if (tag.equals("name")) {

-						String name = parser.nextText();

-						if (this.name == null)

-							this.name = name.trim();

-					}

-					else if (tag.equals("url"))

-						parser.nextText().trim();

-					else if (tag.equals("date"))

-						parser.nextText().trim();

-					else if (tag.equals("extern-repositories")) {

-						parser.require(XmlPullParser.START_TAG, null,

-								"extern-repositories");

-						while (parser.nextTag() == XmlPullParser.START_TAG) {

-							if (parser.getName().equals("url"))

-								parseDocument(new URL(parser.nextText().trim()));

-							else

-								throw new IllegalArgumentException(

-										"Invalid tag in repository while parsing extern repositories: "

-												+ url + " " + parser.getName());

-						}

-						parser.require(XmlPullParser.END_TAG, null,

-								"extern-repositories");

-					}

-					else

-						throw new IllegalArgumentException(

-								"Invalid tag in repository: " + url + " "

-										+ parser.getName());

-				}

-				parser.require(XmlPullParser.END_TAG, null, "repository");

-			}

-			else if (parser.getName().equals("dtd-version")) {

-				parser.nextText();

-			}

-			else

-				throw new IllegalArgumentException(

-						"Invalid tag in repository: " + url + " "

-								+ parser.getName());

-		}

-		parser.require(XmlPullParser.END_TAG, null, "bundles");

-	}

-

-	/**

-	 * We have a referral to another repository. Just create another parser and

-	 * read it inline.

-	 * 

-	 * @param parser

-	 */

-	void referral(XmlPullParser parser) {

-		// TODO handle depth!

-		try {

-			parser.require(XmlPullParser.START_TAG, null, "referral");

-			// String depth = parser.getAttributeValue(null, "depth");

-			String path = parser.getAttributeValue(null, "url");

-			URL url = new URL(this.url, path);

-			parseDocument(url);

-			parser.next();

-			parser.require(XmlPullParser.END_TAG, null, "referral");

-		}

-		catch (Exception e) {

-			e.printStackTrace();

-		}

-	}

-

-	/**

-	 * Parse a repository document.

-	 * 

-	 * @param url

-	 * @throws IOException

-	 * @throws XmlPullParserException

-	 * @throws Exception

-	 */

-	void parseDocument(URL url) throws IOException, XmlPullParserException,

-			Exception {

-		if (!visited.contains(url)) {

-			visited.add(url);

-			try {

-				System.out.println("Visiting: " + url);

-				InputStream in = null;

-				

-				if ( url.getPath().endsWith(".zip")) {

-					ZipInputStream zin = new ZipInputStream( url.openStream() );

-					ZipEntry entry = zin.getNextEntry();

-					while ( entry != null ) {

-						if ( entry.getName().equals("repository.xml")) {

-							in = zin;

-							break;

-						}

-						entry = zin.getNextEntry();

-					}

-				} else {

-					in = url.openStream();

-				}

-				Reader reader = new InputStreamReader(in);

-				XmlPullParser parser = new KXmlParser();

-				parser.setInput(reader);

-				parseRepository(parser);

-			} catch( MalformedURLException e ) {

-				System.out.println("Cannot create connection to url");

-			}

-		}

-	}

-

-	public URL getURL() {

-		return url;

-	}

-

-	/**

-	 * @return

-	 */

-	public Collection getResourceList() {

-		return resources;

-	}

-

-	public Resource[] getResources() {

-		return (Resource[]) getResourceList().toArray(EMPTY_RESOURCE);

-	}

-

-	public String getName() {

-		return name;

-	}

-

-	public Resource getResource(String id) {

-		for (Iterator i = getResourceList().iterator(); i.hasNext();) {

-			ResourceImpl resource = (ResourceImpl) i.next();

-			if (resource.getId().equals(id))

-				return resource;

-		}

-		return null;

-	}

-

-	public long getLastModified() {

-		return lastModified;

-	}

-

-	public int getRanking() {

-		return ranking;

-	}

-

-	public void setRanking(int ranking) {

-		this.ranking = ranking;

-	}

-

-}

+/*
+ * $Id: RepositoryImpl.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.*;
+import java.util.*;
+import java.util.zip.*;
+
+import org.kxml2.io.KXmlParser;
+import org.osgi.service.obr.*;
+import org.xmlpull.v1.*;
+
+/**
+ * Implements the basic repository. A repository holds a set of resources.
+ * 
+ * 
+ * @version $Revision: 44 $
+ */
+public class RepositoryImpl implements Repository {
+	transient Set			resources		= new HashSet();
+	URL						url;
+	String					date;
+	Set						visited			= new HashSet();
+	final static Resource[]	EMPTY_RESOURCE	= new Resource[0];
+	String					name			= "Untitled";
+	long					lastModified;
+	Exception				exception;
+	int						ranking=0;
+
+	/**
+	 * Each repository is identified by a single URL.
+	 * 
+	 * A repository can hold referrals to other repositories. These referred
+	 * repositories are included at the point of referall.
+	 * 
+	 * @param url
+	 */
+	public RepositoryImpl(URL url) {
+		this.url = url;
+	}
+
+	/**
+	 * Refresh the repository from the URL.
+	 * 
+	 * @throws Exception
+	 */
+	public boolean refresh() {
+		exception = null;
+		try {
+			resources.clear();
+			parseDocument(url);
+			visited = null;
+			return true;
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+			exception = e;
+		}
+		return false;
+	}
+
+	/**
+	 * Parse the repository.
+	 * 
+	 * @param parser
+	 * @throws Exception
+	 */
+	private void parseRepository(XmlPullParser parser) throws Exception {
+		try {
+			parser.require(XmlPullParser.START_DOCUMENT, null, null);
+			parser.nextTag();
+			if (parser.getName().equals("bundles"))
+				parseOscar(parser);
+			else {
+				parser.require(XmlPullParser.START_TAG, null, "repository");
+				date = parser.getAttributeValue(null, "lastmodified");
+				name = parser.getAttributeValue(null, "name");
+				if (name == null)
+					name = "Untitled";
+
+				while (parser.nextTag() == XmlPullParser.START_TAG) {
+					if (parser.getName().equals("resource")) {
+						ResourceImpl resource = new ResourceImpl(this, parser);
+						resources.add(resource);
+					}
+					else if (parser.getName().equals("referral"))
+						referral(parser);
+					else
+						throw new IllegalArgumentException(
+								"Invalid tag in repository: " + url + " "
+										+ parser.getName());
+				}
+				parser.require(XmlPullParser.END_TAG, null, "repository");
+			}
+		}
+		catch (XmlPullParserException e) {
+			e.printStackTrace();
+			throw new IllegalArgumentException("XML unregognized around: "
+					+ e.getLineNumber() + " " + e.getMessage());
+		}
+	}
+
+	/**
+	 * Parse an old style OBR repository.
+	 * 
+	 * <dtd-version>1.0</dtd-version> <repository> <name>Oscar Bundle
+	 * Repository</name> <url>http://oscar-osgi.sourceforge.net/</url>
+	 * <date>Fri May 07 16:45:07 CEST 2004</date> <extern-repositories> <!--
+	 * Stefano Lenzi (kismet@interfree.it) -->
+	 * <url>http://domoware.isti.cnr.it/osgi-obr/niche-osgi-obr.xml</url>
+	 * <!--Manuel Palencia (santillan@dit.upm.es) --> <!--
+	 * <url>http://jmood.forge.os4os.org/repository.xml</url> --> <!-- Enrique
+	 * Rodriguez (erodriguez@apache.org) -->
+	 * <url>http://update.cainenable.org/repository.xml</url>
+	 * </extern-repositories> </repository> <bundle> <bundle-name>Bundle
+	 * Repository</bundle-name> <bundle-description> A bundle repository
+	 * service for Oscar. </bundle-description> <bundle-updatelocation>
+	 * http://oscar-osgi.sf.net/repo/bundlerepository/bundlerepository.jar
+	 * </bundle-updatelocation> <bundle-sourceurl>
+	 * http://oscar-osgi.sf.net/repo/bundlerepository/bundlerepository-src.jar
+	 * </bundle-sourceurl> <bundle-version>1.1.3</bundle-version>
+	 * <bundle-docurl> http://oscar-osgi.sf.net/repo/bundlerepository/
+	 * </bundle-docurl> <bundle-category>General</bundle-category>
+	 * <import-package package="org.osgi.framework"/> <export-package
+	 * package="org.ungoverned.osgi.service.bundlerepository"
+	 * specification-version="1.1.0"/> </bundle> *
+	 */
+	private void parseOscar(XmlPullParser parser) throws Exception {
+		parser.require(XmlPullParser.START_TAG, null, "bundles");
+		while (true) {
+			int event = parser.next();
+
+			// Error ..
+			if (event == XmlPullParser.TEXT)
+				event = parser.next();
+
+			if (event != XmlPullParser.START_TAG)
+				break;
+
+			ResourceImpl resource = new ResourceImpl(this);
+
+			if (parser.getName().equals("bundle")) {
+				while (parser.nextTag() == XmlPullParser.START_TAG) {
+					String key = parser.getName();
+					if (key.equals("import-package")) {
+						RequirementImpl requirement = new RequirementImpl(
+								"package");
+						
+						requirement.setOptional(false);
+						requirement.setMultiple(false);
+						
+						String p = parser.getAttributeValue(null, "package");
+						StringBuffer sb = new StringBuffer();
+						sb.append("(&(package=");
+						sb.append(p);
+						sb.append(")");
+						String version = parser.getAttributeValue(null,
+								"specification-version");
+						VersionRange v = new VersionRange("0");
+						if (version != null) {
+							sb.append("(version=");
+							sb.append(v= new VersionRange(version));
+							sb.append(")");
+						}
+						sb.append(")");
+						requirement.setFilter(sb.toString());
+						requirement.setComment("Import-Package: " + p + ";" + v );
+						resource.addRequirement(requirement);
+						
+						parser.nextTag();
+					}
+					else if (key.equals("export-package")) {
+						CapabilityImpl capability = new CapabilityImpl(
+								"package");
+						capability.addProperty("package", parser
+								.getAttributeValue(null, "package"));
+						String version = parser.getAttributeValue(null,
+								"specification-version");
+						if (version != null) {
+							capability.addProperty("version", new VersionRange(
+									version));
+						}
+						resource.addCapability(capability);
+						parser.nextTag();
+					}
+					else {
+						String value = parser.nextText().trim();
+						if (key.equals("bundle-sourceurl"))
+							resource.setSource(new URL(value));
+						else if (key.equals("bundle-docurl"))
+							resource.setDocumentation(new URL(value));
+						else if (key.equals("bundle-updatelocation"))
+							resource.setURL(new URL(value));
+						else if (key.equals("bundle-description"))
+							resource.setDescription(value);
+						else if (key.equals("bundle-category"))
+							resource.addCategory(value);
+						else if (key.equals("bundle-name")) {
+							resource.setName(value);
+							resource.setPresentationName(value);
+						}
+						else if (key.equals("bundle-version"))
+							resource.setVersion(new VersionRange(value));
+						else {
+							resource.put(key, value);
+						}
+					}
+				}
+				resources.add(resource);
+				parser.require(XmlPullParser.END_TAG, null, "bundle");
+			}
+			else if (parser.getName().equals("repository")) {
+				parser.require(XmlPullParser.START_TAG, null, "repository");
+				while (parser.nextTag() == XmlPullParser.START_TAG) {
+					String tag = parser.getName();
+					if (tag.equals("name")) {
+						String name = parser.nextText();
+						if (this.name == null)
+							this.name = name.trim();
+					}
+					else if (tag.equals("url"))
+						parser.nextText().trim();
+					else if (tag.equals("date"))
+						parser.nextText().trim();
+					else if (tag.equals("extern-repositories")) {
+						parser.require(XmlPullParser.START_TAG, null,
+								"extern-repositories");
+						while (parser.nextTag() == XmlPullParser.START_TAG) {
+							if (parser.getName().equals("url"))
+								parseDocument(new URL(parser.nextText().trim()));
+							else
+								throw new IllegalArgumentException(
+										"Invalid tag in repository while parsing extern repositories: "
+												+ url + " " + parser.getName());
+						}
+						parser.require(XmlPullParser.END_TAG, null,
+								"extern-repositories");
+					}
+					else
+						throw new IllegalArgumentException(
+								"Invalid tag in repository: " + url + " "
+										+ parser.getName());
+				}
+				parser.require(XmlPullParser.END_TAG, null, "repository");
+			}
+			else if (parser.getName().equals("dtd-version")) {
+				parser.nextText();
+			}
+			else
+				throw new IllegalArgumentException(
+						"Invalid tag in repository: " + url + " "
+								+ parser.getName());
+		}
+		parser.require(XmlPullParser.END_TAG, null, "bundles");
+	}
+
+	/**
+	 * We have a referral to another repository. Just create another parser and
+	 * read it inline.
+	 * 
+	 * @param parser
+	 */
+	void referral(XmlPullParser parser) {
+		// TODO handle depth!
+		try {
+			parser.require(XmlPullParser.START_TAG, null, "referral");
+			// String depth = parser.getAttributeValue(null, "depth");
+			String path = parser.getAttributeValue(null, "url");
+			URL url = new URL(this.url, path);
+			parseDocument(url);
+			parser.next();
+			parser.require(XmlPullParser.END_TAG, null, "referral");
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	/**
+	 * Parse a repository document.
+	 * 
+	 * @param url
+	 * @throws IOException
+	 * @throws XmlPullParserException
+	 * @throws Exception
+	 */
+	void parseDocument(URL url) throws IOException, XmlPullParserException,
+			Exception {
+		if (!visited.contains(url)) {
+			visited.add(url);
+			try {
+				System.out.println("Visiting: " + url);
+				InputStream in = null;
+				
+				if ( url.getPath().endsWith(".zip")) {
+					ZipInputStream zin = new ZipInputStream( url.openStream() );
+					ZipEntry entry = zin.getNextEntry();
+					while ( entry != null ) {
+						if ( entry.getName().equals("repository.xml")) {
+							in = zin;
+							break;
+						}
+						entry = zin.getNextEntry();
+					}
+				} else {
+					in = url.openStream();
+				}
+				Reader reader = new InputStreamReader(in);
+				XmlPullParser parser = new KXmlParser();
+				parser.setInput(reader);
+				parseRepository(parser);
+			} catch( MalformedURLException e ) {
+				System.out.println("Cannot create connection to url");
+			}
+		}
+	}
+
+	public URL getURL() {
+		return url;
+	}
+
+	/**
+	 * @return
+	 */
+	public Collection getResourceList() {
+		return resources;
+	}
+
+	public Resource[] getResources() {
+		return (Resource[]) getResourceList().toArray(EMPTY_RESOURCE);
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public Resource getResource(String id) {
+		for (Iterator i = getResourceList().iterator(); i.hasNext();) {
+			ResourceImpl resource = (ResourceImpl) i.next();
+			if (resource.getId().equals(id))
+				return resource;
+		}
+		return null;
+	}
+
+	public long getLastModified() {
+		return lastModified;
+	}
+
+	public int getRanking() {
+		return ranking;
+	}
+
+	public void setRanking(int ranking) {
+		this.ranking = ranking;
+	}
+
+}
diff --git a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/RequirementImpl.java b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/RequirementImpl.java
index 146618a..c58f48f 100644
--- a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/RequirementImpl.java
+++ b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/RequirementImpl.java
@@ -1,177 +1,177 @@
-/*

- * $Id: RequirementImpl.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 org.osgi.service.obr.*;

-import org.xmlpull.v1.XmlPullParser;

-

-

-

-/**

- * Implements the Requirement interface.

- * 

- * 

- * @version $Revision: 44 $

- */

-public class RequirementImpl implements Requirement {

-	int		id;

-	String	name;

-	String	filter="()";

-	FilterImpl	_filter;

-	String	comment;

-	boolean optional;

-	boolean multiple;

-	boolean extend;

-	

-	/**

-	 * Create a requirement with the given name.

-	 * 

-	 * @param name

-	 */

-	public RequirementImpl(String name) {

-		this.name = name;

-	}

-

-

-	/**

-	 * Parse the requirement from the pull parser.

-	 * 

-	 * @param parser

-	 * @throws Exception

-	 */

-	public RequirementImpl(XmlPullParser parser) throws Exception {

-		parser.require(XmlPullParser.START_TAG, null, null );

-		name = parser.getAttributeValue(null, "name");

-		filter = parser.getAttributeValue(null, "filter");

-		

-		String opt = parser.getAttributeValue(null,"optional");

-		String mul = parser.getAttributeValue(null,"multiple");

-		String ext = parser.getAttributeValue(null,"extend");

-		optional = "true".equalsIgnoreCase(opt);

-		multiple = "true".equalsIgnoreCase(mul);

-		extend = "true".equalsIgnoreCase(ext);

-		

-		

-		StringBuffer sb = new StringBuffer();

-		while ( parser.next() == XmlPullParser.TEXT ) {

-			sb.append( parser.getText() );

-		}

-		if ( sb.length() > 0 )

-			setComment(sb.toString().trim());

-			

-		parser.require(XmlPullParser.END_TAG, null, null );

-	}

-

-	public void setFilter(String filter) {

-		this.filter = filter;

-		_filter= null;

-	}

-

-	public String getFilter() {

-		return filter;

-	}

-

-	public Tag toXML(String name) {

-		Tag tag = toXML(this);

-		tag.rename(name);

-		return tag;

-	}

-

-

-	public String getName() {

-		return name;

-	}

-

-	public boolean isSatisfied(Capability capability) {

-		if (_filter == null)

-			_filter = new FilterImpl(filter);

-

-		boolean result = _filter.match(capability.getProperties());

-		return result;

-	}

-

-	public String toString() {

-		return name + " " + filter;

-	}

-

-

-	public String getComment() {

-		return comment;

-	}

-

-

-	public void setComment(String comment) {

-		this.comment=comment;

-	}

-

-

-	public static Tag toXML(Requirement requirement) {

-		Tag req = new Tag("require");

-		req.addAttribute("name", requirement.getName());

-		req.addAttribute("filter", requirement.getFilter());

-		

-		req.addAttribute("optional", requirement.isOptional()+"");

-		req.addAttribute("multiple", requirement.isMultiple()+"");

-		req.addAttribute("extend", requirement.isExtend()+"");

-		

-		if ( requirement.getComment() != null )

-			req.addContent(requirement.getComment());

-		

-		return req;

-	}

-

-

-	public boolean isMultiple() {

-		return multiple;

-	}

-

-

-	public boolean isOptional() {

-		return optional;

-	}

-

-

-	public void setOptional(boolean b) {

-		optional = b;

-	}

-

-	public void setMultiple(boolean b) {

-		multiple = b;

-	}

-

-

-	public boolean equals(Object o) {

-		if ( ! (o instanceof Requirement) )

-			return false;

-		

-		Requirement r2 = (Requirement)o;

-		return filter.equals(r2.getFilter()) && name.equals(r2.getName()); 

-	}

-	

-	public int hashCode() {

-		return filter.hashCode() ^ name.hashCode();

-	}

-	

-	public boolean isExtend() {

-		return extend;

-	}

-	

-	public void setExtend(boolean extend) {

-		this.extend = extend;

-	}

-}

+/*
+ * $Id: RequirementImpl.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 org.osgi.service.obr.*;
+import org.xmlpull.v1.XmlPullParser;
+
+
+
+/**
+ * Implements the Requirement interface.
+ * 
+ * 
+ * @version $Revision: 44 $
+ */
+public class RequirementImpl implements Requirement {
+	int		id;
+	String	name;
+	String	filter="()";
+	FilterImpl	_filter;
+	String	comment;
+	boolean optional;
+	boolean multiple;
+	boolean extend;
+	
+	/**
+	 * Create a requirement with the given name.
+	 * 
+	 * @param name
+	 */
+	public RequirementImpl(String name) {
+		this.name = name;
+	}
+
+
+	/**
+	 * Parse the requirement from the pull parser.
+	 * 
+	 * @param parser
+	 * @throws Exception
+	 */
+	public RequirementImpl(XmlPullParser parser) throws Exception {
+		parser.require(XmlPullParser.START_TAG, null, null );
+		name = parser.getAttributeValue(null, "name");
+		filter = parser.getAttributeValue(null, "filter");
+		
+		String opt = parser.getAttributeValue(null,"optional");
+		String mul = parser.getAttributeValue(null,"multiple");
+		String ext = parser.getAttributeValue(null,"extend");
+		optional = "true".equalsIgnoreCase(opt);
+		multiple = "true".equalsIgnoreCase(mul);
+		extend = "true".equalsIgnoreCase(ext);
+		
+		
+		StringBuffer sb = new StringBuffer();
+		while ( parser.next() == XmlPullParser.TEXT ) {
+			sb.append( parser.getText() );
+		}
+		if ( sb.length() > 0 )
+			setComment(sb.toString().trim());
+			
+		parser.require(XmlPullParser.END_TAG, null, null );
+	}
+
+	public void setFilter(String filter) {
+		this.filter = filter;
+		_filter= null;
+	}
+
+	public String getFilter() {
+		return filter;
+	}
+
+	public Tag toXML(String name) {
+		Tag tag = toXML(this);
+		tag.rename(name);
+		return tag;
+	}
+
+
+	public String getName() {
+		return name;
+	}
+
+	public boolean isSatisfied(Capability capability) {
+		if (_filter == null)
+			_filter = new FilterImpl(filter);
+
+		boolean result = _filter.match(capability.getProperties());
+		return result;
+	}
+
+	public String toString() {
+		return name + " " + filter;
+	}
+
+
+	public String getComment() {
+		return comment;
+	}
+
+
+	public void setComment(String comment) {
+		this.comment=comment;
+	}
+
+
+	public static Tag toXML(Requirement requirement) {
+		Tag req = new Tag("require");
+		req.addAttribute("name", requirement.getName());
+		req.addAttribute("filter", requirement.getFilter());
+		
+		req.addAttribute("optional", requirement.isOptional()+"");
+		req.addAttribute("multiple", requirement.isMultiple()+"");
+		req.addAttribute("extend", requirement.isExtend()+"");
+		
+		if ( requirement.getComment() != null )
+			req.addContent(requirement.getComment());
+		
+		return req;
+	}
+
+
+	public boolean isMultiple() {
+		return multiple;
+	}
+
+
+	public boolean isOptional() {
+		return optional;
+	}
+
+
+	public void setOptional(boolean b) {
+		optional = b;
+	}
+
+	public void setMultiple(boolean b) {
+		multiple = b;
+	}
+
+
+	public boolean equals(Object o) {
+		if ( ! (o instanceof Requirement) )
+			return false;
+		
+		Requirement r2 = (Requirement)o;
+		return filter.equals(r2.getFilter()) && name.equals(r2.getName()); 
+	}
+	
+	public int hashCode() {
+		return filter.hashCode() ^ name.hashCode();
+	}
+	
+	public boolean isExtend() {
+		return extend;
+	}
+	
+	public void setExtend(boolean extend) {
+		this.extend = extend;
+	}
+}
diff --git a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/ResourceImpl.java b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/ResourceImpl.java
index 55cd298..7363bf6 100644
--- a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/ResourceImpl.java
+++ b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/ResourceImpl.java
@@ -1,369 +1,369 @@
-/*

- * $Id: ResourceImpl.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.File;

-import java.net.URL;

-import java.util.*;

-

-import org.osgi.framework.Version;

-import org.osgi.service.obr.*;

-import org.xmlpull.v1.XmlPullParser;

-

-public class ResourceImpl implements Resource {

-	List			capabilities	= new ArrayList();

-	List			requirements	= new ArrayList();

-	URL				url;

-	String			symbolicName;

-	VersionRange		version;

-	List			categories		= new ArrayList();

-	long			size			= -1;

-	String			id;

-	static int		ID				= 1;

-	Map				map				= new HashMap();

-	RepositoryImpl	repository;

-	String			presentationName;

-	File			file;

-

-

-	public ResourceImpl(RepositoryImpl repository, String name,

-			VersionRange version) {

-		this.version = version;

-		if ( version == null)

-			this.version = new VersionRange("0");

-		this.symbolicName = name;

-		this.repository = repository;

-	}

-

-	public ResourceImpl(RepositoryImpl repository, XmlPullParser parser)

-			throws Exception {

-		this.repository = repository;

-		parser.require(XmlPullParser.START_TAG, null, "resource");

-		symbolicName = parser.getAttributeValue(null, "symbolicname");

-		if (symbolicName == null)

-			System.err.println("Hey, no symb name! "

-					+ parser.getAttributeValue(null, "uri"));

-

-		map.put(SYMBOLIC_NAME, symbolicName);

-		presentationName = parser.getAttributeValue(null, PRESENTATION_NAME);

-		if (presentationName != null)

-			map.put(PRESENTATION_NAME, presentationName);

-		String v = parser.getAttributeValue(null, "version");

-		if (v == null)

-			setVersion(new VersionRange("0"));

-		else

-			setVersion(new VersionRange(v));

-

-		setURL(toURL(parser.getAttributeValue(null, "uri")));

-

-		while (parser.nextTag() == XmlPullParser.START_TAG) {

-			if (parser.getName().equals("category")) {

-				categories.add(parser.getAttributeValue(null, "id").trim());

-			}

-			else if (parser.getName().equals("require"))

-				addRequirement(new RequirementImpl(parser));

-			else if (parser.getName().equals("capability"))

-				addCapability(new CapabilityImpl(parser));

-			else {

-				String text = parser.nextText();

-				if (text != null)

-					map.put(parser.getName(), text.trim());

-			}

-			parser.next();

-		}

-		parser.require(XmlPullParser.END_TAG, null, "resource");

-	}

-

-	public ResourceImpl(RepositoryImpl impl) {

-		this.repository = impl;

-	}

-

-	private URL toURL(String attributeValue) throws Exception {

-		if (attributeValue == null)

-			return null;

-

-		return new URL(repository.getURL(), attributeValue);

-	}

-

-	public void addCategory(String category) {

-		categories.add(category);

-	}

-

-	public void addCapability(CapabilityImpl capability) {

-		if (capability != null)

-			capabilities.add(capability);

-	}

-

-	public void addRequirement(RequirementImpl requirement) {

-		if (requirement != null)

-			requirements.add(requirement);

-	}

-

-	public void setLicense(URL license) {

-		if (license != null)

-			map.put(LICENSE_URL, license);

-	}

-

-	public String getDescription() {

-		return (String) map.get(DESCRIPTION);

-	}

-

-	public void setDescription(String description) {

-		if (description != null)

-			map.put(DESCRIPTION, description);

-	}

-

-	public Capability[] getCapabilities() {

-		return (Capability[]) capabilities.toArray(new Capability[capabilities

-				.size()]);

-	}

-

-	public URL getLicense() {

-		return (URL) map.get(LICENSE_URL);

-	}

-

-	public String getSymbolicName() {

-		return symbolicName;

-	}

-

-	public Requirement[] getRequirements() {

-		return (Requirement[]) requirements

-				.toArray(new Requirement[requirements.size()]);

-	}

-

-	public Tag toXML() {

-		return toXML(this );

-	}

-

-	public static Tag toXML(Resource resource) {

-		return toXML(resource,true);

-	}

-

-	public static Tag toXML(Resource resource, boolean relative ) {

-		Tag meta = new Tag("resource");

-		URL url = resource.getURL();

-		String urlString = url.toExternalForm();

-		

-		if ( relative )

-			urlString = makeRelative(resource.getRepository().getURL(), url);

-		

-		meta.addAttribute("uri", urlString );

-		meta.addAttribute(SYMBOLIC_NAME, resource.getSymbolicName());

-		if (resource.getPresentationName() != null)

-			meta

-					.addAttribute(PRESENTATION_NAME, resource

-							.getPresentationName());

-		meta.addAttribute(VERSION, resource.getVersion().toString());

-		meta.addAttribute("id", resource.getId());

-		Map map = new TreeMap(resource.getProperties());

-		for (int i = 0; i < Resource.KEYS.length; i++) {

-			String key = KEYS[i];

-			if (!(key.equals(URL) || key.equals(SYMBOLIC_NAME) || key

-					.equals(VERSION) || key.equals(PRESENTATION_NAME))) {

-				Object value = map.get(KEYS[i]);

-				if (value != null) {

-					if (value instanceof URL)

-						value = makeRelative(resource.getRepository().getURL(),(URL) value);

-					meta.addContent(new Tag(key, value.toString()));

-				}

-			}

-		}

-

-		String[] categories = resource.getCategories();

-		for (int i = 0; i < categories.length; i++) {

-			String category = categories[i];

-			meta.addContent(new Tag("category", new String[] {"id",

-					category.toLowerCase()}));

-		}

-

-		Capability[] capabilities = resource.getCapabilities();

-		for (int i = 0; i < capabilities.length; i++) {

-			meta.addContent(CapabilityImpl.toXML(capabilities[i]));

-		}

-

-		Requirement[] requirements = resource.getRequirements();

-		for (int i = 0; i < requirements.length; i++) {

-			meta.addContent(RequirementImpl.toXML(requirements[i]));

-		}

-		return meta;

-	}

-

-	public URL getURL() {

-		return url;

-	}

-

-	static String makeRelative(URL repository, URL url) {

-		try {

-			if (repository != null) {

-				String a = url.toExternalForm();

-				String b = repository.toExternalForm();

-				int index = b.lastIndexOf('/');

-				if ( index > 0 )

-					b = b.substring(0,index+1);

-				if (a.startsWith(b))

-					return a.substring(b.length());

-			}

-		}

-		catch (Exception e) {

-			// Ignore

-		}

-		return url.toExternalForm();

-	}

-

-	public void setURL(URL url) {

-		this.url = url;

-		if (url != null)

-			map.put(URL, url);

-	}

-

-	public String getCopyright() {

-		return (String) map.get(COPYRIGHT);

-	}

-

-	public Version getVersion() {

-		if (version == null)

-			version = new VersionRange("0");

-		return version.low;

-	}

-

-	void setVersion(VersionRange version) {

-		if (version == null)

-			this.version = new VersionRange("0");

-		else

-			this.version = version;

-	}

-

-	public void setCopyright(String copyright) {

-		if (copyright != null)

-			map.put(COPYRIGHT, copyright);

-	}

-

-	public URL getDocumentation() {

-		return (URL) map.get(DOCUMENTATION_URL);

-	}

-

-	public void setDocumentation(URL documentation) {

-		if (documentation != null)

-			map.put(DOCUMENTATION_URL, documentation);

-	}

-

-	public URL getSource() {

-		return (URL) map.get(SOURCE_URL);

-	}

-

-	public void setSource(URL source) {

-		if (source != null)

-			map.put(SOURCE_URL, source);

-	}

-

-	public boolean satisfies(RequirementImpl requirement) {

-		for (Iterator i = capabilities.iterator(); i.hasNext();) {

-			CapabilityImpl capability = (CapabilityImpl) i.next();

-			if (requirement.isSatisfied(capability))

-				return true;

-		}

-		return false;

-	}

-

-	public String toString() {

-		return symbolicName + "-" + version;

-	}

-

-	public long getSize() {

-		return size;

-	}

-

-	public void setSize(long size) {

-		this.size = size;

-		map.put(SIZE, new Long(size));

-	}

-

-	public Collection getRequirementList() {

-		return requirements;

-	}

-

-	public Collection getCapabilityList() {

-		return capabilities;

-	}

-

-	public int hashCode() {

-		return symbolicName.hashCode() ^ version.hashCode();

-	}

-

-	public boolean equals(Object o) {

-		try {

-			ResourceImpl other = (ResourceImpl) o;

-			return symbolicName.equals(other.symbolicName)

-					&& version.equals(other.version);

-		}

-		catch (ClassCastException e) {

-			return false;

-		}

-	}

-

-	public String[] getCategories() {

-		return (String[]) categories.toArray(new String[categories.size()]);

-	}

-

-	public Map getProperties() {

-		return Collections.unmodifiableMap(map);

-	}

-

-	public synchronized String getId() {

-		if ( id == null )

-			id = symbolicName + "/" + version;

-		return id;

-	}

-

-	public Repository getRepository() {

-		return repository;

-	}

-

-	void setName(String value) {

-		this.symbolicName = value;

-	}

-

-	void put(String name, Object value) {

-		map.put(name, value);

-	}

-

-	public void setPresentationName(String name) {

-		presentationName = name;

-		if (name != null)

-			map.put(PRESENTATION_NAME, name);

-	}

-

-	public String getPresentationName() {

-		return presentationName;

-	}

-

-	public void setFile(File zipFile) {

-		file = zipFile;

-	}

-

-	public Set getExtendList() {

-		Set set = new HashSet();

-		for (Iterator i = requirements.iterator(); i.hasNext();) {

-			RequirementImpl	impl = (RequirementImpl) i.next();

-			if ( impl.isExtend())

-				set.add(impl);

-		}

-		return set;

-	}

-

-}

+/*
+ * $Id: ResourceImpl.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.File;
+import java.net.URL;
+import java.util.*;
+
+import org.osgi.framework.Version;
+import org.osgi.service.obr.*;
+import org.xmlpull.v1.XmlPullParser;
+
+public class ResourceImpl implements Resource {
+	List			capabilities	= new ArrayList();
+	List			requirements	= new ArrayList();
+	URL				url;
+	String			symbolicName;
+	VersionRange		version;
+	List			categories		= new ArrayList();
+	long			size			= -1;
+	String			id;
+	static int		ID				= 1;
+	Map				map				= new HashMap();
+	RepositoryImpl	repository;
+	String			presentationName;
+	File			file;
+
+
+	public ResourceImpl(RepositoryImpl repository, String name,
+			VersionRange version) {
+		this.version = version;
+		if ( version == null)
+			this.version = new VersionRange("0");
+		this.symbolicName = name;
+		this.repository = repository;
+	}
+
+	public ResourceImpl(RepositoryImpl repository, XmlPullParser parser)
+			throws Exception {
+		this.repository = repository;
+		parser.require(XmlPullParser.START_TAG, null, "resource");
+		symbolicName = parser.getAttributeValue(null, "symbolicname");
+		if (symbolicName == null)
+			System.err.println("Hey, no symb name! "
+					+ parser.getAttributeValue(null, "uri"));
+
+		map.put(SYMBOLIC_NAME, symbolicName);
+		presentationName = parser.getAttributeValue(null, PRESENTATION_NAME);
+		if (presentationName != null)
+			map.put(PRESENTATION_NAME, presentationName);
+		String v = parser.getAttributeValue(null, "version");
+		if (v == null)
+			setVersion(new VersionRange("0"));
+		else
+			setVersion(new VersionRange(v));
+
+		setURL(toURL(parser.getAttributeValue(null, "uri")));
+
+		while (parser.nextTag() == XmlPullParser.START_TAG) {
+			if (parser.getName().equals("category")) {
+				categories.add(parser.getAttributeValue(null, "id").trim());
+			}
+			else if (parser.getName().equals("require"))
+				addRequirement(new RequirementImpl(parser));
+			else if (parser.getName().equals("capability"))
+				addCapability(new CapabilityImpl(parser));
+			else {
+				String text = parser.nextText();
+				if (text != null)
+					map.put(parser.getName(), text.trim());
+			}
+			parser.next();
+		}
+		parser.require(XmlPullParser.END_TAG, null, "resource");
+	}
+
+	public ResourceImpl(RepositoryImpl impl) {
+		this.repository = impl;
+	}
+
+	private URL toURL(String attributeValue) throws Exception {
+		if (attributeValue == null)
+			return null;
+
+		return new URL(repository.getURL(), attributeValue);
+	}
+
+	public void addCategory(String category) {
+		categories.add(category);
+	}
+
+	public void addCapability(CapabilityImpl capability) {
+		if (capability != null)
+			capabilities.add(capability);
+	}
+
+	public void addRequirement(RequirementImpl requirement) {
+		if (requirement != null)
+			requirements.add(requirement);
+	}
+
+	public void setLicense(URL license) {
+		if (license != null)
+			map.put(LICENSE_URL, license);
+	}
+
+	public String getDescription() {
+		return (String) map.get(DESCRIPTION);
+	}
+
+	public void setDescription(String description) {
+		if (description != null)
+			map.put(DESCRIPTION, description);
+	}
+
+	public Capability[] getCapabilities() {
+		return (Capability[]) capabilities.toArray(new Capability[capabilities
+				.size()]);
+	}
+
+	public URL getLicense() {
+		return (URL) map.get(LICENSE_URL);
+	}
+
+	public String getSymbolicName() {
+		return symbolicName;
+	}
+
+	public Requirement[] getRequirements() {
+		return (Requirement[]) requirements
+				.toArray(new Requirement[requirements.size()]);
+	}
+
+	public Tag toXML() {
+		return toXML(this );
+	}
+
+	public static Tag toXML(Resource resource) {
+		return toXML(resource,true);
+	}
+
+	public static Tag toXML(Resource resource, boolean relative ) {
+		Tag meta = new Tag("resource");
+		URL url = resource.getURL();
+		String urlString = url.toExternalForm();
+		
+		if ( relative )
+			urlString = makeRelative(resource.getRepository().getURL(), url);
+		
+		meta.addAttribute("uri", urlString );
+		meta.addAttribute(SYMBOLIC_NAME, resource.getSymbolicName());
+		if (resource.getPresentationName() != null)
+			meta
+					.addAttribute(PRESENTATION_NAME, resource
+							.getPresentationName());
+		meta.addAttribute(VERSION, resource.getVersion().toString());
+		meta.addAttribute("id", resource.getId());
+		Map map = new TreeMap(resource.getProperties());
+		for (int i = 0; i < Resource.KEYS.length; i++) {
+			String key = KEYS[i];
+			if (!(key.equals(URL) || key.equals(SYMBOLIC_NAME) || key
+					.equals(VERSION) || key.equals(PRESENTATION_NAME))) {
+				Object value = map.get(KEYS[i]);
+				if (value != null) {
+					if (value instanceof URL)
+						value = makeRelative(resource.getRepository().getURL(),(URL) value);
+					meta.addContent(new Tag(key, value.toString()));
+				}
+			}
+		}
+
+		String[] categories = resource.getCategories();
+		for (int i = 0; i < categories.length; i++) {
+			String category = categories[i];
+			meta.addContent(new Tag("category", new String[] {"id",
+					category.toLowerCase()}));
+		}
+
+		Capability[] capabilities = resource.getCapabilities();
+		for (int i = 0; i < capabilities.length; i++) {
+			meta.addContent(CapabilityImpl.toXML(capabilities[i]));
+		}
+
+		Requirement[] requirements = resource.getRequirements();
+		for (int i = 0; i < requirements.length; i++) {
+			meta.addContent(RequirementImpl.toXML(requirements[i]));
+		}
+		return meta;
+	}
+
+	public URL getURL() {
+		return url;
+	}
+
+	static String makeRelative(URL repository, URL url) {
+		try {
+			if (repository != null) {
+				String a = url.toExternalForm();
+				String b = repository.toExternalForm();
+				int index = b.lastIndexOf('/');
+				if ( index > 0 )
+					b = b.substring(0,index+1);
+				if (a.startsWith(b))
+					return a.substring(b.length());
+			}
+		}
+		catch (Exception e) {
+			// Ignore
+		}
+		return url.toExternalForm();
+	}
+
+	public void setURL(URL url) {
+		this.url = url;
+		if (url != null)
+			map.put(URL, url);
+	}
+
+	public String getCopyright() {
+		return (String) map.get(COPYRIGHT);
+	}
+
+	public Version getVersion() {
+		if (version == null)
+			version = new VersionRange("0");
+		return version.low;
+	}
+
+	void setVersion(VersionRange version) {
+		if (version == null)
+			this.version = new VersionRange("0");
+		else
+			this.version = version;
+	}
+
+	public void setCopyright(String copyright) {
+		if (copyright != null)
+			map.put(COPYRIGHT, copyright);
+	}
+
+	public URL getDocumentation() {
+		return (URL) map.get(DOCUMENTATION_URL);
+	}
+
+	public void setDocumentation(URL documentation) {
+		if (documentation != null)
+			map.put(DOCUMENTATION_URL, documentation);
+	}
+
+	public URL getSource() {
+		return (URL) map.get(SOURCE_URL);
+	}
+
+	public void setSource(URL source) {
+		if (source != null)
+			map.put(SOURCE_URL, source);
+	}
+
+	public boolean satisfies(RequirementImpl requirement) {
+		for (Iterator i = capabilities.iterator(); i.hasNext();) {
+			CapabilityImpl capability = (CapabilityImpl) i.next();
+			if (requirement.isSatisfied(capability))
+				return true;
+		}
+		return false;
+	}
+
+	public String toString() {
+		return symbolicName + "-" + version;
+	}
+
+	public long getSize() {
+		return size;
+	}
+
+	public void setSize(long size) {
+		this.size = size;
+		map.put(SIZE, new Long(size));
+	}
+
+	public Collection getRequirementList() {
+		return requirements;
+	}
+
+	public Collection getCapabilityList() {
+		return capabilities;
+	}
+
+	public int hashCode() {
+		return symbolicName.hashCode() ^ version.hashCode();
+	}
+
+	public boolean equals(Object o) {
+		try {
+			ResourceImpl other = (ResourceImpl) o;
+			return symbolicName.equals(other.symbolicName)
+					&& version.equals(other.version);
+		}
+		catch (ClassCastException e) {
+			return false;
+		}
+	}
+
+	public String[] getCategories() {
+		return (String[]) categories.toArray(new String[categories.size()]);
+	}
+
+	public Map getProperties() {
+		return Collections.unmodifiableMap(map);
+	}
+
+	public synchronized String getId() {
+		if ( id == null )
+			id = symbolicName + "/" + version;
+		return id;
+	}
+
+	public Repository getRepository() {
+		return repository;
+	}
+
+	void setName(String value) {
+		this.symbolicName = value;
+	}
+
+	void put(String name, Object value) {
+		map.put(name, value);
+	}
+
+	public void setPresentationName(String name) {
+		presentationName = name;
+		if (name != null)
+			map.put(PRESENTATION_NAME, name);
+	}
+
+	public String getPresentationName() {
+		return presentationName;
+	}
+
+	public void setFile(File zipFile) {
+		file = zipFile;
+	}
+
+	public Set getExtendList() {
+		Set set = new HashSet();
+		for (Iterator i = requirements.iterator(); i.hasNext();) {
+			RequirementImpl	impl = (RequirementImpl) i.next();
+			if ( impl.isExtend())
+				set.add(impl);
+		}
+		return set;
+	}
+
+}
diff --git a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/StringSet.java b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/StringSet.java
index d2bbd5d..36d2a27 100644
--- a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/StringSet.java
+++ b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/StringSet.java
@@ -1,32 +1,32 @@
-/*

- * $Id: StringSet.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.*;

-

-public class StringSet extends HashSet {

-	static final long	serialVersionUID	= 1L;

-

-	public StringSet(String set) {

-		StringTokenizer st = new StringTokenizer(set, ",");

-		while (st.hasMoreTokens())

-			add(st.nextToken().trim());

-	}

-}

+/*
+ * $Id: StringSet.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.*;
+
+public class StringSet extends HashSet {
+	static final long	serialVersionUID	= 1L;
+
+	public StringSet(String set) {
+		StringTokenizer st = new StringTokenizer(set, ",");
+		while (st.hasMoreTokens())
+			add(st.nextToken().trim());
+	}
+}
diff --git a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/Tag.java b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/Tag.java
index 3c1375f..973c989 100644
--- a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/Tag.java
+++ b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/Tag.java
@@ -1,488 +1,488 @@
-/*

- * $Id: Tag.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.text.SimpleDateFormat;

-import java.util.*;

-

-/**

- * The Tag class represents a minimal XML tree. It consist of a named element

- * with a hashtable of named attributes. Methods are provided to walk the tree

- * and get its constituents. The content of a Tag is a list that contains String

- * objects or other Tag objects.

- */

-public class Tag {

-	Tag						parent;

-	String					name;

-	Map						attributes	= new TreeMap();

-	Vector					content		= new Vector();

-

-	static SimpleDateFormat	format		= new SimpleDateFormat(

-												"yyyyMMddhhmmss.SSS");

-

-	/**

-	 * Construct a new Tag with a name.

-	 */

-	public Tag(String name) {

-		this.name = name;

-	}

-

-	/**

-	 * Construct a new Tag with a name.

-	 */

-	public Tag(String name, Map attributes) {

-		this.name = name;

-		this.attributes = attributes;

-	}

-

-	/**

-	 * Construct a new Tag with a name and a set of attributes. The attributes

-	 * are given as ( name, value ) ...

-	 */

-	public Tag(String name, String[] attributes) {

-		this.name = name;

-		for (int i = 0; i < attributes.length; i += 2)

-			addAttribute(attributes[i], attributes[i + 1]);

-	}

-

-	/**

-	 * Construct a new Tag with a single string as content.

-	 */

-	public Tag(String name, String content) {

-		this.name = name;

-		addContent(content);

-	}

-

-	/**

-	 * Add a new attribute.

-	 */

-	public void addAttribute(String key, String value) {

-		attributes.put(key, value);

-	}

-

-	/**

-	 * Add a new attribute.

-	 */

-	public void addAttribute(String key, Object value) {

-		if (value == null)

-			return;

-		attributes.put(key, value.toString());

-	}

-

-	/**

-	 * Add a new attribute.

-	 */

-	public void addAttribute(String key, int value) {

-		attributes.put(key, Integer.toString(value));

-	}

-

-	/**

-	 * Add a new date attribute. The date is formatted as the SimpleDateFormat

-	 * describes at the top of this class.

-	 */

-	public void addAttribute(String key, Date value) {

-		attributes.put(key, format.format(value));

-	}

-

-	/**

-	 * Add a new content string.

-	 */

-	public void addContent(String string) {

-		content.addElement(string);

-	}

-

-	/**

-	 * Add a new content tag.

-	 */

-	public void addContent(Tag tag) {

-		content.addElement(tag);

-		tag.parent = this;

-	}

-

-	/**

-	 * Return the name of the tag.

-	 */

-	public String getName() {

-		return name;

-	}

-

-	/**

-	 * Return the attribute value.

-	 */

-	public String getAttribute(String key) {

-		return (String) attributes.get(key);

-	}

-

-	/**

-	 * Return the attribute value or a default if not defined.

-	 */

-	public String getAttribute(String key, String deflt) {

-		String answer = getAttribute(key);

-		return answer == null ? deflt : answer;

-	}

-

-	/**

-	 * Answer the attributes as a Dictionary object.

-	 */

-	public Map getAttributes() {

-		return attributes;

-	}

-

-	/**

-	 * Return the contents.

-	 */

-	public Vector getContents() {

-		return content;

-	}

-

-	/**

-	 * Return a string representation of this Tag and all its children

-	 * recursively.

-	 */

-	public String toString() {

-		StringWriter sw = new StringWriter();

-		print(0, new PrintWriter(sw));

-		return sw.toString();

-	}

-

-	/**

-	 * Return only the tags of the first level of descendants that match the

-	 * name.

-	 */

-	public Vector getContents(String tag) {

-		Vector out = new Vector();

-		for (Enumeration e = content.elements(); e.hasMoreElements();) {

-			Object o = e.nextElement();

-			if (o instanceof Tag && ((Tag) o).getName().equals(tag))

-				out.addElement(o);

-		}

-		return out;

-	}

-

-	/**

-	 * Return the whole contents as a String (no tag info and attributes).

-	 */

-	public String getContentsAsString() {

-		StringBuffer sb = new StringBuffer();

-		getContentsAsString(sb);

-		return sb.toString();

-	}

-

-	/**

-	 * convenient method to get the contents in a StringBuffer.

-	 */

-	public void getContentsAsString(StringBuffer sb) {

-		for (Enumeration e = content.elements(); e.hasMoreElements();) {

-			Object o = e.nextElement();

-			if (o instanceof Tag)

-				((Tag) o).getContentsAsString(sb);

-			else

-				sb.append(o.toString());

-		}

-	}

-

-	/**

-	 * Print the tag formatted to a PrintWriter.

-	 */

-	public void print(int indent, PrintWriter pw) {

-		pw.print("\n");

-		spaces(pw, indent);

-		pw.print('<');

-		pw.print(name);

-

-		for (Iterator e = attributes.keySet().iterator(); e.hasNext();) {

-			String key = (String) e.next();

-			String value = escape((String) attributes.get(key));

-			pw.print(' ');

-			pw.print(key);

-			pw.print("=");

-			String quote = "'";

-			if (value.indexOf(quote) >= 0)

-				quote = "\"";

-			pw.print(quote);

-			pw.print(value);

-			pw.print(quote);

-		}

-

-		if (content.size() == 0)

-			pw.print('/');

-		else {

-			pw.print('>');

-			for (Enumeration e = content.elements(); e.hasMoreElements();) {

-				Object content = e.nextElement();

-				if (content instanceof String) {

-					formatted(pw, indent + 2, 60, escape((String) content));

-				}

-				else if (content instanceof Tag) {

-					Tag tag = (Tag) content;

-					tag.print(indent + 2, pw);

-				}

-			}

-			pw.print("\n");

-			spaces(pw, indent);

-			pw.print("</");

-			pw.print(name);

-		}

-		pw.print('>');

-	}

-

-	/**

-	 * Convenience method to print a string nicely and does character conversion

-	 * to entities.

-	 */

-	void formatted(PrintWriter pw, int left, int width, String s) {

-		int pos = width + 1;

-		s = s.trim();

-

-		for (int i = 0; i < s.length(); i++) {

-			char c = s.charAt(i);

-			if (i == 0 || (Character.isWhitespace(c) && pos > width - 3)) {

-				pw.print("\n");

-				spaces(pw, left);

-				pos = 0;

-			}

-			switch (c) {

-				case '<' :

-					pw.print("&lt;");

-					pos += 4;

-					break;

-				case '>' :

-					pw.print("&gt;");

-					pos += 4;

-					break;

-				case '&' :

-					pw.print("&amp;");

-					pos += 5;

-					break;

-				default :

-					pw.print(c);

-					pos++;

-					break;

-			}

-

-		}

-	}

-

-	/**

-	 * Escape a string, do entity conversion.

-	 */

-	String escape(String s) {

-		if  ( s == null )

-			return "?null?";

-		

-		StringBuffer sb = new StringBuffer();

-		for (int i = 0; i < s.length(); i++) {

-			char c = s.charAt(i);

-			switch (c) {

-				case '<' :

-					sb.append("&lt;");

-					break;

-				case '>' :

-					sb.append("&gt;");

-					break;

-				case '&' :

-					sb.append("&amp;");

-					break;

-				default :

-					sb.append(c);

-					break;

-			}

-		}

-		return sb.toString();

-	}

-

-	/**

-	 * Make spaces.

-	 */

-	void spaces(PrintWriter pw, int n) {

-		while (n-- > 0)

-			pw.print(' ');

-	}

-

-	/**

-	 * root/preferences/native/os

-	 */

-	public Tag[] select(String path) {

-		return select(path, (Tag) null);

-	}

-

-	public Tag[] select(String path, Tag mapping) {

-		Vector v = new Vector();

-		select(path, v, mapping);

-		Tag[] result = new Tag[v.size()];

-		v.copyInto(result);

-		return result;

-	}

-

-	void select(String path, Vector results, Tag mapping) {

-		if (path.startsWith("//")) {

-			int i = path.indexOf('/', 2);

-			String name = path.substring(2, i < 0 ? path.length() : i);

-

-			for (Enumeration e = content.elements(); e.hasMoreElements();) {

-				Object o = e.nextElement();

-				if (o instanceof Tag) {

-					Tag child = (Tag) o;

-					if (match(name, child, mapping))

-						results.add(child);

-					child.select(path, results, mapping);

-				}

-

-			}

-			return;

-		}

-

-		if (path.length() == 0) {

-			results.addElement(this);

-			return;

-		}

-

-		int i = path.indexOf("/");

-		String elementName = path;

-		String remainder = "";

-		if (i > 0) {

-			elementName = path.substring(0, i);

-			remainder = path.substring(i + 1);

-		}

-

-		for (Enumeration e = content.elements(); e.hasMoreElements();) {

-			Object o = e.nextElement();

-			if (o instanceof Tag) {

-				Tag child = (Tag) o;

-				if (child.getName().equals(elementName)

-						|| elementName.equals("*"))

-					child.select(remainder, results, mapping);

-			}

-		}

-	}

-

-	public boolean match(String search, Tag child, Tag mapping) {

-		String target = child.getName();

-		String sn = null;

-		String tn = null;

-

-		if (search.equals("*"))

-			return true;

-

-		int s = search.indexOf(':');

-		if (s > 0) {

-			sn = search.substring(0, s);

-			search = search.substring(s + 1);

-		}

-		int t = target.indexOf(':');

-		if (t > 0) {

-			tn = target.substring(0, t);

-			target = target.substring(t + 1);

-		}

-

-		if (!search.equals(target)) // different tag names

-			return false;

-

-		if (mapping == null) {

-			return tn == sn || (sn != null && sn.equals(tn));

-		}

-		else {

-			String suri = sn == null ? mapping.getAttribute("xmlns") : mapping

-					.getAttribute("xmlns:" + sn);

-			String turi = tn == null ? child.findRecursiveAttribute("xmlns")

-					: child.findRecursiveAttribute("xmlns:" + tn);

-			return turi == suri

-					|| (turi != null && suri != null && turi.equals(suri));

-		}

-	}

-

-	public String getString(String path) {

-		String attribute = null;

-		int index = path.indexOf("@");

-		if (index >= 0) {

-			// attribute

-			attribute = path.substring(index + 1);

-

-			if (index > 0) {

-				// prefix path

-				path = path.substring(index - 1); // skip -1

-			}

-			else

-				path = "";

-		}

-		Tag tags[] = select(path);

-		StringBuffer sb = new StringBuffer();

-		for (int i = 0; i < tags.length; i++) {

-			if (attribute == null)

-				tags[i].getContentsAsString(sb);

-			else

-				sb.append(tags[i].getAttribute(attribute));

-		}

-		return sb.toString();

-	}

-

-	public String getStringContent() {

-		StringBuffer sb = new StringBuffer();

-		for (Enumeration e = content.elements(); e.hasMoreElements();) {

-			Object c = e.nextElement();

-			if (!(c instanceof Tag))

-				sb.append(c);

-		}

-		return sb.toString();

-	}

-

-	public String getNameSpace() {

-		return getNameSpace(name);

-	}

-

-	public String getNameSpace(String name) {

-		int index = name.indexOf(':');

-		if (index > 0) {

-			String ns = name.substring(0, index);

-			return findRecursiveAttribute("xmlns:" + ns);

-		}

-		else

-			return findRecursiveAttribute("xmlns");

-	}

-

-	public String findRecursiveAttribute(String name) {

-		String value = getAttribute(name);

-		if (value != null)

-			return value;

-		if (parent != null)

-			return parent.findRecursiveAttribute(name);

-		return null;

-	}

-

-	public String getLocalName() {

-		int index = name.indexOf(':');

-		if (index <= 0)

-			return name;

-

-		return name.substring(index + 1);

-	}

-

-	public void rename(String string) {

-		name = string;

-	}

-

-

-	public static void convert( Collection c, String type, Tag parent ) {

-		for ( Iterator i=c.iterator(); i.hasNext(); ) {

-			Map	map = (Map) i.next();

-			parent.addContent( new Tag(type, map) );

-		}

-	}

-

-}

+/*
+ * $Id: Tag.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.text.SimpleDateFormat;
+import java.util.*;
+
+/**
+ * The Tag class represents a minimal XML tree. It consist of a named element
+ * with a hashtable of named attributes. Methods are provided to walk the tree
+ * and get its constituents. The content of a Tag is a list that contains String
+ * objects or other Tag objects.
+ */
+public class Tag {
+	Tag						parent;
+	String					name;
+	Map						attributes	= new TreeMap();
+	Vector					content		= new Vector();
+
+	static SimpleDateFormat	format		= new SimpleDateFormat(
+												"yyyyMMddhhmmss.SSS");
+
+	/**
+	 * Construct a new Tag with a name.
+	 */
+	public Tag(String name) {
+		this.name = name;
+	}
+
+	/**
+	 * Construct a new Tag with a name.
+	 */
+	public Tag(String name, Map attributes) {
+		this.name = name;
+		this.attributes = attributes;
+	}
+
+	/**
+	 * Construct a new Tag with a name and a set of attributes. The attributes
+	 * are given as ( name, value ) ...
+	 */
+	public Tag(String name, String[] attributes) {
+		this.name = name;
+		for (int i = 0; i < attributes.length; i += 2)
+			addAttribute(attributes[i], attributes[i + 1]);
+	}
+
+	/**
+	 * Construct a new Tag with a single string as content.
+	 */
+	public Tag(String name, String content) {
+		this.name = name;
+		addContent(content);
+	}
+
+	/**
+	 * Add a new attribute.
+	 */
+	public void addAttribute(String key, String value) {
+		attributes.put(key, value);
+	}
+
+	/**
+	 * Add a new attribute.
+	 */
+	public void addAttribute(String key, Object value) {
+		if (value == null)
+			return;
+		attributes.put(key, value.toString());
+	}
+
+	/**
+	 * Add a new attribute.
+	 */
+	public void addAttribute(String key, int value) {
+		attributes.put(key, Integer.toString(value));
+	}
+
+	/**
+	 * Add a new date attribute. The date is formatted as the SimpleDateFormat
+	 * describes at the top of this class.
+	 */
+	public void addAttribute(String key, Date value) {
+		attributes.put(key, format.format(value));
+	}
+
+	/**
+	 * Add a new content string.
+	 */
+	public void addContent(String string) {
+		content.addElement(string);
+	}
+
+	/**
+	 * Add a new content tag.
+	 */
+	public void addContent(Tag tag) {
+		content.addElement(tag);
+		tag.parent = this;
+	}
+
+	/**
+	 * Return the name of the tag.
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * Return the attribute value.
+	 */
+	public String getAttribute(String key) {
+		return (String) attributes.get(key);
+	}
+
+	/**
+	 * Return the attribute value or a default if not defined.
+	 */
+	public String getAttribute(String key, String deflt) {
+		String answer = getAttribute(key);
+		return answer == null ? deflt : answer;
+	}
+
+	/**
+	 * Answer the attributes as a Dictionary object.
+	 */
+	public Map getAttributes() {
+		return attributes;
+	}
+
+	/**
+	 * Return the contents.
+	 */
+	public Vector getContents() {
+		return content;
+	}
+
+	/**
+	 * Return a string representation of this Tag and all its children
+	 * recursively.
+	 */
+	public String toString() {
+		StringWriter sw = new StringWriter();
+		print(0, new PrintWriter(sw));
+		return sw.toString();
+	}
+
+	/**
+	 * Return only the tags of the first level of descendants that match the
+	 * name.
+	 */
+	public Vector getContents(String tag) {
+		Vector out = new Vector();
+		for (Enumeration e = content.elements(); e.hasMoreElements();) {
+			Object o = e.nextElement();
+			if (o instanceof Tag && ((Tag) o).getName().equals(tag))
+				out.addElement(o);
+		}
+		return out;
+	}
+
+	/**
+	 * Return the whole contents as a String (no tag info and attributes).
+	 */
+	public String getContentsAsString() {
+		StringBuffer sb = new StringBuffer();
+		getContentsAsString(sb);
+		return sb.toString();
+	}
+
+	/**
+	 * convenient method to get the contents in a StringBuffer.
+	 */
+	public void getContentsAsString(StringBuffer sb) {
+		for (Enumeration e = content.elements(); e.hasMoreElements();) {
+			Object o = e.nextElement();
+			if (o instanceof Tag)
+				((Tag) o).getContentsAsString(sb);
+			else
+				sb.append(o.toString());
+		}
+	}
+
+	/**
+	 * Print the tag formatted to a PrintWriter.
+	 */
+	public void print(int indent, PrintWriter pw) {
+		pw.print("\n");
+		spaces(pw, indent);
+		pw.print('<');
+		pw.print(name);
+
+		for (Iterator e = attributes.keySet().iterator(); e.hasNext();) {
+			String key = (String) e.next();
+			String value = escape((String) attributes.get(key));
+			pw.print(' ');
+			pw.print(key);
+			pw.print("=");
+			String quote = "'";
+			if (value.indexOf(quote) >= 0)
+				quote = "\"";
+			pw.print(quote);
+			pw.print(value);
+			pw.print(quote);
+		}
+
+		if (content.size() == 0)
+			pw.print('/');
+		else {
+			pw.print('>');
+			for (Enumeration e = content.elements(); e.hasMoreElements();) {
+				Object content = e.nextElement();
+				if (content instanceof String) {
+					formatted(pw, indent + 2, 60, escape((String) content));
+				}
+				else if (content instanceof Tag) {
+					Tag tag = (Tag) content;
+					tag.print(indent + 2, pw);
+				}
+			}
+			pw.print("\n");
+			spaces(pw, indent);
+			pw.print("</");
+			pw.print(name);
+		}
+		pw.print('>');
+	}
+
+	/**
+	 * Convenience method to print a string nicely and does character conversion
+	 * to entities.
+	 */
+	void formatted(PrintWriter pw, int left, int width, String s) {
+		int pos = width + 1;
+		s = s.trim();
+
+		for (int i = 0; i < s.length(); i++) {
+			char c = s.charAt(i);
+			if (i == 0 || (Character.isWhitespace(c) && pos > width - 3)) {
+				pw.print("\n");
+				spaces(pw, left);
+				pos = 0;
+			}
+			switch (c) {
+				case '<' :
+					pw.print("&lt;");
+					pos += 4;
+					break;
+				case '>' :
+					pw.print("&gt;");
+					pos += 4;
+					break;
+				case '&' :
+					pw.print("&amp;");
+					pos += 5;
+					break;
+				default :
+					pw.print(c);
+					pos++;
+					break;
+			}
+
+		}
+	}
+
+	/**
+	 * Escape a string, do entity conversion.
+	 */
+	String escape(String s) {
+		if  ( s == null )
+			return "?null?";
+		
+		StringBuffer sb = new StringBuffer();
+		for (int i = 0; i < s.length(); i++) {
+			char c = s.charAt(i);
+			switch (c) {
+				case '<' :
+					sb.append("&lt;");
+					break;
+				case '>' :
+					sb.append("&gt;");
+					break;
+				case '&' :
+					sb.append("&amp;");
+					break;
+				default :
+					sb.append(c);
+					break;
+			}
+		}
+		return sb.toString();
+	}
+
+	/**
+	 * Make spaces.
+	 */
+	void spaces(PrintWriter pw, int n) {
+		while (n-- > 0)
+			pw.print(' ');
+	}
+
+	/**
+	 * root/preferences/native/os
+	 */
+	public Tag[] select(String path) {
+		return select(path, (Tag) null);
+	}
+
+	public Tag[] select(String path, Tag mapping) {
+		Vector v = new Vector();
+		select(path, v, mapping);
+		Tag[] result = new Tag[v.size()];
+		v.copyInto(result);
+		return result;
+	}
+
+	void select(String path, Vector results, Tag mapping) {
+		if (path.startsWith("//")) {
+			int i = path.indexOf('/', 2);
+			String name = path.substring(2, i < 0 ? path.length() : i);
+
+			for (Enumeration e = content.elements(); e.hasMoreElements();) {
+				Object o = e.nextElement();
+				if (o instanceof Tag) {
+					Tag child = (Tag) o;
+					if (match(name, child, mapping))
+						results.add(child);
+					child.select(path, results, mapping);
+				}
+
+			}
+			return;
+		}
+
+		if (path.length() == 0) {
+			results.addElement(this);
+			return;
+		}
+
+		int i = path.indexOf("/");
+		String elementName = path;
+		String remainder = "";
+		if (i > 0) {
+			elementName = path.substring(0, i);
+			remainder = path.substring(i + 1);
+		}
+
+		for (Enumeration e = content.elements(); e.hasMoreElements();) {
+			Object o = e.nextElement();
+			if (o instanceof Tag) {
+				Tag child = (Tag) o;
+				if (child.getName().equals(elementName)
+						|| elementName.equals("*"))
+					child.select(remainder, results, mapping);
+			}
+		}
+	}
+
+	public boolean match(String search, Tag child, Tag mapping) {
+		String target = child.getName();
+		String sn = null;
+		String tn = null;
+
+		if (search.equals("*"))
+			return true;
+
+		int s = search.indexOf(':');
+		if (s > 0) {
+			sn = search.substring(0, s);
+			search = search.substring(s + 1);
+		}
+		int t = target.indexOf(':');
+		if (t > 0) {
+			tn = target.substring(0, t);
+			target = target.substring(t + 1);
+		}
+
+		if (!search.equals(target)) // different tag names
+			return false;
+
+		if (mapping == null) {
+			return tn == sn || (sn != null && sn.equals(tn));
+		}
+		else {
+			String suri = sn == null ? mapping.getAttribute("xmlns") : mapping
+					.getAttribute("xmlns:" + sn);
+			String turi = tn == null ? child.findRecursiveAttribute("xmlns")
+					: child.findRecursiveAttribute("xmlns:" + tn);
+			return turi == suri
+					|| (turi != null && suri != null && turi.equals(suri));
+		}
+	}
+
+	public String getString(String path) {
+		String attribute = null;
+		int index = path.indexOf("@");
+		if (index >= 0) {
+			// attribute
+			attribute = path.substring(index + 1);
+
+			if (index > 0) {
+				// prefix path
+				path = path.substring(index - 1); // skip -1
+			}
+			else
+				path = "";
+		}
+		Tag tags[] = select(path);
+		StringBuffer sb = new StringBuffer();
+		for (int i = 0; i < tags.length; i++) {
+			if (attribute == null)
+				tags[i].getContentsAsString(sb);
+			else
+				sb.append(tags[i].getAttribute(attribute));
+		}
+		return sb.toString();
+	}
+
+	public String getStringContent() {
+		StringBuffer sb = new StringBuffer();
+		for (Enumeration e = content.elements(); e.hasMoreElements();) {
+			Object c = e.nextElement();
+			if (!(c instanceof Tag))
+				sb.append(c);
+		}
+		return sb.toString();
+	}
+
+	public String getNameSpace() {
+		return getNameSpace(name);
+	}
+
+	public String getNameSpace(String name) {
+		int index = name.indexOf(':');
+		if (index > 0) {
+			String ns = name.substring(0, index);
+			return findRecursiveAttribute("xmlns:" + ns);
+		}
+		else
+			return findRecursiveAttribute("xmlns");
+	}
+
+	public String findRecursiveAttribute(String name) {
+		String value = getAttribute(name);
+		if (value != null)
+			return value;
+		if (parent != null)
+			return parent.findRecursiveAttribute(name);
+		return null;
+	}
+
+	public String getLocalName() {
+		int index = name.indexOf(':');
+		if (index <= 0)
+			return name;
+
+		return name.substring(index + 1);
+	}
+
+	public void rename(String string) {
+		name = string;
+	}
+
+
+	public static void convert( Collection c, String type, Tag parent ) {
+		for ( Iterator i=c.iterator(); i.hasNext(); ) {
+			Map	map = (Map) i.next();
+			parent.addContent( new Tag(type, map) );
+		}
+	}
+
+}
diff --git a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/VersionRange.java b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/VersionRange.java
index 39e666e..5770c17 100644
--- a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/VersionRange.java
+++ b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/VersionRange.java
@@ -1,119 +1,119 @@
-/*

- * $Id: VersionRange.java 46 2008-01-17 19:05:21Z 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.util.regex.*;

-

-import org.osgi.framework.*;

-

-public class VersionRange implements Comparable {

-	Version high;

-	Version low;

-	char start = '[';

-	char end = ']';

-

-	static String V = "[0-9]+(\\.[0-9]+(\\.[0-9]+(\\.[a-zA-Z0-9_-]+)?)?)?";

-	static Pattern RANGE = Pattern.compile("(\\(|\\[)\\s*(" + V + ")\\s*,\\s*(" + V

-			+ ")\\s*(\\)|\\])");

-

-	public VersionRange(String string) {

-		string = string.trim();

-		Matcher m = RANGE.matcher(string);

-		if (m.matches()) {

-			start = m.group(1).charAt(0);

-			low = new Version(m.group(2));

-			high = new Version(m.group(6));

-			end = m.group(10).charAt(0);

-			if (low.compareTo(high) > 0)

-				throw new IllegalArgumentException(

-						"Low Range is higher than High Range: " + low + "-"

-								+ high);

-

-		} else

-			high = low = new Version(string);

-	}

-

-	public boolean isRange() {

-		return high != low;

-	}

-

-	public boolean includeLow() {

-		return start == '[';

-	}

-

-	public boolean includeHigh() {

-		return end == ']';

-	}

-

-	public String toString() {

-		if (high == low)

-			return high.toString();

-

-		StringBuffer sb = new StringBuffer();

-		sb.append(start);

-		sb.append(low);

-		sb.append(',');

-		sb.append(high);

-		sb.append(end);

-		return sb.toString();

-	}

-

-	public boolean equals(Object other) {

-		if (other instanceof VersionRange) {

-			return compareTo(other)==0;

-		}

-		return false;

-	}

-

-	public int hashCode() {

-		return low.hashCode() * high.hashCode();

-	}

-

-	public int compareTo(Object other) {

-		VersionRange range = (VersionRange) other;

-		VersionRange a = this, b = range;

-		if (range.isRange()) {

-			a = range;

-			b = this;

-		} else {

-			if ( !isRange() )

-				return low.compareTo(range.high);

-		}

-		int l = a.low.compareTo(b.low);

-		boolean ll = false;

-		if (a.includeLow())

-			ll = l <= 0;

-		else

-			ll = l < 0;

-

-		if (!ll)

-			return -1;

-

-		int h = a.high.compareTo(b.high);

-		if (a.includeHigh())

-			ll = h >= 0;

-		else

-			ll = h > 0;

-

-		if (ll)

-			return 0;

-		else

-			return 1;

-	}

-}

+/*
+ * $Id: VersionRange.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.util.regex.*;
+
+import org.osgi.framework.*;
+
+public class VersionRange implements Comparable {
+	Version high;
+	Version low;
+	char start = '[';
+	char end = ']';
+
+	static String V = "[0-9]+(\\.[0-9]+(\\.[0-9]+(\\.[a-zA-Z0-9_-]+)?)?)?";
+	static Pattern RANGE = Pattern.compile("(\\(|\\[)\\s*(" + V + ")\\s*,\\s*(" + V
+			+ ")\\s*(\\)|\\])");
+
+	public VersionRange(String string) {
+		string = string.trim();
+		Matcher m = RANGE.matcher(string);
+		if (m.matches()) {
+			start = m.group(1).charAt(0);
+			low = new Version(m.group(2));
+			high = new Version(m.group(6));
+			end = m.group(10).charAt(0);
+			if (low.compareTo(high) > 0)
+				throw new IllegalArgumentException(
+						"Low Range is higher than High Range: " + low + "-"
+								+ high);
+
+		} else
+			high = low = new Version(string);
+	}
+
+	public boolean isRange() {
+		return high != low;
+	}
+
+	public boolean includeLow() {
+		return start == '[';
+	}
+
+	public boolean includeHigh() {
+		return end == ']';
+	}
+
+	public String toString() {
+		if (high == low)
+			return high.toString();
+
+		StringBuffer sb = new StringBuffer();
+		sb.append(start);
+		sb.append(low);
+		sb.append(',');
+		sb.append(high);
+		sb.append(end);
+		return sb.toString();
+	}
+
+	public boolean equals(Object other) {
+		if (other instanceof VersionRange) {
+			return compareTo(other)==0;
+		}
+		return false;
+	}
+
+	public int hashCode() {
+		return low.hashCode() * high.hashCode();
+	}
+
+	public int compareTo(Object other) {
+		VersionRange range = (VersionRange) other;
+		VersionRange a = this, b = range;
+		if (range.isRange()) {
+			a = range;
+			b = this;
+		} else {
+			if ( !isRange() )
+				return low.compareTo(range.high);
+		}
+		int l = a.low.compareTo(b.low);
+		boolean ll = false;
+		if (a.includeLow())
+			ll = l <= 0;
+		else
+			ll = l < 0;
+
+		if (!ll)
+			return -1;
+
+		int h = a.high.compareTo(b.high);
+		if (a.includeHigh())
+			ll = h >= 0;
+		else
+			ll = h > 0;
+
+		if (ll)
+			return 0;
+		else
+			return 1;
+	}
+}
\ No newline at end of file