/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.apache.felix.bundlerepository.impl; import java.io.*; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.net.URLConnection; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Dictionary; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.jar.Attributes; import java.util.jar.JarFile; import java.util.jar.Manifest; import java.util.zip.GZIPInputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import org.apache.felix.bundlerepository.Capability; import org.apache.felix.bundlerepository.DataModelHelper; import org.apache.felix.bundlerepository.Property; import org.apache.felix.bundlerepository.Repository; import org.apache.felix.bundlerepository.Requirement; import org.apache.felix.bundlerepository.Resource; import org.apache.felix.utils.filter.FilterImpl; import org.apache.felix.utils.manifest.Attribute; import org.apache.felix.utils.manifest.Clause; import org.apache.felix.utils.manifest.Directive; import org.apache.felix.utils.manifest.Parser; import org.apache.felix.utils.version.VersionCleaner; import org.apache.felix.utils.version.VersionRange; import org.osgi.framework.Bundle; import org.osgi.framework.Constants; import org.osgi.framework.Filter; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.Version; public class DataModelHelperImpl implements DataModelHelper { public static final String BUNDLE_LICENSE = "Bundle-License"; public static final String BUNDLE_SOURCE = "Bundle-Source"; public Requirement requirement(String name, String filter) { RequirementImpl req = new RequirementImpl(); req.setName(name); if (filter != null) { req.setFilter(filter); } return req; } public Filter filter(String filter) { try { return FilterImpl.newInstance(filter); } catch (InvalidSyntaxException e) { IllegalArgumentException ex = new IllegalArgumentException(); ex.initCause(e); throw ex; } } public Repository repository(final URL url) throws Exception { InputStream is = null; BufferedReader br = null; try { if (url.getPath().endsWith(".zip")) { ZipInputStream zin = new ZipInputStream(FileUtil.openURL(url)); ZipEntry entry = zin.getNextEntry(); while (entry != null) { if (entry.getName().equals("repository.xml") || entry.getName().equals("index.xml")) { is = zin; break; } entry = zin.getNextEntry(); } // as the ZipInputStream is not used further it would not be closed. if (is == null) { try { zin.close(); } catch (IOException ex) { // Not much we can do. } } } else if (url.getPath().endsWith(".gz")) { is = new GZIPInputStream(FileUtil.openURL(url)); } else { is = FileUtil.openURL(url); } if (is != null) { String repostr = url.toExternalForm(); if (repostr.endsWith("zip")) { repostr = "jar:".concat(repostr).concat("!/"); } else if (repostr.endsWith(".xml")) { repostr = repostr.substring(0, repostr.lastIndexOf('/')+1); } return repository(is, repostr); } else { // This should not happen. throw new Exception("Unable to get input stream for repository."); } } finally { try { if (is != null) { is.close(); } } catch (IOException ex) { // Not much we can do. } } } public RepositoryImpl repository(InputStream is, String uri) throws Exception { RepositoryParser parser = RepositoryParser.getParser(); RepositoryImpl repository = parser.parseRepository(is, uri); return repository; } public Repository repository(Resource[] resources) { return new RepositoryImpl(resources); } public Capability capability(String name, Map properties) { CapabilityImpl cap = new CapabilityImpl(name); for (Iterator it = properties.entrySet().iterator(); it.hasNext();) { Map.Entry e = (Map.Entry) it.next(); cap.addProperty((String) e.getKey(), (String) e.getValue()); } return cap; } public String writeRepository(Repository repository) { try { StringWriter sw = new StringWriter(); writeRepository(repository, sw); return sw.toString(); } catch (IOException e) { IllegalStateException ex = new IllegalStateException(e); ex.initCause(e); throw ex; } } public void writeRepository(Repository repository, Writer writer) throws IOException { XmlWriter w = new XmlWriter(writer); toXml(w, repository); } public String writeResource(Resource resource) { try { StringWriter sw = new StringWriter(); writeResource(resource, sw); return sw.toString(); } catch (IOException e) { IllegalStateException ex = new IllegalStateException(e); ex.initCause(e); throw ex; } } public void writeResource(Resource resource, Writer writer) throws IOException { XmlWriter w = new XmlWriter(writer); toXml(w, resource); } public String writeCapability(Capability capability) { try { StringWriter sw = new StringWriter(); writeCapability(capability, sw); return sw.toString(); } catch (IOException e) { IllegalStateException ex = new IllegalStateException(e); ex.initCause(e); throw ex; } } public void writeCapability(Capability capability, Writer writer) throws IOException { XmlWriter w = new XmlWriter(writer); toXml(w, capability); } public String writeRequirement(Requirement requirement) { try { StringWriter sw = new StringWriter(); writeRequirement(requirement, sw); return sw.toString(); } catch (IOException e) { IllegalStateException ex = new IllegalStateException(e); ex.initCause(e); throw ex; } } public void writeRequirement(Requirement requirement, Writer writer) throws IOException { XmlWriter w = new XmlWriter(writer); toXml(w, requirement); } public String writeProperty(Property property) { try { StringWriter sw = new StringWriter(); writeProperty(property, sw); return sw.toString(); } catch (IOException e) { IllegalStateException ex = new IllegalStateException(e); ex.initCause(e); throw ex; } } public void writeProperty(Property property, Writer writer) throws IOException { XmlWriter w = new XmlWriter(writer); toXml(w, property); } private static void toXml(XmlWriter w, Repository repository) throws IOException { SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmss.SSS"); w.element(RepositoryParser.REPOSITORY) .attribute(RepositoryParser.NAME, repository.getName()) .attribute(RepositoryParser.LASTMODIFIED, format.format(new Date(repository.getLastModified()))); if (repository instanceof RepositoryImpl) { Referral[] referrals = ((RepositoryImpl) repository).getReferrals(); for (int i = 0; referrals != null && i < referrals.length; i++) { w.element(RepositoryParser.REFERRAL) .attribute(RepositoryParser.DEPTH, new Integer(referrals[i].getDepth())) .attribute(RepositoryParser.URL, referrals[i].getUrl()) .end(); } } Resource[] resources = repository.getResources(); for (int i = 0; resources != null && i < resources.length; i++) { toXml(w, resources[i]); } w.end(); } private static void toXml(XmlWriter w, Resource resource) throws IOException { w.element(RepositoryParser.RESOURCE) .attribute(Resource.ID, resource.getId()) .attribute(Resource.SYMBOLIC_NAME, resource.getSymbolicName()) .attribute(Resource.PRESENTATION_NAME, resource.getPresentationName()) .attribute(Resource.URI, getRelativeUri(resource, Resource.URI)) .attribute(Resource.VERSION, resource.getVersion().toString()); w.textElement(Resource.DESCRIPTION, resource.getProperties().get(Resource.DESCRIPTION)) .textElement(Resource.SIZE, resource.getProperties().get(Resource.SIZE)) .textElement(Resource.DOCUMENTATION_URI, getRelativeUri(resource, Resource.DOCUMENTATION_URI)) .textElement(Resource.SOURCE_URI, getRelativeUri(resource, Resource.SOURCE_URI)) .textElement(Resource.JAVADOC_URI, getRelativeUri(resource, Resource.JAVADOC_URI)) .textElement(Resource.LICENSE_URI, getRelativeUri(resource, Resource.LICENSE_URI)); String[] categories = resource.getCategories(); for (int i = 0; categories != null && i < categories.length; i++) { w.element(RepositoryParser.CATEGORY) .attribute(RepositoryParser.ID, categories[i]) .end(); } Capability[] capabilities = resource.getCapabilities(); for (int i = 0; capabilities != null && i < capabilities.length; i++) { toXml(w, capabilities[i]); } Requirement[] requirements = resource.getRequirements(); for (int i = 0; requirements != null && i < requirements.length; i++) { toXml(w, requirements[i]); } w.end(); } private static String getRelativeUri(Resource resource, String name) { String uri = (String) resource.getProperties().get(name); if (resource instanceof ResourceImpl) { try { uri = URI.create(((ResourceImpl) resource).getRepository().getURI()).relativize(URI.create(uri)).toASCIIString(); } catch (Throwable t) { } } return uri; } private static void toXml(XmlWriter w, Capability capability) throws IOException { w.element(RepositoryParser.CAPABILITY) .attribute(RepositoryParser.NAME, capability.getName()); Property[] props = capability.getProperties(); for (int j = 0; props != null && j < props.length; j++) { toXml(w, props[j]); } w.end(); } private static void toXml(XmlWriter w, Property property) throws IOException { w.element(RepositoryParser.P) .attribute(RepositoryParser.N, property.getName()) .attribute(RepositoryParser.T, property.getType()) .attribute(RepositoryParser.V, property.getValue()) .end(); } private static void toXml(XmlWriter w, Requirement requirement) throws IOException { w.element(RepositoryParser.REQUIRE) .attribute(RepositoryParser.NAME, requirement.getName()) .attribute(RepositoryParser.FILTER, requirement.getFilter()) .attribute(RepositoryParser.EXTEND, Boolean.toString(requirement.isExtend())) .attribute(RepositoryParser.MULTIPLE, Boolean.toString(requirement.isMultiple())) .attribute(RepositoryParser.OPTIONAL, Boolean.toString(requirement.isOptional())) .text(requirement.getComment().trim()) .end(); } public Resource createResource(final Bundle bundle) { final Dictionary dict = bundle.getHeaders(); return createResource(new Headers() { public String getHeader(String name) { return (String) dict.get(name); } }); } public Resource createResource(final URL bundleUrl) throws IOException { ResourceImpl resource = createResource(new Headers() { private final Manifest manifest; private Properties localization; { // Do not use a JarInputStream so that we can read the manifest even if it's not // the first entry in the JAR. byte[] man = loadEntry(JarFile.MANIFEST_NAME); if (man == null) { throw new IllegalArgumentException("The specified url is not a valid jar (can't read manifest): " + bundleUrl); } manifest = new Manifest(new ByteArrayInputStream(man)); } public String getHeader(String name) { String value = manifest.getMainAttributes().getValue(name); if (value != null && value.startsWith("%")) { if (localization == null) { try { localization = new Properties(); String path = manifest.getMainAttributes().getValue(Constants.BUNDLE_LOCALIZATION); if (path == null) { path = Constants.BUNDLE_LOCALIZATION_DEFAULT_BASENAME; } path += ".properties"; byte[] loc = loadEntry(path); if (loc != null) { localization.load(new ByteArrayInputStream(loc)); } } catch (IOException e) { // TODO: ? } } value = value.substring(1); value = localization.getProperty(value, value); } return value; } private byte[] loadEntry(String name) throws IOException { ZipInputStream zis = new ZipInputStream(FileUtil.openURL(bundleUrl)); try { for (ZipEntry e = zis.getNextEntry(); e != null; e = zis.getNextEntry()) { if (name.equalsIgnoreCase(e.getName())) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buf = new byte[1024]; int n; while ((n = zis.read(buf, 0, buf.length)) > 0) { baos.write(buf, 0, n); } return baos.toByteArray(); } } } finally { zis.close(); } return null; } }); if (resource != null) { if ("file".equals(bundleUrl.getProtocol())) { try { File f = new File(bundleUrl.toURI()); resource.put(Resource.SIZE, Long.toString(f.length()), null); } catch (URISyntaxException e) { throw new RuntimeException(e); } } resource.put(Resource.URI, bundleUrl.toExternalForm(), null); } return resource; } public Resource createResource(final Attributes attributes) { return createResource(new Headers() { public String getHeader(String name) { return attributes.getValue(name); } }); } public ResourceImpl createResource(Headers headers) { String bsn = headers.getHeader(Constants.BUNDLE_SYMBOLICNAME); if (bsn == null) { return null; } ResourceImpl resource = new ResourceImpl(); populate(headers, resource); return resource; } static void populate(Headers headers, ResourceImpl resource) { String bsn = getSymbolicName(headers); String v = getVersion(headers); resource.put(Resource.ID, bsn + "/" + v); resource.put(Resource.SYMBOLIC_NAME, bsn); resource.put(Resource.VERSION, v); if (headers.getHeader(Constants.BUNDLE_NAME) != null) { resource.put(Resource.PRESENTATION_NAME, headers.getHeader(Constants.BUNDLE_NAME)); } if (headers.getHeader(Constants.BUNDLE_DESCRIPTION) != null) { resource.put(Resource.DESCRIPTION, headers.getHeader(Constants.BUNDLE_DESCRIPTION)); } if (headers.getHeader(BUNDLE_LICENSE) != null) { resource.put(Resource.LICENSE_URI, headers.getHeader(BUNDLE_LICENSE)); } if (headers.getHeader(Constants.BUNDLE_COPYRIGHT) != null) { resource.put(Resource.COPYRIGHT, headers.getHeader(Constants.BUNDLE_COPYRIGHT)); } if (headers.getHeader(Constants.BUNDLE_DOCURL) != null) { resource.put(Resource.DOCUMENTATION_URI, headers.getHeader(Constants.BUNDLE_DOCURL)); } if (headers.getHeader(BUNDLE_SOURCE) != null) { resource.put(Resource.SOURCE_URI, headers.getHeader(BUNDLE_SOURCE)); } doCategories(resource, headers); doBundle(resource, headers); doImportExportServices(resource, headers); doFragment(resource, headers); doRequires(resource, headers); doExports(resource, headers); doImports(resource, headers); doExecutionEnvironment(resource, headers); doProvides(resource, headers); } private static void doCategories(ResourceImpl resource, Headers headers) { Clause[] clauses = Parser.parseHeader(headers.getHeader(Constants.BUNDLE_CATEGORY)); for (int i = 0; clauses != null && i < clauses.length; i++) { resource.addCategory(clauses[i].getName()); } } private static void doImportExportServices(ResourceImpl resource, Headers headers) { Clause[] imports = Parser.parseHeader(headers.getHeader(Constants.IMPORT_SERVICE)); for (int i = 0; imports != null && i < imports.length; i++) { RequirementImpl ri = new RequirementImpl(Capability.SERVICE); ri.setFilter(createServiceFilter(imports[i])); ri.addText("Import Service " + imports[i].getName()); String avail = imports[i].getDirective("availability"); String mult = imports[i].getDirective("multiple"); ri.setOptional("optional".equalsIgnoreCase(avail)); ri.setMultiple(!"false".equalsIgnoreCase(mult)); resource.addRequire(ri); } Clause[] exports = Parser.parseHeader(headers.getHeader(Constants.EXPORT_SERVICE)); for (int i = 0; exports != null && i < exports.length; i++) { CapabilityImpl cap = createServiceCapability(exports[i]); resource.addCapability(cap); } } private static String createServiceFilter(Clause clause) { String f = clause.getAttribute("filter"); StringBuffer filter = new StringBuffer(); if (f != null) { filter.append("(&"); } filter.append("("); filter.append(Capability.SERVICE); filter.append("="); filter.append(clause.getName()); filter.append(")"); if (f != null) { if (!f.startsWith("(")) { filter.append("(").append(f).append(")"); } else { filter.append(f); } filter.append(")"); } return filter.toString(); } private static CapabilityImpl createServiceCapability(Clause clause) { CapabilityImpl capability = new CapabilityImpl(Capability.SERVICE); capability.addProperty(Capability.SERVICE, clause.getName()); Attribute[] attributes = clause.getAttributes(); for (int i = 0; attributes != null && i < attributes.length; i++) { capability.addProperty(attributes[i].getName(), attributes[i].getValue()); } return capability; } private static void doFragment(ResourceImpl resource, Headers headers) { // Check if we are a fragment Clause[] clauses = Parser.parseHeader(headers.getHeader(Constants.FRAGMENT_HOST)); if (clauses != null && clauses.length == 1) { // We are a fragment, create a requirement // to our host. RequirementImpl r = new RequirementImpl(Capability.BUNDLE); StringBuffer sb = new StringBuffer(); sb.append("(&(symbolicname="); sb.append(clauses[0].getName()); sb.append(")"); appendVersion(sb, VersionRange.parseVersionRange(clauses[0].getAttribute(Constants.BUNDLE_VERSION_ATTRIBUTE))); sb.append(")"); r.setFilter(sb.toString()); r.addText("Required Host " + clauses[0].getName()); r.setExtend(true); r.setOptional(false); r.setMultiple(false); resource.addRequire(r); // And insert a capability that we are available // as a fragment. ### Do we need that with extend? CapabilityImpl capability = new CapabilityImpl(Capability.FRAGMENT); capability.addProperty("host", clauses[0].getName()); capability.addProperty("version", Property.VERSION, getVersion(clauses[0])); resource.addCapability(capability); } } private static void doRequires(ResourceImpl resource, Headers headers) { Clause[] clauses = Parser.parseHeader(headers.getHeader(Constants.REQUIRE_BUNDLE)); for (int i = 0; clauses != null && i < clauses.length; i++) { RequirementImpl r = new RequirementImpl(Capability.BUNDLE); VersionRange v = VersionRange.parseVersionRange(clauses[i].getAttribute(Constants.BUNDLE_VERSION_ATTRIBUTE)); StringBuffer sb = new StringBuffer(); sb.append("(&(symbolicname="); sb.append(clauses[i].getName()); sb.append(")"); appendVersion(sb, v); sb.append(")"); r.setFilter(sb.toString()); r.addText("Require Bundle " + clauses[i].getName() + "; " + v); r.setOptional(Constants.RESOLUTION_OPTIONAL.equalsIgnoreCase(clauses[i].getDirective(Constants.RESOLUTION_DIRECTIVE))); resource.addRequire(r); } } private static void doBundle(ResourceImpl resource, Headers headers) { CapabilityImpl capability = new CapabilityImpl(Capability.BUNDLE); capability.addProperty(Resource.SYMBOLIC_NAME, getSymbolicName(headers)); if (headers.getHeader(Constants.BUNDLE_NAME) != null) { capability.addProperty(Resource.PRESENTATION_NAME, headers.getHeader(Constants.BUNDLE_NAME)); } capability.addProperty(Resource.VERSION, Property.VERSION, getVersion(headers)); capability.addProperty(Resource.MANIFEST_VERSION, getManifestVersion(headers)); resource.addCapability(capability); } private static void doExports(ResourceImpl resource, Headers headers) { Clause[] clauses = Parser.parseHeader(headers.getHeader(Constants.EXPORT_PACKAGE)); for (int i = 0; clauses != null && i < clauses.length; i++) { CapabilityImpl capability = createCapability(Capability.PACKAGE, clauses[i]); resource.addCapability(capability); } } private static void doProvides(ResourceImpl resource, Headers headers) { Clause[] clauses = Parser.parseHeader(headers.getHeader(Constants.PROVIDE_CAPABILITY)); if (clauses != null) { for (Clause clause : clauses) { CapabilityImpl capability = createCapability(clause.getName(), clause); resource.addCapability(capability); } } } private static CapabilityImpl createCapability(String name, Clause clause) { CapabilityImpl capability = new CapabilityImpl(NamespaceTranslator.getFelixNamespace(name)); capability.addProperty(name, clause.getName()); capability.addProperty(Resource.VERSION, Property.VERSION, getVersion(clause)); Attribute[] attributes = clause.getAttributes(); for (int i = 0; attributes != null && i < attributes.length; i++) { String key = attributes[i].getName(); if (key.equalsIgnoreCase(Constants.PACKAGE_SPECIFICATION_VERSION) || key.equalsIgnoreCase(Constants.VERSION_ATTRIBUTE) || key.equalsIgnoreCase("version:Version")) { continue; } else { String value = attributes[i].getValue(); capability.addProperty(key, value); } } Directive[] directives = clause.getDirectives(); for (int i = 0; directives != null && i < directives.length; i++) { String key = directives[i].getName(); String value = directives[i].getValue(); capability.addProperty(key + ":", value); } return capability; } private static void doImports(ResourceImpl resource, Headers headers) { Clause[] clauses = Parser.parseHeader(headers.getHeader(Constants.IMPORT_PACKAGE)); for (int i = 0; clauses != null && i < clauses.length; i++) { RequirementImpl requirement = new RequirementImpl(Capability.PACKAGE); createImportFilter(requirement, Capability.PACKAGE, clauses[i]); requirement.addText("Import package " + clauses[i]); requirement.setOptional(Constants.RESOLUTION_OPTIONAL.equalsIgnoreCase(clauses[i].getDirective(Constants.RESOLUTION_DIRECTIVE))); resource.addRequire(requirement); } } private static void createImportFilter(RequirementImpl requirement, String name, Clause clause) { StringBuffer filter = new StringBuffer(); filter.append("(&("); filter.append(name); filter.append("="); filter.append(clause.getName()); filter.append(")"); appendVersion(filter, getVersionRange(clause)); Attribute[] attributes = clause.getAttributes(); Set attrs = doImportPackageAttributes(requirement, filter, attributes); // The next code is using the subset operator // to check mandatory attributes, it seems to be // impossible to rewrite. It must assert that whateber // is in mandatory: must be in any of the attributes. // This is a fundamental shortcoming of the filter language. 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(")"); requirement.setFilter(filter.toString()); } private static Set doImportPackageAttributes(RequirementImpl requirement, StringBuffer filter, Attribute[] attributes) { HashSet set = new HashSet(); for (int i = 0; attributes != null && i < attributes.length; i++) { String name = attributes[i].getName(); String value = attributes[i].getValue(); if (name.equalsIgnoreCase(Constants.PACKAGE_SPECIFICATION_VERSION) || name.equalsIgnoreCase(Constants.VERSION_ATTRIBUTE)) { continue; } else if (name.equalsIgnoreCase(Constants.RESOLUTION_DIRECTIVE + ":")) { requirement.setOptional(Constants.RESOLUTION_OPTIONAL.equalsIgnoreCase(value)); } if (name.endsWith(":")) { // Ignore } else { filter.append("("); filter.append(name); filter.append("="); filter.append(value); filter.append(")"); set.add(name); } } return set; } private static void doExecutionEnvironment(ResourceImpl resource, Headers headers) { Clause[] clauses = Parser.parseHeader(headers.getHeader(Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT)); if (clauses != null && clauses.length > 0) { StringBuffer sb = new StringBuffer(); sb.append("(|"); for (int i = 0; i < clauses.length; i++) { sb.append("("); sb.append(Capability.EXECUTIONENVIRONMENT); sb.append("="); sb.append(clauses[i].getName()); sb.append(")"); } sb.append(")"); RequirementImpl req = new RequirementImpl(Capability.EXECUTIONENVIRONMENT); req.setFilter(sb.toString()); req.addText("Execution Environment " + sb.toString()); resource.addRequire(req); } } private static String getVersion(Clause clause) { String v = clause.getAttribute(Constants.VERSION_ATTRIBUTE); if (v == null) { v = clause.getAttribute(Constants.PACKAGE_SPECIFICATION_VERSION); } if (v == null) { v = clause.getAttribute(Constants.BUNDLE_VERSION_ATTRIBUTE); } if (v == null) { v = clause.getAttribute("version:Version"); } return VersionCleaner.clean(v); } private static VersionRange getVersionRange(Clause clause) { String v = clause.getAttribute(Constants.VERSION_ATTRIBUTE); if (v == null) { v = clause.getAttribute(Constants.PACKAGE_SPECIFICATION_VERSION); } if (v == null) { v = clause.getAttribute(Constants.BUNDLE_VERSION_ATTRIBUTE); } return VersionRange.parseVersionRange(v); } private static String getSymbolicName(Headers headers) { String bsn = headers.getHeader(Constants.BUNDLE_SYMBOLICNAME); if (bsn == null) { bsn = headers.getHeader(Constants.BUNDLE_NAME); if (bsn == null) { bsn = "Untitled-" + headers.hashCode(); } } Clause[] clauses = Parser.parseHeader(bsn); return clauses[0].getName(); } private static String getVersion(Headers headers) { String v = headers.getHeader(Constants.BUNDLE_VERSION); return VersionCleaner.clean(v); } private static String getManifestVersion(Headers headers) { String v = headers.getHeader(Constants.BUNDLE_MANIFESTVERSION); if (v == null) { v = "1"; } return v; } private static void appendVersion(StringBuffer filter, VersionRange version) { if (version != null) { if ( !version.isOpenFloor() ) { if ( !Version.emptyVersion.equals(version.getFloor()) ) { filter.append("("); filter.append(Constants.VERSION_ATTRIBUTE); filter.append(">="); filter.append(version.getFloor()); filter.append(")"); } } else { filter.append("(!("); filter.append(Constants.VERSION_ATTRIBUTE); filter.append("<="); filter.append(version.getFloor()); filter.append("))"); } if (!VersionRange.INFINITE_VERSION.equals(version.getCeiling())) { if ( !version.isOpenCeiling() ) { filter.append("("); filter.append(Constants.VERSION_ATTRIBUTE); filter.append("<="); filter.append(version.getCeiling()); filter.append(")"); } else { filter.append("(!("); filter.append(Constants.VERSION_ATTRIBUTE); filter.append(">="); filter.append(version.getCeiling()); filter.append("))"); } } } } interface Headers { String getHeader(String name); } public Repository readRepository(String xml) throws Exception { try { return readRepository(new StringReader(xml)); } catch (IOException e) { IllegalStateException ex = new IllegalStateException(e); ex.initCause(e); throw ex; } } public Repository readRepository(Reader reader) throws Exception { return RepositoryParser.getParser().parseRepository(reader); } public Resource readResource(String xml) throws Exception { try { return readResource(new StringReader(xml)); } catch (IOException e) { IllegalStateException ex = new IllegalStateException(e); ex.initCause(e); throw ex; } } public Resource readResource(Reader reader) throws Exception { return RepositoryParser.getParser().parseResource(reader); } public Capability readCapability(String xml) throws Exception { try { return readCapability(new StringReader(xml)); } catch (IOException e) { IllegalStateException ex = new IllegalStateException(e); ex.initCause(e); throw ex; } } public Capability readCapability(Reader reader) throws Exception { return RepositoryParser.getParser().parseCapability(reader); } public Requirement readRequirement(String xml) throws Exception { try { return readRequirement(new StringReader(xml)); } catch (IOException e) { IllegalStateException ex = new IllegalStateException(e); ex.initCause(e); throw ex; } } public Requirement readRequirement(Reader reader) throws Exception { return RepositoryParser.getParser().parseRequirement(reader); } public Property readProperty(String xml) throws Exception { try { return readProperty(new StringReader(xml)); } catch (IOException e) { IllegalStateException ex = new IllegalStateException(e); ex.initCause(e); throw ex; } } public Property readProperty(Reader reader) throws Exception { return RepositoryParser.getParser().parseProperty(reader); } }