You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ace.apache.org by br...@apache.org on 2013/06/25 16:45:34 UTC

svn commit: r1496498 - in /ace/trunk/org.apache.ace.obr: ./ src/org/apache/ace/obr/metadata/util/ src/org/apache/ace/obr/storage/file/ src/org/osgi/impl/bundle/bindex/ src/org/osgi/impl/bundle/obr/resource/ test/org/apache/ace/obr/metadata/util/ test/o...

Author: bramk
Date: Tue Jun 25 14:45:34 2013
New Revision: 1496498

URL: http://svn.apache.org/r1496498
Log:
ACE-365 Expose symbolicname and version on non-bundle resource in the OBR

Factorred the filename heuristices into seperate utility class to prevent deuplications.


Added:
    ace/trunk/org.apache.ace.obr/src/org/apache/ace/obr/metadata/util/
    ace/trunk/org.apache.ace.obr/src/org/apache/ace/obr/metadata/util/ResourceMetaData.java
    ace/trunk/org.apache.ace.obr/test/org/apache/ace/obr/metadata/util/
    ace/trunk/org.apache.ace.obr/test/org/apache/ace/obr/metadata/util/ResourceMetaDataTest.java
Modified:
    ace/trunk/org.apache.ace.obr/metadata.bnd
    ace/trunk/org.apache.ace.obr/src/org/apache/ace/obr/storage/file/BundleFileStore.java
    ace/trunk/org.apache.ace.obr/src/org/osgi/impl/bundle/bindex/Index.java
    ace/trunk/org.apache.ace.obr/src/org/osgi/impl/bundle/obr/resource/ResourceImpl.java
    ace/trunk/org.apache.ace.obr/storage.bnd
    ace/trunk/org.apache.ace.obr/test/org/apache/ace/obr/storage/file/BundleFileStoreTest.java

Modified: ace/trunk/org.apache.ace.obr/metadata.bnd
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.obr/metadata.bnd?rev=1496498&r1=1496497&r2=1496498&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.obr/metadata.bnd (original)
+++ ace/trunk/org.apache.ace.obr/metadata.bnd Tue Jun 25 14:45:34 2013
@@ -7,7 +7,8 @@ Private-Package: org.apache.ace.obr.meta
 	org.kxml2.wap.wv,\
 	org.xmlpull.v1,\
 	org.osgi.impl.bundle.bindex,\
-	org.osgi.impl.bundle.obr.resource
+	org.osgi.impl.bundle.obr.resource,\
+	org.apache.ace.obr.metadata.util
 Bundle-Activator: org.apache.ace.obr.metadata.bindex.Activator
 Export-Package: org.apache.ace.obr.metadata,\
 	org.osgi.impl.bundle.obr.resource,\

Added: ace/trunk/org.apache.ace.obr/src/org/apache/ace/obr/metadata/util/ResourceMetaData.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.obr/src/org/apache/ace/obr/metadata/util/ResourceMetaData.java?rev=1496498&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.obr/src/org/apache/ace/obr/metadata/util/ResourceMetaData.java (added)
+++ ace/trunk/org.apache.ace.obr/src/org/apache/ace/obr/metadata/util/ResourceMetaData.java Tue Jun 25 14:45:34 2013
@@ -0,0 +1,155 @@
+/*
+ * 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.ace.obr.metadata.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.jar.Attributes;
+import java.util.jar.JarInputStream;
+import java.util.jar.Manifest;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.osgi.framework.Constants;
+
+/**
+ * Internal util class that represents some basic resource metadata and provides static methods to retrieve it.
+ * 
+ */
+public class ResourceMetaData {
+
+    // matches a valid OSGi version
+    private static final Pattern VERSION_PATTERN = Pattern.compile("(\\d+)(\\.(\\d+)(\\.(\\d+)([\\.-]([\\w-]+))?)?)?");
+
+    /**
+     * Tries extract file metadata from a file assuming it is a valid OSGi bundle.
+     * 
+     * @param file
+     *            the file to analyze
+     * @return the metadata, or <code>null</code> if the file is not a valid bundle.
+     */
+    public static ResourceMetaData getBundleMetaData(File file) {
+        JarInputStream jis = null;
+        try {
+            jis = new JarInputStream(new FileInputStream(file));
+            Manifest manifest = jis.getManifest();
+            if (manifest != null) {
+                Attributes attributes = manifest.getMainAttributes();
+                if (attributes != null) {
+                    String bundleSymbolicName = attributes.getValue(Constants.BUNDLE_SYMBOLICNAME);
+                    String bundleVersion = attributes.getValue(Constants.BUNDLE_VERSION);
+                    if (bundleSymbolicName != null) {
+                        // ACE-350 strip BSN parameters
+                        if (bundleSymbolicName.indexOf(";") > 0) {
+                            bundleSymbolicName = bundleSymbolicName.substring(0, bundleSymbolicName.indexOf(";"));
+                        }
+                        if (bundleVersion == null) {
+                            bundleVersion = "0.0.0";
+                        }
+                        return new ResourceMetaData(bundleSymbolicName, bundleVersion, "jar");
+                    }
+                }
+            }
+            return null;
+        }
+        catch (Exception e) {
+            return null;
+        }
+        finally {
+            try {
+                jis.close();
+            }
+            catch (IOException e) {
+                // too bad
+            }
+        }
+    }
+
+    /**
+     * Tries extract file metadata from a filename assuming a pattern. The version must be a valid OSGi version. If no
+     * version is found the default "0.0.0" is returned. <br/>
+     * <br/>
+     * Filename pattern: <code>&lt;filename&gt;[-&lt;version&gt;][.&lt;extension&gt;]<code>
+     * 
+     * @param filename
+     *            the filename to analyze
+     * @return the metadata
+     */
+    public static ResourceMetaData getArtifactMetaData(String fileName) {
+
+        if(fileName == null || fileName.equals("")){
+            return null;
+        }
+        String symbolicName = null;
+        String version = null;
+        String extension = null;
+
+        // determine extension
+        String[] fileNameParts = fileName.split("\\.");
+        if (fileNameParts.length > 1) {
+            extension = fileNameParts[fileNameParts.length - 1];
+            symbolicName = fileName.substring(0, fileName.lastIndexOf('.'));
+        }
+        else {
+            symbolicName = fileName;
+        }
+
+        // determine version
+        int dashIndex = symbolicName.indexOf('-');
+        while (dashIndex != -1 && version == null) {
+            String versionCandidate = symbolicName.substring(dashIndex + 1);
+            Matcher versionMatcher = VERSION_PATTERN.matcher(versionCandidate);
+            if (versionMatcher.matches()) {
+                symbolicName = symbolicName.substring(0, dashIndex);
+                version = versionCandidate;
+            }
+            else {
+                dashIndex = symbolicName.indexOf('-', dashIndex + 1);
+            }
+        }
+
+        if (version == null) {
+            version = "0.0.0";
+        }
+        return new ResourceMetaData(symbolicName, version, extension);
+    }
+
+    private final String m_bundleSymbolicName;
+    private final String m_version;
+    private final String m_extension;
+
+    ResourceMetaData(String bundleSymbolicName, String version, String extension) {
+        m_bundleSymbolicName = bundleSymbolicName;
+        m_version = version;
+        m_extension = extension;
+    }
+
+    public String getSymbolicName() {
+        return m_bundleSymbolicName;
+    }
+
+    public String getVersion() {
+        return m_version;
+    }
+
+    public String getExtension() {
+        return m_extension;
+    }
+}

Modified: ace/trunk/org.apache.ace.obr/src/org/apache/ace/obr/storage/file/BundleFileStore.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.obr/src/org/apache/ace/obr/storage/file/BundleFileStore.java?rev=1496498&r1=1496497&r2=1496498&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.obr/src/org/apache/ace/obr/storage/file/BundleFileStore.java (original)
+++ ace/trunk/org.apache.ace.obr/src/org/apache/ace/obr/storage/file/BundleFileStore.java Tue Jun 25 14:45:34 2013
@@ -31,29 +31,22 @@ import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.util.Dictionary;
 import java.util.Stack;
-import java.util.jar.Attributes;
-import java.util.jar.JarInputStream;
-import java.util.jar.Manifest;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 import org.apache.ace.obr.metadata.MetadataGenerator;
+import org.apache.ace.obr.metadata.util.ResourceMetaData;
 import org.apache.ace.obr.storage.BundleStore;
 import org.apache.ace.obr.storage.file.constants.OBRFileStoreConstants;
-import org.osgi.framework.Constants;
 import org.osgi.service.cm.ConfigurationException;
 import org.osgi.service.cm.ManagedService;
 import org.osgi.service.log.LogService;
 
 /**
- * This BundleStore retrieves the files from the file system. Via the Configurator the relative path is set, and all bundles and
- * the repository.xml should be retrievable from that path (which will internally be converted to an absolute path).
+ * This BundleStore retrieves the files from the file system. Via the Configurator the relative path is set, and all
+ * bundles and the repository.xml should be retrievable from that path (which will internally be converted to an
+ * absolute path).
  */
 public class BundleFileStore implements BundleStore, ManagedService {
 
-    // matches a valid OSGi version
-    private final Pattern VERSION_PATTERN = Pattern.compile("(\\d+)(\\.(\\d+)(\\.(\\d+)([\\.-]([\\w-]+))?)?)?");
-    
     private static int BUFFER_SIZE = 8 * 1024;
     private static final String REPOSITORY_XML = "repository.xml";
 
@@ -67,7 +60,8 @@ public class BundleFileStore implements 
     /**
      * Checks if the the directory was modified since we last checked. If so, the meta-data generator is called.
      * 
-     * @throws IOException If there is a problem synchronizing the meta-data.
+     * @throws IOException
+     *             If there is a problem synchronizing the meta-data.
      */
     public void synchronizeMetadata() throws IOException {
         File dir = m_dir;
@@ -85,20 +79,21 @@ public class BundleFileStore implements 
         }
         FileInputStream result = null;
         try {
-			result = new FileInputStream(createFile(fileName));
-		} catch (FileNotFoundException e) {
-			// Resource does not exist; notify caller by returning null...
-		}
-		return result;
+            result = new FileInputStream(createFile(fileName));
+        }
+        catch (FileNotFoundException e) {
+            // Resource does not exist; notify caller by returning null...
+        }
+        return result;
     }
 
     public String put(InputStream data, String fileName) throws IOException {
 
         File tempFile = downloadToTempFile(data);
 
-        ResourceMetaData metaData = getBundleMetaData(tempFile);
+        ResourceMetaData metaData = ResourceMetaData.getBundleMetaData(tempFile);
         if (metaData == null) {
-            metaData = getArtifactMetaData(fileName);
+            metaData = ResourceMetaData.getArtifactMetaData(fileName);
         }
         if (metaData == null) {
             throw new IOException("Not a valid bundle and no filename found");
@@ -113,7 +108,7 @@ public class BundleFileStore implements 
         }
 
         moveFile(tempFile, storeLocation);
-        
+
         String filePath = storeLocation.toURI().toString().substring(getWorkingDir().toURI().toString().length());
         if (filePath.startsWith("/")) {
             filePath = filePath.substring(1);
@@ -175,7 +170,6 @@ public class BundleFileStore implements 
         }
     }
 
-
     /**
      * Computes a magic checksum used to determine whether there where changes in the directory without actually looking
      * into the files or using observation.
@@ -185,8 +179,6 @@ public class BundleFileStore implements 
      * @return The checksum
      */
     private String getDirChecksum(File dir) {
-        long start = System.nanoTime();
-
         MessageDigest digest = null;
         try {
             digest = MessageDigest.getInstance("MD5");
@@ -220,8 +212,10 @@ public class BundleFileStore implements 
     /**
      * Downloads a given input stream to a temporary file.
      * 
-     * @param source the input stream to download;
-     * @throws IOException in case of I/O problems.
+     * @param source
+     *            the input stream to download;
+     * @throws IOException
+     *             in case of I/O problems.
      */
     private File downloadToTempFile(InputStream source) throws IOException {
         File tempFile = File.createTempFile("obr", ".tmp");
@@ -241,100 +235,15 @@ public class BundleFileStore implements 
             closeQuietly(fos);
         }
     }
-    
-    /**
-     * Tries extract file metadata from a file assuming it is a valid OSGi bundle.
-     * 
-     * @param file the file to analyze
-     * @return the metadata, or <code>null</code> if the file is not a valid bundle.
-     */
-    private ResourceMetaData getBundleMetaData(File file) {
-        JarInputStream jis = null;
-        try {
-            jis = new JarInputStream(new FileInputStream(file));
-            Manifest manifest = jis.getManifest();
-            if (manifest != null) {
-                Attributes attributes = manifest.getMainAttributes();
-                if (attributes != null) {
-                    String bundleSymbolicName = attributes.getValue(Constants.BUNDLE_SYMBOLICNAME);
-                    String bundleVersion = attributes.getValue(Constants.BUNDLE_VERSION);
-                    if (bundleSymbolicName != null) {
-                    	// ACE-350 strip BSN parameters 
-                    	if(bundleSymbolicName.indexOf(";") > 0){
-                    		bundleSymbolicName = bundleSymbolicName.substring(0, bundleSymbolicName.indexOf(";"));
-                    	}
-                        if (bundleVersion == null) {
-                            bundleVersion = "0.0.0";
-                        }
-                        return new ResourceMetaData(bundleSymbolicName, bundleVersion, "jar");
-                    }
-                }
-            }
-            return null;
-        }
-        catch (Exception e) {
-            return null;
-        }
-        finally {
-            closeQuietly(jis);
-        }
-    }
-        
-    /**
-     * Tries extract file metadata from a filename assuming a pattern. The version must be a valid OSGi version. If no
-     * version is found the default "0.0.0" is returned.
-     * <br/><br/>
-     * Filename pattern: <code>&lt;filename&gt;[-&lt;version&gt;][.&lt;extension&gt;]<code>
-     * 
-     * @param file the fileName to analyze
-     * @return the metadata, or <code>null</code> if the file is not a valid bundle.
-     */
-    ResourceMetaData getArtifactMetaData(String fileName) {
-        
-        if (fileName == null || fileName.equals("")) {
-            return null;
-        }
-
-        String symbolicName = null;
-        String version = null;
-        String extension = null;
-
-        // determine extension
-        String[] fileNameParts = fileName.split("\\.");
-        if (fileNameParts.length > 1) {
-            extension = fileNameParts[fileNameParts.length - 1];
-            symbolicName = fileName.substring(0, fileName.lastIndexOf('.'));
-        }
-        else {
-            symbolicName = fileName;
-        }
 
-        // determine version
-        int dashIndex = symbolicName.indexOf('-');
-        while (dashIndex != -1 && version == null) {
-            String versionCandidate = symbolicName.substring(dashIndex + 1);
-            Matcher versionMatcher = VERSION_PATTERN.matcher(versionCandidate);
-            if (versionMatcher.matches()) {
-                symbolicName = symbolicName.substring(0, dashIndex);
-                version = versionCandidate;
-            }
-            else {
-                dashIndex = symbolicName.indexOf('-', dashIndex + 1);                
-            }
-        }
-        
-        if (version == null) {
-            version = "0.0.0";
-        }
-        return new ResourceMetaData(symbolicName, version, extension);
-    }
-    
     /**
      * Encapsulated the store layout strategy by creating the resource file based on the provided meta-data.
      * 
-     * @param metaData the meta-data for the resource
+     * @param metaData
+     *            the meta-data for the resource
      * @return the resource file
-     * @throws IOException in case of I/O problems.
+     * @throws IOException
+     *             in case of I/O problems.
      */
     private File getResourceFile(ResourceMetaData metaData) throws IOException {
 
@@ -351,7 +260,7 @@ public class BundleFileStore implements 
         if (!resourceFile.exists() && !resourceFile.mkdirs()) {
             throw new IOException("Failed to create store directory");
         }
-        
+
         if (metaData.getExtension() != null && !metaData.getExtension().equals("")) {
             resourceFile = new File(resourceFile, metaData.getSymbolicName() + "-" + metaData.getVersion() + "." + metaData.getExtension());
         }
@@ -371,10 +280,13 @@ public class BundleFileStore implements 
     /**
      * Moves a given source file to a destination location, effectively resulting in a rename.
      * 
-     * @param source the source file to move;
-     * @param dest the destination file to move the file to.
+     * @param source
+     *            the source file to move;
+     * @param dest
+     *            the destination file to move the file to.
      * @return <code>true</code> if the move succeeded.
-     * @throws IOException in case of I/O problems.
+     * @throws IOException
+     *             in case of I/O problems.
      */
     private boolean moveFile(File source, File dest) throws IOException {
         final int bufferSize = 1024 * 1024; // 1MB
@@ -421,7 +333,8 @@ public class BundleFileStore implements 
     /**
      * Safely closes a given resource, ignoring any I/O exceptions that might occur by this.
      * 
-     * @param resource the resource to close, can be <code>null</code>.
+     * @param resource
+     *            the resource to close, can be <code>null</code>.
      */
     private void closeQuietly(Closeable resource) {
         try {
@@ -437,39 +350,12 @@ public class BundleFileStore implements 
     /**
      * Creates a {@link File} object with the given file name in the current working directory.
      * 
-     * @param fileName the name of the file.
+     * @param fileName
+     *            the name of the file.
      * @return a {@link File} object, never <code>null</code>.
      * @see #getWorkingDir()
      */
     private File createFile(String fileName) {
         return new File(getWorkingDir(), fileName);
     }
-    
-    /**
-     * Wrapper that holds resource meta-data relevant to the store layout.
-     *
-     */
-    static class ResourceMetaData {
-        private final String m_bundleSymbolicName;
-        private final String m_version;
-        private final String m_extension;
-        
-        public ResourceMetaData(String bundleSymbolicName, String version, String extension) {
-            m_bundleSymbolicName = bundleSymbolicName;
-            m_version = version;
-            m_extension = extension;
-        }
-        
-        public String getSymbolicName() {
-            return m_bundleSymbolicName;
-        }
-        
-        public String getVersion() {
-            return m_version;
-        }
-        
-        public String getExtension() {
-            return m_extension;
-        }
-    }
-}
\ No newline at end of file
+}

Modified: ace/trunk/org.apache.ace.obr/src/org/osgi/impl/bundle/bindex/Index.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.obr/src/org/osgi/impl/bundle/bindex/Index.java?rev=1496498&r1=1496497&r2=1496498&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.obr/src/org/osgi/impl/bundle/bindex/Index.java (original)
+++ ace/trunk/org.apache.ace.obr/src/org/osgi/impl/bundle/bindex/Index.java Tue Jun 25 14:45:34 2013
@@ -39,270 +39,273 @@ import java.util.Set;
 import java.util.zip.CRC32;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipOutputStream;
+
+import org.apache.ace.obr.metadata.util.ResourceMetaData;
 import org.osgi.impl.bundle.obr.resource.BundleInfo;
 import org.osgi.impl.bundle.obr.resource.RepositoryImpl;
 import org.osgi.impl.bundle.obr.resource.ResourceImpl;
 import org.osgi.impl.bundle.obr.resource.Tag;
+import org.osgi.impl.bundle.obr.resource.VersionRange;
 
 /**
- * Iterate over a set of given bundles and convert them to resources. When -a is
- * specified, other resources than bundles will be included too. After
- * this, convert an local urls (file systems, JAR file) to relative URLs and
- * create a ZIP file with the complete content. This ZIP file can be used in an
- * OSGi Framework to map to an http service or it can be expanded on the web
- * server's file system.
- *
+ * Iterate over a set of given bundles and convert them to resources. When -a is specified, other resources than bundles
+ * will be included too. After this, convert an local urls (file systems, JAR file) to relative URLs and create a ZIP
+ * file with the complete content. This ZIP file can be used in an OSGi Framework to map to an http service or it can be
+ * expanded on the web server's file system.
+ * 
  * @version $Revision: 44 $
  */
 public class Index
 {
-	static String			repositoryFileName	= "repository.xml";
-	static URL				licenseURL			= null;
-	static boolean			quiet				= false;
-	static String			name				= "Untitled";
-    static boolean          all                 = false;
-	static String			urlTemplate			= null;
-	static File				rootFile			= new File("")
-														.getAbsoluteFile();
-	static RepositoryImpl	repository;
-	static String			root;
-
-	/**
-	 * Main entry. See -help for options.
-	 *
-	 * @param args
-	 * @throws Exception
-	 */
-	public static void main(String args[]) throws Exception {
-		System.err.println("Bundle Indexer | v2.2");
-		System.err.println("(c) 2007 OSGi, All Rights Reserved");
-
-		Set resources = new HashSet();
-		root = rootFile.toURL().toString();
-		repository = new RepositoryImpl(rootFile.toURL());
 
-		for (int i = 0; i < args.length; i++) {
+    static String repositoryFileName = "repository.xml";
+    static URL licenseURL = null;
+    static boolean quiet = false;
+    static String name = "Untitled";
+    static boolean all = false;
+    static String urlTemplate = null;
+    static File rootFile = new File("")
+        .getAbsoluteFile();
+    static RepositoryImpl repository;
+    static String root;
+
+    /**
+     * Main entry. See -help for options.
+     * 
+     * @param args
+     * @throws Exception
+     */
+    public static void main(String args[]) throws Exception {
+        System.err.println("Bundle Indexer | v2.2");
+        System.err.println("(c) 2007 OSGi, All Rights Reserved");
+
+        Set resources = new HashSet();
+        root = rootFile.toURL().toString();
+        repository = new RepositoryImpl(rootFile.toURL());
+
+        for (int i = 0; i < args.length; i++) {
             try {
-				if (args[i].startsWith("-n")) {
+                if (args[i].startsWith("-n")) {
                     name = args[++i];
                 }
-                else
-					if (args[i].startsWith("-r")) {
-						repositoryFileName = args[++i];
-						repository = new RepositoryImpl(new File(
-								repositoryFileName).getAbsoluteFile().toURL());
-					}
-					else
-						if (args[i].startsWith("-q")) {
-                            quiet = true;
-                        }
-                        else
-							if (args[i].startsWith("-t")) {
-                                urlTemplate = args[++i];
-                            }
-                            else
-								if (args[i].startsWith("-l")) {
-									licenseURL = new URL(new File("").toURL(),
-											args[++i]);
-								}
-								else
-									if (args[i].startsWith("-help")) {
-										System.err
-												.println("bindex [-t \"%s\" symbolic name \"%v\" version \"%f\" filename \"%p\" dirpath ] [ -r repository.(xml|zip) ] [-help] [-l file:license.html ] [-quiet] [-all] <jar file>*");
-									}
-									else
-									    if (args[i].startsWith("-a")) {
-                                            all = true;
-                                        }
-                                        else {
-	    									recurse(resources, new File(args[i]));
-		    							}
-			}
-			catch (Exception e) {
-				System.err.println("Error in " + args[i] + " : " +
-						e.getMessage());
-				e.printStackTrace();
-			}
-        }
-
-		List sorted = new ArrayList(resources);
-		Collections.sort(sorted, new Comparator() {
-			public int compare(Object r1, Object r2) {
-				String s1 = getName((ResourceImpl) r1);
-				String s2 = getName((ResourceImpl) r2);
-				return s1.compareTo(s2);
-			}
-		});
-
-		Tag tag = doIndex(sorted);
-		if (repositoryFileName != null) {
-			ByteArrayOutputStream out = new ByteArrayOutputStream();
-			PrintWriter pw = new PrintWriter(new OutputStreamWriter(out,
-					"UTF-8"));
-
-			pw.println("<?xml version='1.0' encoding='utf-8'?>");
-			pw
-					.println("<?xml-stylesheet type='text/xsl' href='http://www2.osgi.org/www/obr2html.xsl'?>");
-
-			tag.print(0, pw);
-			pw.close();
-			byte buffer[] = out.toByteArray();
-			String name = "repository.xml";
-			FileOutputStream fout = new FileOutputStream(repositoryFileName);
-
-			if (repositoryFileName.endsWith(".zip")) {
-				ZipOutputStream zip = new ZipOutputStream(fout);
-				CRC32 checksum = new CRC32();
-				checksum.update(buffer);
-				ZipEntry ze = new ZipEntry(name);
-				ze.setSize(buffer.length);
-				ze.setCrc(checksum.getValue());
-				zip.putNextEntry(ze);
-				zip.write(buffer, 0, buffer.length);
-				zip.closeEntry();
-				zip.close();
-			}
-			else {
-				fout.write(buffer);
-			}
-			fout.close();
-		}
-
-		if (!quiet) {
-			PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
-			pw.println("<?xml version='1.0' encoding='utf-8'?>");
-			pw
-					.println("<?xml-stylesheet type='text/xsl' href='http://www2.osgi.org/www/obr2html.xsl'?>");
-			tag.print(0, pw);
-			pw.close();
-		}
-	}
-
-	static String getName(ResourceImpl impl) {
-		String s = impl.getSymbolicName();
-		if (s != null) {
+                else if (args[i].startsWith("-r")) {
+                    repositoryFileName = args[++i];
+                    repository = new RepositoryImpl(new File(
+                        repositoryFileName).getAbsoluteFile().toURL());
+                }
+                else if (args[i].startsWith("-q")) {
+                    quiet = true;
+                }
+                else if (args[i].startsWith("-t")) {
+                    urlTemplate = args[++i];
+                }
+                else if (args[i].startsWith("-l")) {
+                    licenseURL = new URL(new File("").toURL(),
+                        args[++i]);
+                }
+                else if (args[i].startsWith("-help")) {
+                    System.err
+                        .println("bindex [-t \"%s\" symbolic name \"%v\" version \"%f\" filename \"%p\" dirpath ] [ -r repository.(xml|zip) ] [-help] [-l file:license.html ] [-quiet] [-all] <jar file>*");
+                }
+                else if (args[i].startsWith("-a")) {
+                    all = true;
+                }
+                else {
+                    recurse(resources, new File(args[i]));
+                }
+            }
+            catch (Exception e) {
+                System.err.println("Error in " + args[i] + " : " +
+                    e.getMessage());
+                e.printStackTrace();
+            }
+        }
+
+        List sorted = new ArrayList(resources);
+        Collections.sort(sorted, new Comparator() {
+            public int compare(Object r1, Object r2) {
+                String s1 = getName((ResourceImpl) r1);
+                String s2 = getName((ResourceImpl) r2);
+                return s1.compareTo(s2);
+            }
+        });
+
+        Tag tag = doIndex(sorted);
+        if (repositoryFileName != null) {
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            PrintWriter pw = new PrintWriter(new OutputStreamWriter(out,
+                "UTF-8"));
+
+            pw.println("<?xml version='1.0' encoding='utf-8'?>");
+            pw
+                .println("<?xml-stylesheet type='text/xsl' href='http://www2.osgi.org/www/obr2html.xsl'?>");
+
+            tag.print(0, pw);
+            pw.close();
+            byte buffer[] = out.toByteArray();
+            String name = "repository.xml";
+            FileOutputStream fout = new FileOutputStream(repositoryFileName);
+
+            if (repositoryFileName.endsWith(".zip")) {
+                ZipOutputStream zip = new ZipOutputStream(fout);
+                CRC32 checksum = new CRC32();
+                checksum.update(buffer);
+                ZipEntry ze = new ZipEntry(name);
+                ze.setSize(buffer.length);
+                ze.setCrc(checksum.getValue());
+                zip.putNextEntry(ze);
+                zip.write(buffer, 0, buffer.length);
+                zip.closeEntry();
+                zip.close();
+            }
+            else {
+                fout.write(buffer);
+            }
+            fout.close();
+        }
+
+        if (!quiet) {
+            PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
+            pw.println("<?xml version='1.0' encoding='utf-8'?>");
+            pw
+                .println("<?xml-stylesheet type='text/xsl' href='http://www2.osgi.org/www/obr2html.xsl'?>");
+            tag.print(0, pw);
+            pw.close();
+        }
+    }
+
+    static String getName(ResourceImpl impl) {
+        String s = impl.getSymbolicName();
+        if (s != null) {
             return s;
         }
         else {
-			return "no-symbolic-name";
-		}
-	}
-
-	static void recurse(Set resources, File path) throws Exception {
-		if (path.isDirectory()) {
-			String list[] = path.list();
-			for (int i = 0; i < list.length; i++) {
-				recurse(resources, new File(path, list[i]));
-			}
-		}
-		else {
-		    if (path.getName().equals("repository.xml") || path.getName().equals(new File(repositoryFileName).getName())) {
-		        // do not index our repository.xml, nor the file we are working on now.
-		        return;
-		    }
-			if (path.getName().endsWith(".jar")) {
-				BundleInfo info = new BundleInfo(repository, path);
-				ResourceImpl resource = info.build();
-				if (urlTemplate != null) {
-					doTemplate(path, resource);
-				}
+            return "no-symbolic-name";
+        }
+    }
+
+    static void recurse(Set resources, File path) throws Exception {
+        if (path.isDirectory()) {
+            String list[] = path.list();
+            for (int i = 0; i < list.length; i++) {
+                recurse(resources, new File(path, list[i]));
+            }
+        }
+        else {
+            if (path.getName().equals("repository.xml") || path.getName().equals(new File(repositoryFileName).getName())) {
+                // do not index our repository.xml, nor the file we are working on now.
+                return;
+            }
+            if (path.getName().endsWith(".jar")) {
+                BundleInfo info = new BundleInfo(repository, path);
+                ResourceImpl resource = info.build();
+                if (urlTemplate != null) {
+                    doTemplate(path, resource);
+                }
                 else {
                     resource.setURL(path.toURL());
                 }
 
-				resources.add(resource);
-			}
-			else {
-			    // this is some other resource, we might want to include it.
-			    if (all) {
-			        resources.add(new ResourceImpl(repository, path.toURL()));
-			    }
-			}
-		}
-	}
-
-	static void doTemplate(File path, ResourceImpl resource)
-			throws MalformedURLException {
-		String dir = path.getAbsoluteFile().getParentFile().getAbsoluteFile()
-				.toURL().toString();
-		if (dir.endsWith("/")) {
+                resources.add(resource);
+            }
+            else {
+                // this is some other resource, we might want to include it.
+                if (all) {
+                    ResourceMetaData metadata = ResourceMetaData.getArtifactMetaData(path.getName());
+                    ResourceImpl impl = new ResourceImpl(repository, metadata.getSymbolicName(), new VersionRange(metadata.getVersion()));
+                    impl.setURL(path.toURL());
+                    resources.add(impl);
+                }
+            }
+        }
+    }
+
+    static void doTemplate(File path, ResourceImpl resource)
+        throws MalformedURLException {
+        String dir = path.getAbsoluteFile().getParentFile().getAbsoluteFile()
+            .toURL().toString();
+        if (dir.endsWith("/")) {
             dir = dir.substring(0, dir.length() - 1);
         }
 
-		if (dir.startsWith(root)) {
+        if (dir.startsWith(root)) {
             dir = dir.substring(root.length());
         }
 
-		String url = urlTemplate.replaceAll("%v", "" + resource.getVersion());
-		url = url.replaceAll("%s", resource.getSymbolicName());
-		url = url.replaceAll("%f", path.getName());
-		url = url.replaceAll("%p", dir);
-		resource.setURL(new URL(url));
-	}
-
-	/**
-	 * Create the repository index
-	 *
-	 * @param resources Set of resources
-	 * @param collected The output zip file
-	 * @throws java.io.IOException
-	 */
-	static Tag doIndex(Collection resources) throws IOException {
-		Tag repository = new Tag("repository");
-		repository.addAttribute("lastmodified", new Date());
-		repository.addAttribute("name", name);
-
-		for (Iterator i = resources.iterator(); i.hasNext();) {
-			ResourceImpl resource = (ResourceImpl) i.next();
-			repository.addContent(resource.toXML());
-		}
-		return repository;
-	}
-
-	/**
-	 * Add the resource to the ZIP file, calculating the CRC etc.
-	 *
-	 * @param zip The output ZIP file
-	 * @param name The name of the resource
-	 * @param actual The contents stream
-	 * @throws java.io.IOException
-	 */
-	static void addToZip(ZipOutputStream zip, String name, InputStream actual)
-			throws IOException {
-		byte buffer[];
-		buffer = readAll(actual, 0);
-		actual.close();
-		CRC32 checksum = new CRC32();
-		checksum.update(buffer);
-		ZipEntry ze = new ZipEntry(name);
-		ze.setSize(buffer.length);
-		ze.setCrc(checksum.getValue());
-		zip.putNextEntry(ze);
-		zip.write(buffer, 0, buffer.length);
-		zip.closeEntry();
-	}
-
-	/**
-	 * Read a complete stream till EOF. This method will parse the input stream
-	 * until a -1 is discovered.
-	 *
-	 * The method is recursive. It keeps on calling a higher level routine until
-	 * EOF. Only then is the result buffer calculated.
-	 */
-	static byte[] readAll(InputStream in, int offset) throws IOException {
-		byte temp[] = new byte[4096];
-		byte result[];
-		int size = in.read(temp, 0, temp.length);
-		if (size <= 0) {
+        String url = urlTemplate.replaceAll("%v", "" + resource.getVersion());
+        url = url.replaceAll("%s", resource.getSymbolicName());
+        url = url.replaceAll("%f", path.getName());
+        url = url.replaceAll("%p", dir);
+        resource.setURL(new URL(url));
+    }
+
+    /**
+     * Create the repository index
+     * 
+     * @param resources
+     *            Set of resources
+     * @param collected
+     *            The output zip file
+     * @throws java.io.IOException
+     */
+    static Tag doIndex(Collection resources) throws IOException {
+        Tag repository = new Tag("repository");
+        repository.addAttribute("lastmodified", new Date());
+        repository.addAttribute("name", name);
+
+        for (Iterator i = resources.iterator(); i.hasNext();) {
+            ResourceImpl resource = (ResourceImpl) i.next();
+            repository.addContent(resource.toXML());
+        }
+        return repository;
+    }
+
+    /**
+     * Add the resource to the ZIP file, calculating the CRC etc.
+     * 
+     * @param zip
+     *            The output ZIP file
+     * @param name
+     *            The name of the resource
+     * @param actual
+     *            The contents stream
+     * @throws java.io.IOException
+     */
+    static void addToZip(ZipOutputStream zip, String name, InputStream actual)
+        throws IOException {
+        byte buffer[];
+        buffer = readAll(actual, 0);
+        actual.close();
+        CRC32 checksum = new CRC32();
+        checksum.update(buffer);
+        ZipEntry ze = new ZipEntry(name);
+        ze.setSize(buffer.length);
+        ze.setCrc(checksum.getValue());
+        zip.putNextEntry(ze);
+        zip.write(buffer, 0, buffer.length);
+        zip.closeEntry();
+    }
+
+    /**
+     * Read a complete stream till EOF. This method will parse the input stream until a -1 is discovered.
+     * 
+     * The method is recursive. It keeps on calling a higher level routine until EOF. Only then is the result buffer
+     * calculated.
+     */
+    static byte[] readAll(InputStream in, int offset) throws IOException {
+        byte temp[] = new byte[4096];
+        byte result[];
+        int size = in.read(temp, 0, temp.length);
+        if (size <= 0) {
             return new byte[offset];
         }
-		//
-		// We have a positive result, copy it
-		// to the right offset.
-		//
-		result = readAll(in, offset + size);
-		System.arraycopy(temp, 0, result, offset, size);
-		return result;
-	}
+        //
+        // We have a positive result, copy it
+        // to the right offset.
+        //
+        result = readAll(in, offset + size);
+        System.arraycopy(temp, 0, result, offset, size);
+        return result;
+    }
 
-}
\ No newline at end of file
+}

Modified: ace/trunk/org.apache.ace.obr/src/org/osgi/impl/bundle/obr/resource/ResourceImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.obr/src/org/osgi/impl/bundle/obr/resource/ResourceImpl.java?rev=1496498&r1=1496497&r2=1496498&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.obr/src/org/osgi/impl/bundle/obr/resource/ResourceImpl.java (original)
+++ ace/trunk/org.apache.ace.obr/src/org/osgi/impl/bundle/obr/resource/ResourceImpl.java Tue Jun 25 14:45:34 2013
@@ -26,359 +26,356 @@ 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;
-	}
+    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;
+    }
 
     public ResourceImpl(RepositoryImpl impl, URL url) {
         this.repository = impl;
         setURL(url);
     }
-    
-	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 );
-		if (urlString.endsWith(".jar")) {
-		    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;
-	}
 
-	@Override
+    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;
+    }
+
+    @Override
     public String toString() {
-		return symbolicName + "-" + version;
-	}
+        return symbolicName + "-" + version;
+    }
+
+    public long getSize() {
+        return size;
+    }
 
-	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 void setSize(long size) {
+        this.size = size;
+        map.put(SIZE, new Long(size));
+    }
+
+    public Collection getRequirementList() {
+        return requirements;
+    }
+
+    public Collection getCapabilityList() {
+        return capabilities;
+    }
 
-	@Override
+    @Override
     public int hashCode() {
-	    if (url.toExternalForm().endsWith(".jar")) {
-	        return symbolicName.hashCode() ^ version.hashCode();
-	    }
-	    else {
-	        return url.hashCode();
-	    }
-	}
+        if (url.toExternalForm().endsWith(".jar")) {
+            return symbolicName.hashCode() ^ version.hashCode();
+        }
+        else {
+            return url.hashCode();
+        }
+    }
 
-	@Override
+    @Override
     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;
-	}
+        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;
+    }
 
 }

Modified: ace/trunk/org.apache.ace.obr/storage.bnd
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.obr/storage.bnd?rev=1496498&r1=1496497&r2=1496498&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.obr/storage.bnd (original)
+++ ace/trunk/org.apache.ace.obr/storage.bnd Tue Jun 25 14:45:34 2013
@@ -1,5 +1,6 @@
 Private-Package: org.apache.ace.obr.storage.file,\
-	org.apache.ace.obr.storage.file.constants
+	org.apache.ace.obr.storage.file.constants,\
+	org.apache.ace.obr.metadata.util
 Bundle-Activator: org.apache.ace.obr.storage.file.Activator
 Export-Package: org.apache.ace.obr.storage
 Bundle-Version: 1.0.0

Added: ace/trunk/org.apache.ace.obr/test/org/apache/ace/obr/metadata/util/ResourceMetaDataTest.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.obr/test/org/apache/ace/obr/metadata/util/ResourceMetaDataTest.java?rev=1496498&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.obr/test/org/apache/ace/obr/metadata/util/ResourceMetaDataTest.java (added)
+++ ace/trunk/org.apache.ace.obr/test/org/apache/ace/obr/metadata/util/ResourceMetaDataTest.java Tue Jun 25 14:45:34 2013
@@ -0,0 +1,66 @@
+/*
+ * 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.ace.obr.metadata.util;
+
+import static org.apache.ace.test.utils.TestUtils.UNIT;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.jar.Attributes;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+
+import org.osgi.framework.Constants;
+import org.testng.annotations.Test;
+
+public class ResourceMetaDataTest {
+
+    @Test(groups = { UNIT })
+    public void checkArtifactMetadataGeneration() throws Exception {
+        ResourceMetaData data = ResourceMetaData.getArtifactMetaData("foo.bar-1.0.3.xml");
+        assert "foo.bar".equals(data.getSymbolicName()) : "Generated symbolic name should be 'foo.bar', was " + data.getSymbolicName();
+        assert "1.0.3".equals(data.getVersion()) : "Generated version should be '1.0.3', was " + data.getVersion();
+        assert "xml".equals(data.getExtension()) : "Extension should be 'xml', was " + data.getExtension();
+    }
+
+    @Test(groups = { UNIT })
+    public void checkBundleMetadataGeneration() throws Exception {
+        ResourceMetaData data = ResourceMetaData.getBundleMetaData(createBundle("foo.bar", "1.0.3"));
+        assert "foo.bar".equals(data.getSymbolicName()) : "Generated symbolic name should be 'foo.bar', was " + data.getSymbolicName();
+        assert "1.0.3".equals(data.getVersion()) : "Generated version should be '1.0.3', was " + data.getVersion();
+        assert "jar".equals(data.getExtension()) : "Extension should be 'xml', was " + data.getExtension();
+    }
+
+    private File createBundle(String symbolicName, String version) throws IOException {
+        File tmpFile = File.createTempFile("tmpbundle-", "jar");
+        tmpFile.deleteOnExit();
+        Manifest manifest = new Manifest();
+        manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
+        if (symbolicName != null) {
+            manifest.getMainAttributes().putValue(Constants.BUNDLE_SYMBOLICNAME, symbolicName);
+        }
+        if (version != null) {
+            manifest.getMainAttributes().putValue(Constants.BUNDLE_VERSION, version);
+        }
+        JarOutputStream target = new JarOutputStream(new FileOutputStream(tmpFile), manifest);
+        target.close();
+        return tmpFile;
+    }
+}

Modified: ace/trunk/org.apache.ace.obr/test/org/apache/ace/obr/storage/file/BundleFileStoreTest.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.obr/test/org/apache/ace/obr/storage/file/BundleFileStoreTest.java?rev=1496498&r1=1496497&r2=1496498&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.obr/test/org/apache/ace/obr/storage/file/BundleFileStoreTest.java (original)
+++ ace/trunk/org.apache.ace.obr/test/org/apache/ace/obr/storage/file/BundleFileStoreTest.java Tue Jun 25 14:45:34 2013
@@ -34,12 +34,10 @@ import java.util.jar.JarOutputStream;
 import java.util.jar.Manifest;
 
 import org.apache.ace.obr.metadata.MetadataGenerator;
-import org.apache.ace.obr.storage.file.BundleFileStore.ResourceMetaData;
 import org.apache.ace.obr.storage.file.constants.OBRFileStoreConstants;
 import org.apache.ace.test.utils.FileUtils;
 import org.apache.ace.test.utils.TestUtils;
 import org.osgi.framework.Constants;
-import org.osgi.framework.Version;
 import org.osgi.service.cm.ConfigurationException;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
@@ -247,7 +245,7 @@ public class BundleFileStoreTest {
     public void putBundle() throws Exception {
         File bundle = createTmpResource("foo.bar", "1.0.0");
         String filePath = m_bundleStore.put(new FileInputStream(bundle), null);
-        assert filePath.equals("foo/bar/foo.bar-1.0.0.jar");
+        assert filePath.equals("foo/bar/foo.bar-1.0.0.jar") : "Path should be 'foo/bar/foo.bar-1.0.0.jar', was " + filePath;
         File file = new File(m_directory, filePath);
         assert file.exists();
     }
@@ -255,7 +253,7 @@ public class BundleFileStoreTest {
     @Test(groups = { UNIT })
     public void putBundleDuplicate() throws Exception {
         File bundle = createTmpResource("foo.bar", "1.0.0");
-        m_bundleStore.put(new FileInputStream(bundle), null);
+        String filePath = m_bundleStore.put(new FileInputStream(bundle), null);
         String filePath2 = m_bundleStore.put(new FileInputStream(bundle), null);
         assert filePath2 == null;
     }
@@ -264,7 +262,7 @@ public class BundleFileStoreTest {
     public void putBundleFail() throws Exception {
         File bundle = createTmpResource(null, "1.0.0");
         String filePath = m_bundleStore.put(new FileInputStream(bundle), null);
-        assert filePath.equals("foo/bar/foo.bar-1.0.0.jar");
+        assert filePath.equals("foo/bar/foo.bar-1.0.0.jar") : "Path should be 'foo/bar/foo.bar-1.0.0.jar', was " + filePath;
         File file = new File(m_directory, filePath);
         assert file.exists();
     }
@@ -383,19 +381,6 @@ public class BundleFileStoreTest {
         assert !m_metadata.generated() : "After changing the directory, the metadata should not be regenerated.";
     }
     
-    @Test(groups = { UNIT })
-    public void checkArtifactMetadataGeneration() {
-    	ResourceMetaData data = m_bundleStore.getArtifactMetaData("resource-1.0.3.xml");
-		assert "resource".equals(data.getSymbolicName()) : "Generated symbolic name should be 'resource', was " + data.getSymbolicName();
-		assert "1.0.3".equals(data.getVersion()) : "Generated version should be '1.0.3', was " + data.getVersion();
-		assert "xml".equals(data.getExtension()) : "Extension should be 'xml', was " + data.getExtension();
-
-		data = m_bundleStore.getArtifactMetaData("maven-artifact-2.3.5-SNAPSHOT.jar");
-		assert "maven-artifact".equals(data.getSymbolicName()) : "Generated symbolic name should be 'maven-artifact', was " + data.getSymbolicName();
-		assert "2.3.5-SNAPSHOT".equals(data.getVersion()) : "Generated version should be '2.3.5-SNAPSHOT', was " + data.getVersion();
-		assert "jar".equals(data.getExtension()) : "Extension should be 'jar', was " + data.getExtension();
-    }
-
     private File createTmpResource(String symbolicName, String version) throws IOException {
         File tmpFile = File.createTempFile("tmpbundle-", "jar");
         tmpFile.deleteOnExit();