You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2010/08/13 13:38:02 UTC

svn commit: r985161 - in /sling/trunk/installer: ./ osgi/installer/src/main/java/org/apache/sling/osgi/installer/ osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/ osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks...

Author: cziegeler
Date: Fri Aug 13 11:38:01 2010
New Revision: 985161

URL: http://svn.apache.org/viewvc?rev=985161&view=rev
Log:
SLING-1560 : Merge installer impl and thread, make registered resources comparable

Removed:
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiInstallerImpl.java
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/RegisteredResourceComparator.java
Modified:
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/InstallableResource.java
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/Activator.java
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/Logger.java
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiInstallerTask.java
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiInstallerThread.java
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/PersistentResourceList.java
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/RegisteredResource.java
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/RegisteredResourceImpl.java
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/AbstractConfigTask.java
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/BundleStartTask.java
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/ConfigInstallTask.java
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/ConfigRemoveTask.java
    sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/LocalFileRegisteredResource.java
    sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/MockBundleResource.java
    sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/PersistentResourceListTest.java
    sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/RegisteredResourceComparatorTest.java
    sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/RegisteredResourceTest.java
    sling/trunk/installer/pom.xml

Modified: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/InstallableResource.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/InstallableResource.java?rev=985161&r1=985160&r2=985161&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/InstallableResource.java (original)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/InstallableResource.java Fri Aug 13 11:38:01 2010
@@ -94,7 +94,7 @@ public class InstallableResource {
             type = (type != null ? type : InstallableResource.TYPE_CONFIG);
         }
         // TODO - compute digest if digest is null - for now we throw
-        if ( digest == null ) {
+        if ( digest == null || digest.length() == 0 ) {
             throw new IllegalArgumentException("digest must not be null");
         }
 

Modified: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/Activator.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/Activator.java?rev=985161&r1=985160&r2=985161&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/Activator.java (original)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/Activator.java Fri Aug 13 11:38:01 2010
@@ -24,15 +24,15 @@ import org.apache.sling.osgi.installer.O
 import org.apache.sling.osgi.installer.OsgiInstallerStatistics;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleEvent;
-import org.osgi.framework.BundleListener;
 import org.osgi.framework.Constants;
-import org.osgi.framework.FrameworkEvent;
-import org.osgi.framework.FrameworkListener;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.util.tracker.ServiceTracker;
 
-public class Activator implements BundleActivator, FrameworkListener, BundleListener {
+/**
+ * The activator sets up the logging and registers the
+ * OSGi installer service.
+ */
+public class Activator implements BundleActivator {
 
     /** Interface of the log service */
     private static String LOG_SERVICE_NAME = "org.osgi.service.log.LogService";
@@ -40,75 +40,64 @@ public class Activator implements Bundle
     /** Vendor of all registered services. */
     private static final String VENDOR = "The Apache Software Foundation";
 
-    private OsgiInstallerImpl osgiControllerService;
+    private OsgiInstallerThread osgiControllerService;
     private ServiceRegistration osgiControllerServiceReg;
 
     /** Tracker for the log service. */
     private ServiceTracker logServiceTracker;
 
-    private static long eventsCount;
-
     /**
      * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
      */
     public void start(final BundleContext context) throws Exception {
-        // listen to framework and bundle events
-        context.addFrameworkListener(this);
-        context.addBundleListener(this);
-
+        // setup logging
         this.logServiceTracker = new ServiceTracker(context, LOG_SERVICE_NAME, null);
         this.logServiceTracker.open();
         Logger.setTracker(this.logServiceTracker);
-        // register OsgiController service
-        {
-            final Hashtable<String, String> props = new Hashtable<String, String>();
-            props.put(Constants.SERVICE_DESCRIPTION, "Apache Sling Install Controller Service");
-            props.put(Constants.SERVICE_VENDOR, VENDOR);
-
-            this.osgiControllerService = new OsgiInstallerImpl(context);
-            final String [] serviceInterfaces = {
-                    OsgiInstaller.class.getName(),
-                    OsgiInstallerStatistics.class.getName()
-            };
-            osgiControllerServiceReg = context.registerService(serviceInterfaces, osgiControllerService, props);
-        }
+
+        // register osgi installer service
+        final Hashtable<String, String> props = new Hashtable<String, String>();
+        props.put(Constants.SERVICE_DESCRIPTION, "Apache Sling Install Controller Service");
+        props.put(Constants.SERVICE_VENDOR, VENDOR);
+
+        this.osgiControllerService = new OsgiInstallerThread(context);
+        this.osgiControllerService.setDaemon(true);
+        this.osgiControllerService.start();
+        final String [] serviceInterfaces = {
+                OsgiInstaller.class.getName(),
+                OsgiInstallerStatistics.class.getName()
+        };
+        osgiControllerServiceReg = context.registerService(serviceInterfaces, osgiControllerService, props);
     }
 
     /**
      * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
      */
     public void stop(BundleContext context) {
-    	context.removeBundleListener(this);
-    	context.removeFrameworkListener(this);
-
+        // stop osgi installer service
         if ( this.osgiControllerService != null ) {
             this.osgiControllerService.deactivate();
+            Logger.logInfo("Waiting for installer thread to stop");
+            try {
+                this.osgiControllerService.join();
+            } catch (InterruptedException e) {
+                // we simply ignore this
+            }
+
+            Logger.logWarn(OsgiInstaller.class.getName()
+                    + " service deactivated - this warning can be ignored if system is shutting down");
             this.osgiControllerService = null;
         }
+        // unregister service
         if ( this.osgiControllerServiceReg != null ) {
             this.osgiControllerServiceReg.unregister();
             this.osgiControllerServiceReg = null;
         }
+        // stop logging
         Logger.setTracker(null);
     	if ( this.logServiceTracker != null ) {
     	    this.logServiceTracker.close();
     	    this.logServiceTracker = null;
     	}
     }
-
-    /** Used for tasks that wait for a framework or bundle event before retrying their operations */
-    public static long getTotalEventsCount() {
-        return eventsCount;
-    }
-
-    /**
-     * @see org.osgi.framework.FrameworkListener#frameworkEvent(org.osgi.framework.FrameworkEvent)
-     */
-    public void frameworkEvent(final FrameworkEvent event) {
-        eventsCount++;
-    }
-
-    public void bundleChanged(final BundleEvent event) {
-        eventsCount++;
-    }
 }

Modified: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/Logger.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/Logger.java?rev=985161&r1=985160&r2=985161&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/Logger.java (original)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/Logger.java Fri Aug 13 11:38:01 2010
@@ -23,7 +23,10 @@ import org.osgi.util.tracker.ServiceTrac
 
 
 /**
- * Logger support
+ * Logger support.
+ * If a log service is available, log messages go
+ * to the log service - if no log service is
+ * available, log messages are ignored.
  */
 public class Logger {
 

Modified: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiInstallerTask.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiInstallerTask.java?rev=985161&r1=985160&r2=985161&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiInstallerTask.java (original)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiInstallerTask.java Fri Aug 13 11:38:01 2010
@@ -19,7 +19,7 @@
 package org.apache.sling.osgi.installer.impl;
 
 
-/** Base class for tasks that can be executed by the {@link OsgiInstallerImpl} */
+/** Base class for tasks that can be executed by the {@link OsgiInstallerThread} */
 public abstract class OsgiInstallerTask implements Comparable<OsgiInstallerTask> {
 
     public enum Result {
@@ -41,11 +41,6 @@ public abstract class OsgiInstallerTask 
 		return getSortKey().compareTo(o.getSortKey());
 	}
 
-	/** Is it worth executing this task now? */
-	public boolean isExecutable(OsgiInstallerContext ctx) throws Exception {
-	    return true;
-	}
-
 	@Override
 	public final boolean equals(Object o) {
 		if(o instanceof OsgiInstallerTask) {

Modified: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiInstallerThread.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiInstallerThread.java?rev=985161&r1=985160&r2=985161&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiInstallerThread.java (original)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiInstallerThread.java Fri Aug 13 11:38:01 2010
@@ -37,6 +37,8 @@ import org.apache.sling.osgi.installer.i
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleEvent;
 import org.osgi.framework.BundleListener;
+import org.osgi.framework.FrameworkEvent;
+import org.osgi.framework.FrameworkListener;
 
 /** Worker thread where all OSGi tasks are executed.
  *  Runs cycles where the list of RegisteredResources is examined,
@@ -46,9 +48,10 @@ import org.osgi.framework.BundleListener
  *  that are updated or removed during a cycle, and merged with
  *  the main list at the end of the cycle.
  */
-class OsgiInstallerThread
+public class OsgiInstallerThread
     extends Thread
-    implements BundleListener, OsgiInstallerStatistics, OsgiInstallerContext {
+    implements BundleListener, FrameworkListener,
+               OsgiInstaller, OsgiInstallerStatistics, OsgiInstallerContext {
 
     private final BundleContext ctx;
     private final List<RegisteredResource> newResources = new LinkedList<RegisteredResource>();
@@ -70,20 +73,24 @@ class OsgiInstallerThread
     private long [] counters = new long[COUNTERS_SIZE];
 
     OsgiInstallerThread(final BundleContext ctx) {
+        this.ctx = ctx;
+        // listen to framework and bundle events
+        this.ctx.addFrameworkListener(this);
+        this.ctx.addBundleListener(this);
         this.configTaskCreator = new ConfigTaskCreator(ctx);
         this.bundleTaskCreator = new BundleTaskCreator(ctx);
         setName(getClass().getSimpleName());
-        this.ctx = ctx;
         final File f = ctx.getDataFile("RegisteredResourceList.ser");
         persistentList = new PersistentResourceList(ctx, f);
         registeredResources = persistentList.getData();
     }
 
     void deactivate() {
+        this.active = false;
         this.configTaskCreator.deactivate();
         this.bundleTaskCreator.deactivate();
         ctx.removeBundleListener(this);
-        active = false;
+        ctx.removeFrameworkListener(this);
         synchronized (newResources) {
             newResources.notify();
         }
@@ -106,9 +113,7 @@ class OsgiInstallerThread
 
     @Override
     public void run() {
-        ctx.addBundleListener(this);
-
-        while(active) {
+        while (active) {
             try {
             	mergeNewResources();
             	computeTasks();
@@ -162,8 +167,20 @@ class OsgiInstallerThread
         }
     }
 
-    /** Register a resource for removal, or ignore if we don't have that URL */
-    void removeResource(String id, final String scheme) {
+    private void checkScheme(final String scheme) {
+        if ( scheme == null || scheme.length() == 0 ) {
+            throw new IllegalArgumentException("Scheme required");
+        }
+        if ( scheme.indexOf(':') != -1 ) {
+            throw new IllegalArgumentException("Scheme must not contain a colon");
+        }
+    }
+
+    /**
+     * @see org.apache.sling.osgi.installer.OsgiInstaller#removeResource(java.lang.String, java.lang.String)
+     */
+    public void removeResource(final String scheme, final String id) {
+        checkScheme(scheme);
         final String url = scheme + ':' + id;
 		// Will mark all resources which have r's URL as uninstallable
         Logger.logDebug("Adding URL " + url + " to urlsToRemove");
@@ -174,8 +191,11 @@ class OsgiInstallerThread
         }
     }
 
-    /** Register a single new resource, will be processed on the next cycle */
-    void addNewResource(final InstallableResource r, final String scheme) {
+    /**
+     * @see org.apache.sling.osgi.installer.OsgiInstaller#addResource(java.lang.String, org.apache.sling.osgi.installer.InstallableResource)
+     */
+    public void addResource(final String scheme, final InstallableResource r) {
+        checkScheme(scheme);
         RegisteredResource rr = null;
         try {
             rr = new RegisteredResourceImpl(ctx, r, scheme);
@@ -191,15 +211,16 @@ class OsgiInstallerThread
         }
     }
 
-    /** Register a number of new resources, and mark others having the same scheme as not installable.
-     *  Used with {@link OsgiInstaller.registerResources}
+    /**
+     * @see org.apache.sling.osgi.installer.OsgiInstaller#registerResources(java.lang.String, java.util.Collection)
      */
-    void addNewResources(Collection<InstallableResource> data, String urlScheme, BundleContext bundleContext) {
-        final SortedSet<RegisteredResource> toAdd = new TreeSet<RegisteredResource>(new RegisteredResourceComparator());
+    public void registerResources(final String scheme, final Collection<InstallableResource> data) {
+        checkScheme(scheme);
+        final SortedSet<RegisteredResource> toAdd = new TreeSet<RegisteredResource>();
         for(InstallableResource r : data) {
             RegisteredResource rr =  null;
             try {
-                rr = new RegisteredResourceImpl(ctx, r, urlScheme);
+                rr = new RegisteredResourceImpl(ctx, r, scheme);
             } catch(IOException ioe) {
                 Logger.logWarn("Cannot create RegisteredResource (resource will be ignored):" + r, ioe);
                 continue;
@@ -215,8 +236,8 @@ class OsgiInstallerThread
             }
             // Need to manage schemes separately: in case toAdd is empty we
             // want to mark all such resources as non-installable
-            Logger.logDebug("Adding to newResourcesSchemes: " + urlScheme);
-            newResourcesSchemes.add(urlScheme);
+            Logger.logDebug("Adding to newResourcesSchemes: " + scheme);
+            newResourcesSchemes.add(scheme);
             newResources.notify();
         }
     }
@@ -263,7 +284,7 @@ class OsgiInstallerThread
                 // new one which might have different attributes
                 if(t.contains(r)) {
                 	for(RegisteredResource rr : t) {
-                		if(t.comparator().compare(rr, r) == 0) {
+                		if(rr.compareTo(r) == 0) {
                 		    Logger.logDebug("Cleanup obsolete " + rr);
                 			rr.cleanup();
                 		}
@@ -301,24 +322,18 @@ class OsgiInstallerThread
 
     /** Factored out to use the exact same structure in tests */
     static SortedSet<RegisteredResource> createRegisteredResourcesEntry() {
-        return new TreeSet<RegisteredResource>(new RegisteredResourceComparator());
+        return new TreeSet<RegisteredResource>();
     }
 
 
     /** Compute OSGi tasks based on our resources, and add to supplied list of tasks */
     void computeTasks() throws Exception {
-        // Add tasks that were scheduled for next cycle and are executable now
-        final List<OsgiInstallerTask> toKeep = new ArrayList<OsgiInstallerTask>();
+        // Add tasks that were scheduled for next cycle
         synchronized (tasksForNextCycle) {
             for(OsgiInstallerTask t : tasksForNextCycle) {
-                if(t.isExecutable(this)) {
-                    tasks.add(t);
-                } else {
-                    toKeep.add(t);
-                }
+                tasks.add(t);
             }
             tasksForNextCycle.clear();
-            tasksForNextCycle.addAll(toKeep);
         }
 
         // Walk the list of entities, and create appropriate OSGi tasks for each group
@@ -405,11 +420,37 @@ class OsgiInstallerThread
     	}
     }
 
+    /**
+     * @see org.osgi.framework.BundleListener#bundleChanged(org.osgi.framework.BundleEvent)
+     */
     public void bundleChanged(BundleEvent e) {
+        synchronized (LOCK) {
+            eventsCount++;
+        }
     	final int t = e.getType();
     	if(t == BundleEvent.INSTALLED || t == BundleEvent.RESOLVED || t == BundleEvent.STARTED || t == BundleEvent.UPDATED) {
     	    Logger.logDebug("Received BundleEvent that might allow installed bundles to start, scheduling retries if any");
     		scheduleRetries();
     	}
     }
+
+    private static volatile long eventsCount;
+
+    private static final Object LOCK = new Object();
+
+    /** Used for tasks that wait for a framework or bundle event before retrying their operations */
+    public static long getTotalEventsCount() {
+        synchronized (LOCK) {
+            return eventsCount;
+        }
+    }
+
+    /**
+     * @see org.osgi.framework.FrameworkListener#frameworkEvent(org.osgi.framework.FrameworkEvent)
+     */
+    public void frameworkEvent(final FrameworkEvent event) {
+        synchronized (LOCK) {
+            eventsCount++;
+        }
+    }
 }
\ No newline at end of file

Modified: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/PersistentResourceList.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/PersistentResourceList.java?rev=985161&r1=985160&r2=985161&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/PersistentResourceList.java (original)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/PersistentResourceList.java Fri Aug 13 11:38:01 2010
@@ -56,15 +56,6 @@ class PersistentResourceList {
                 }
             }
         }
-        if ( restoredData != null ) {
-            for(final SortedSet<RegisteredResource> set : restoredData.values() ) {
-                for(final RegisteredResource rr : set) {
-                    if ( rr instanceof RegisteredResourceImpl ) {
-                        ((RegisteredResourceImpl)rr).init(bc);
-                    }
-                }
-            }
-        }
         data = restoredData != null ? restoredData : new HashMap<String, SortedSet<RegisteredResource>>();
     }
 

Modified: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/RegisteredResource.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/RegisteredResource.java?rev=985161&r1=985160&r2=985161&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/RegisteredResource.java (original)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/RegisteredResource.java Fri Aug 13 11:38:01 2010
@@ -20,6 +20,7 @@ package org.apache.sling.osgi.installer.
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.Serializable;
 import java.util.Dictionary;
 import java.util.Map;
 
@@ -30,7 +31,7 @@ import org.apache.sling.osgi.installer.O
  *  it locally to avoid holding up to classes or data from our
  *  clients, in case those disappear while we're installing stuff.
  */
-public interface RegisteredResource {
+public interface RegisteredResource extends Serializable, Comparable<RegisteredResource> {
 
 	String DIGEST_TYPE = "MD5";
     String ENTITY_JAR_PREFIX = "jar:";
@@ -90,7 +91,6 @@ public interface RegisteredResource {
 	boolean isInstallable();
 	void setInstallable(boolean installable);
 	String getUrlScheme();
-	long getSerialNumber();
 
 	/** Attributes include the bundle symbolic name, bundle version, etc. */
 	Map<String, Object> getAttributes();
@@ -101,4 +101,5 @@ public interface RegisteredResource {
      */
     String getEntityId();
 
+    long getSerialNumber();
 }

Modified: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/RegisteredResourceImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/RegisteredResourceImpl.java?rev=985161&r1=985160&r2=985161&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/RegisteredResourceImpl.java (original)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/RegisteredResourceImpl.java Fri Aug 13 11:38:01 2010
@@ -42,12 +42,15 @@ import org.apache.sling.osgi.installer.I
 import org.apache.sling.osgi.installer.impl.config.ConfigurationPid;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
+import org.osgi.framework.Version;
 
 /**
  * Implementation of the registered resource
  */
-public class RegisteredResourceImpl implements RegisteredResource, Serializable {
-    private static final long serialVersionUID = 2L;
+public class RegisteredResourceImpl
+    implements RegisteredResource, Serializable {
+
+    private static final long serialVersionUID = 3L;
     private final String id;
 	private final String url;
 	private final String urlScheme;
@@ -56,52 +59,37 @@ public class RegisteredResourceImpl impl
 	private final Dictionary<String, Object> dictionary;
 	private final Map<String, Object> attributes = new HashMap<String, Object>();
 	private boolean installable = true;
-	private final boolean hasDataFile;
+	private final File dataFile;
 	private final int priority;
     private final long serialNumber;
     private static long serialNumberCounter = System.currentTimeMillis();
 
     private final String resourceType;
 
-    private transient BundleContext bundleContext;
-
-	/** Create a RegisteredResource from given data. If the data's extension
-	 *  maps to a configuration and the data provides an input stream, it is
-	 *  converted to a Dictionary
+	/**
+	 * Create a RegisteredResource from given data.
+	 * As this data object is filled from an {@link InstallableResource}
+	 * we don't have to validate values - this has already been done
+	 * by the installable resource!
 	 */
 	public RegisteredResourceImpl(final BundleContext ctx,
 	        final InstallableResource input,
 	        final String scheme) throws IOException {
-	    this.bundleContext = ctx;
-        if ( scheme == null || scheme.length() == 0 ) {
-            throw new IllegalArgumentException("Scheme required");
-        }
-        if ( scheme.indexOf(':') != -1 ) {
-            throw new IllegalArgumentException("Scheme must not contain a colon");
-        }
         this.id = input.getId();
-		url = scheme + ':' + input.getId();
-		urlScheme = scheme;
-		resourceType = input.getType();
-		priority = input.getPriority();
-		serialNumber = getNextSerialNumber();
-
-        if(input.getDigest() == null || input.getDigest().length() == 0) {
-            throw new IllegalArgumentException("Missing digest: " + input);
-        }
+        this.urlScheme = scheme;
+		this.url = scheme + ':' + input.getId();
+		this.resourceType = input.getType();
+		this.priority = input.getPriority();
+        this.dictionary = copy(input.getDictionary());
+        this.digest = input.getDigest();
+		this.serialNumber = getNextSerialNumber();
 
 		if (resourceType.equals(InstallableResource.TYPE_BUNDLE)) {
 		    final InputStream is = input.getInputStream();
-            if (is == null) {
-                throw new IllegalArgumentException("InputStream is required for BUNDLE resource type: " + input);
-            }
             try {
-                dictionary = copy(input.getDictionary());
-                final File f = getDataFile();
-                Logger.logDebug("Copying data to local storage " + f.getAbsolutePath());
-                copyToLocalStorage(input.getInputStream(), f);
-                hasDataFile = true;
-                digest = input.getDigest();
+                this.dataFile = getDataFile(ctx);
+                Logger.logDebug("Copying data to local storage " + this.dataFile);
+                copyToLocalStorage(input.getInputStream());
                 setAttributesFromManifest();
                 final String name = (String)attributes.get(Constants.BUNDLE_SYMBOLICNAME);
                 if(name == null) {
@@ -114,22 +102,15 @@ public class RegisteredResourceImpl impl
                 is.close();
             }
 		} else if ( resourceType.equals(InstallableResource.TYPE_CONFIG)) {
-            hasDataFile = false;
+            this.dataFile = null;
             final ConfigurationPid pid = new ConfigurationPid(url);
             entity = ENTITY_CONFIG_PREFIX + pid.getCompositePid();
             attributes.put(CONFIG_PID_ATTRIBUTE, pid);
-            // config provided as a Dictionary
-            dictionary = copy(input.getDictionary());
-            digest = input.getDigest();
 		} else {
 		    throw new IOException("Unknown type " + resourceType);
 		}
 	}
 
-	public void init(final BundleContext bc) {
-	    this.bundleContext = bc;
-	}
-
     private static long getNextSerialNumber() {
         synchronized (RegisteredResourceImpl.class) {
             return serialNumberCounter++;
@@ -141,14 +122,13 @@ public class RegisteredResourceImpl impl
 	    return getClass().getSimpleName() + " " + url + ", digest=" + digest + ", serialNumber=" + serialNumber;
 	}
 
-	protected File getDataFile() {
+	protected File getDataFile(final BundleContext bundleContext) {
 		final String filename = getClass().getSimpleName() + "." + serialNumber;
-		return this.bundleContext.getDataFile(filename);
+		return bundleContext.getDataFile(filename);
 	}
 
 	public void cleanup() {
-	    final File dataFile = getDataFile();
-		if(dataFile.exists()) {
+	    if ( this.dataFile != null && this.dataFile.exists() ) {
 		    Logger.logDebug("Deleting local storage file "
 		                + dataFile.getAbsolutePath());
 			dataFile.delete();
@@ -160,11 +140,8 @@ public class RegisteredResourceImpl impl
 	}
 
 	public InputStream getInputStream() throws IOException {
-	    if(hasDataFile) {
-	        final File dataFile = getDataFile();
-	        if(dataFile.exists()) {
-	            return new BufferedInputStream(new FileInputStream(dataFile));
-	        }
+	    if (this.dataFile != null && this.dataFile.exists() ) {
+	        return new BufferedInputStream(new FileInputStream(this.dataFile));
 	    }
         return  null;
 	}
@@ -177,9 +154,16 @@ public class RegisteredResourceImpl impl
 		return digest;
 	}
 
+    /**
+     * @see org.apache.sling.osgi.installer.impl.RegisteredResource#getSerialNumber()
+     */
+    public long getSerialNumber() {
+        return this.serialNumber;
+    }
+
     /** Copy data to local storage */
-	private void copyToLocalStorage(InputStream data, File f) throws IOException {
-		final OutputStream os = new BufferedOutputStream(new FileOutputStream(f));
+	private void copyToLocalStorage(final InputStream data) throws IOException {
+		final OutputStream os = new BufferedOutputStream(new FileOutputStream(this.dataFile));
 		try {
 			final byte[] buffer = new byte[16384];
 			int count = 0;
@@ -296,7 +280,89 @@ public class RegisteredResourceImpl impl
         return priority;
     }
 
-    public long getSerialNumber() {
-        return serialNumber;
+    /**
+     * @see java.lang.Comparable#compareTo(java.lang.Object)
+     */
+    public int compareTo(final RegisteredResource b) {
+        return compare(this, b);
+    }
+
+    public static int compare(final RegisteredResource a, final RegisteredResource b) {
+        final boolean aBundle = a.getType().equals(InstallableResource.TYPE_BUNDLE);
+        final boolean bBundle = b.getType().equals(InstallableResource.TYPE_BUNDLE);
+
+        if (aBundle && bBundle) {
+            return compareBundles(a, b);
+        } else if (!aBundle && !bBundle){
+            return compareConfig(a, b);
+        } else if (aBundle) {
+            return 1;
+        } else {
+            return -1;
+        }
+    }
+
+    private static int compareBundles(final RegisteredResource a, final RegisteredResource b) {
+        boolean isSnapshot = false;
+        int result = 0;
+
+        // Order first by symbolic name
+        final String nameA = (String)a.getAttributes().get(Constants.BUNDLE_SYMBOLICNAME);
+        final String nameB = (String)b.getAttributes().get(Constants.BUNDLE_SYMBOLICNAME);
+        if(nameA != null && nameB != null) {
+            result = nameA.compareTo(nameB);
+        }
+
+        // Then by version
+        if(result == 0) {
+            final Version va = new Version((String)a.getAttributes().get(Constants.BUNDLE_VERSION));
+            final Version vb = new Version((String)b.getAttributes().get(Constants.BUNDLE_VERSION));
+            isSnapshot = va.toString().contains("SNAPSHOT");
+            // higher version has more priority, must come first so invert comparison
+            result = vb.compareTo(va);
+        }
+
+        // Then by priority, higher values first
+        if(result == 0) {
+            if(a.getPriority() < b.getPriority()) {
+                result = 1;
+            } else if(a.getPriority() > b.getPriority()) {
+                result = -1;
+            }
+        }
+
+        if(result == 0 && isSnapshot) {
+            // For snapshots, compare serial numbers so that snapshots registered
+            // later get priority
+            if(a.getSerialNumber() < b.getSerialNumber()) {
+                result = 1;
+            } else if(a.getSerialNumber() > b.getSerialNumber()) {
+                result = -1;
+            }
+        }
+
+        return result;
+    }
+
+    private static int compareConfig(final RegisteredResource a, final RegisteredResource b) {
+        int result = 0;
+
+        // First compare by pid
+        final ConfigurationPid pA = (ConfigurationPid)a.getAttributes().get(RegisteredResource.CONFIG_PID_ATTRIBUTE);
+        final ConfigurationPid pB = (ConfigurationPid)b.getAttributes().get(RegisteredResource.CONFIG_PID_ATTRIBUTE);
+        if(pA != null && pA.getCompositePid() != null && pB != null && pB.getCompositePid() != null) {
+            result = pA.getCompositePid().compareTo(pB.getCompositePid());
+        }
+
+        // Then by priority, higher values first
+        if(result == 0) {
+            if(a.getPriority() < b.getPriority()) {
+                result = 1;
+            } else if( a.getPriority() > b.getPriority()) {
+                result = -1;
+            }
+        }
+
+        return result;
     }
 }
\ No newline at end of file

Modified: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/AbstractConfigTask.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/AbstractConfigTask.java?rev=985161&r1=985160&r2=985161&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/AbstractConfigTask.java (original)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/AbstractConfigTask.java Fri Aug 13 11:38:01 2010
@@ -20,7 +20,6 @@ package org.apache.sling.osgi.installer.
 
 import java.io.IOException;
 
-import org.apache.sling.osgi.installer.impl.OsgiInstallerContext;
 import org.apache.sling.osgi.installer.impl.OsgiInstallerTask;
 import org.apache.sling.osgi.installer.impl.RegisteredResource;
 import org.apache.sling.osgi.installer.impl.config.ConfigurationPid;
@@ -35,12 +34,14 @@ abstract class AbstractConfigTask extend
     protected final ConfigurationPid pid;
     protected final RegisteredResource resource;
 
+    /** Tracker for the configuration admin. */
     private final ServiceTracker configAdminServiceTracker;
+
     AbstractConfigTask(final RegisteredResource r, final ServiceTracker configAdminServiceTracker) {
         this.configAdminServiceTracker = configAdminServiceTracker;
-        resource = r;
-        pid = (ConfigurationPid)r.getAttributes().get(RegisteredResource.CONFIG_PID_ATTRIBUTE);
-        if(pid == null) {
+        this.resource = r;
+        this.pid = (ConfigurationPid)r.getAttributes().get(RegisteredResource.CONFIG_PID_ATTRIBUTE);
+        if (this.pid == null) {
             throw new IllegalArgumentException("RegisteredResource does not have CONFIG_PID_ATTRIBUTE: " + r);
         }
     }
@@ -53,10 +54,10 @@ abstract class AbstractConfigTask extend
     }
 
 
-    protected Configuration getConfiguration(ConfigurationAdmin ca,
-            ConfigurationPid cp, boolean createIfNeeded, OsgiInstallerContext ocs)
-    throws IOException, InvalidSyntaxException
-    {
+    protected Configuration getConfiguration(final ConfigurationAdmin ca,
+            final ConfigurationPid cp,
+            final boolean createIfNeeded)
+    throws IOException, InvalidSyntaxException {
         Configuration result = null;
 
         if (cp.getFactoryPid() == null) {
@@ -83,9 +84,4 @@ abstract class AbstractConfigTask extend
     public String toString() {
         return getClass().getName() + ": " + resource;
     }
-
-    @Override
-    public boolean isExecutable(OsgiInstallerContext ctx) throws Exception {
-        return this.getConfigurationAdmin() != null;
-    }
 }

Modified: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/BundleStartTask.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/BundleStartTask.java?rev=985161&r1=985160&r2=985161&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/BundleStartTask.java (original)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/BundleStartTask.java Fri Aug 13 11:38:01 2010
@@ -20,11 +20,11 @@ package org.apache.sling.osgi.installer.
 
 import java.text.DecimalFormat;
 
-import org.apache.sling.osgi.installer.impl.Activator;
 import org.apache.sling.osgi.installer.impl.BundleTaskCreator;
 import org.apache.sling.osgi.installer.impl.Logger;
 import org.apache.sling.osgi.installer.impl.OsgiInstallerContext;
 import org.apache.sling.osgi.installer.impl.OsgiInstallerTask;
+import org.apache.sling.osgi.installer.impl.OsgiInstallerThread;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleException;
 
@@ -47,7 +47,7 @@ public class BundleStartTask extends Osg
 	public BundleStartTask(final long bundleId, final BundleTaskCreator btc) {
 		this.bundleId = bundleId;
 		this.creator = btc;
-		sortKey = BUNDLE_START_ORDER + new DecimalFormat("00000").format(bundleId);
+		this.sortKey = BUNDLE_START_ORDER + new DecimalFormat("00000").format(bundleId);
 	}
 
 	@Override
@@ -60,62 +60,56 @@ public class BundleStartTask extends Osg
 		return getClass().getSimpleName() + ": bundle " + bundleId;
 	}
 
-	public Result execute(OsgiInstallerContext ctx) {
-		final Bundle b = this.creator.getBundleContext().getBundle(bundleId);
-		boolean needToRetry = false;
-
-        if(bundleId == 0) {
+	/**
+	 * @see org.apache.sling.osgi.installer.impl.OsgiInstallerTask#execute(org.apache.sling.osgi.installer.impl.OsgiInstallerContext)
+	 */
+	public Result execute(final OsgiInstallerContext ctx) {
+	    // TODO : if bundle id is zero we should have created this task in the first place!
+        if (bundleId == 0) {
             Logger.logDebug("Bundle 0 is the framework bundle, ignoring request to start it");
             return Result.NOTHING;
         }
 
-		if(b == null) {
-		    Logger.logInfo("Cannot start bundle, id not found:" + bundleId);
+        // Do not execute this task if waiting for events
+        final long eventsCount = OsgiInstallerThread.getTotalEventsCount();
+        if (eventsCount < eventsCountForRetrying) {
+            Logger.logDebug(this + " is not executable at this time, counters=" + eventsCountForRetrying + "/" + eventsCount);
+            ctx.addTaskToNextCycle(this);
+            return Result.NOTHING;
+        }
+
+        final Bundle b = this.creator.getBundleContext().getBundle(bundleId);
+		if (b == null) {
+		    Logger.logInfo("Cannot start bundle, id not found: " + bundleId);
 			return Result.NOTHING;
 		}
 
-		try {
-	        if(b.getState() == Bundle.ACTIVE) {
-	            Logger.logDebug("Bundle already started, no action taken:" + bundleId + "/" + b.getSymbolicName());
-	        } else {
-	            // Try to start bundle, and if that doesn't work we'll need to retry
-	            logExecution();
-	            try {
-	                b.start();
-	                Logger.logInfo("Bundle started (retry count=" + retryCount + ", bundle ID=" + bundleId + ") " + b.getSymbolicName());
-	            } catch(BundleException e) {
-	                Logger.logInfo("Could not start bundle (retry count=" + retryCount + ", " + e
-	                            + "), will retry: " + bundleId + "/" + b.getSymbolicName());
-	                needToRetry = true;
-	            }
-
-	        }
-		} finally {
-	        if(needToRetry) {
-
-	            // Do the first retry immediately (in case "something" happenened right now
-	            // that warrants a retry), but for the next ones wait for at least one bundle
-	            // event or framework event
-	            if(retryCount == 0) {
-	                eventsCountForRetrying = Activator.getTotalEventsCount();
-	            } else {
-                    eventsCountForRetrying = Activator.getTotalEventsCount() + 1;
-	            }
+        if (b.getState() == Bundle.ACTIVE) {
+            Logger.logDebug("Bundle already started, no action taken:" + bundleId + "/" + b.getSymbolicName());
+        } else {
+            // Try to start bundle, and if that doesn't work we'll need to retry
+            logExecution();
+            try {
+                b.start();
+                Logger.logInfo("Bundle started (retry count=" + retryCount + ", bundle ID=" + bundleId + ") " + b.getSymbolicName());
+            } catch(BundleException e) {
+                Logger.logInfo("Could not start bundle (retry count=" + retryCount + ", " + e
+                            + "), will retry: " + bundleId + "/" + b.getSymbolicName());
+
+                // Do the first retry immediately (in case "something" happenened right now
+                // that warrants a retry), but for the next ones wait for at least one bundle
+                // event or framework event
+                if (retryCount == 0) {
+                    eventsCountForRetrying = OsgiInstallerThread.getTotalEventsCount();
+                } else {
+                    eventsCountForRetrying = OsgiInstallerThread.getTotalEventsCount() + 1;
+                }
 
-	            ctx.addTaskToNextCycle(this);
-	        }
-		}
+                ctx.addTaskToNextCycle(this);
+            }
+
+        }
 		retryCount++;
         return Result.SUCCESS;
 	}
-
-	/** Do not execute this task if waiting for events */
-    public boolean isExecutable(OsgiInstallerContext tctx) {
-        final long eventsCount = Activator.getTotalEventsCount();
-        final boolean result = eventsCount >= eventsCountForRetrying;
-        if(!result) {
-            Logger.logDebug(this + " is not executable at this time, counters=" + eventsCountForRetrying + "/" + eventsCount);
-        }
-        return result;
-    }
 }

Modified: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/ConfigInstallTask.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/ConfigInstallTask.java?rev=985161&r1=985160&r2=985161&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/ConfigInstallTask.java (original)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/ConfigInstallTask.java Fri Aug 13 11:38:01 2010
@@ -57,10 +57,9 @@ public class ConfigInstallTask extends A
 
     @SuppressWarnings("unchecked")
 	@Override
-    public Result execute(OsgiInstallerContext ctx) {
-
+    public Result execute(final OsgiInstallerContext ctx) {
         final ConfigurationAdmin ca = this.getConfigurationAdmin();
-        if(ca == null) {
+        if (ca == null) {
             ctx.addTaskToNextCycle(this);
             Logger.logDebug("ConfigurationAdmin not available, task will be retried later: " + this);
             return Result.NOTHING;
@@ -85,10 +84,10 @@ public class ConfigInstallTask extends A
         // update if the new one has the same values.
         boolean created = false;
         try {
-            Configuration config = getConfiguration(ca, pid, false, ctx);
+            Configuration config = getConfiguration(ca, pid, false);
             if(config == null) {
                 created = true;
-                config = getConfiguration(ca, pid, true, ctx);
+                config = getConfiguration(ca, pid, true);
             } else {
     			if(isSameData(config.getProperties(), resource.getDictionary())) {
     			    Logger.logDebug("Configuration " + config.getPid()

Modified: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/ConfigRemoveTask.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/ConfigRemoveTask.java?rev=985161&r1=985160&r2=985161&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/ConfigRemoveTask.java (original)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/ConfigRemoveTask.java Fri Aug 13 11:38:01 2010
@@ -34,7 +34,8 @@ public class ConfigRemoveTask extends Ab
     static final String CONFIG_PATH_KEY = "_jcr_config_path";
     public static final String [] CONFIG_EXTENSIONS = { ".cfg", ".properties" };
 
-    public ConfigRemoveTask(final RegisteredResource r, final ServiceTracker configAdminServiceTracker) {
+    public ConfigRemoveTask(final RegisteredResource r,
+            final ServiceTracker configAdminServiceTracker) {
         super(r, configAdminServiceTracker);
     }
 
@@ -43,10 +44,12 @@ public class ConfigRemoveTask extends Ab
         return CONFIG_REMOVE_ORDER + pid.getCompositePid();
     }
 
-    public Result execute(OsgiInstallerContext ctx) {
-
+    /**
+     * @see org.apache.sling.osgi.installer.impl.OsgiInstallerTask#execute(org.apache.sling.osgi.installer.impl.OsgiInstallerContext)
+     */
+    public Result execute(final OsgiInstallerContext ctx) {
         final ConfigurationAdmin ca = this.getConfigurationAdmin();
-        if(ca == null) {
+        if (ca == null) {
             ctx.addTaskToNextCycle(this);
             Logger.logDebug("ConfigurationAdmin not available, task will be retried later: " + this);
             return Result.NOTHING;
@@ -54,7 +57,7 @@ public class ConfigRemoveTask extends Ab
 
         logExecution();
         try {
-            final Configuration cfg = getConfiguration(ca, pid, false, ctx);
+            final Configuration cfg = getConfiguration(ca, pid, false);
             if(cfg == null) {
                 Logger.logDebug("Cannot delete config , pid=" + pid + " not found, ignored (" + resource + ")");
             } else {

Modified: sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/LocalFileRegisteredResource.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/LocalFileRegisteredResource.java?rev=985161&r1=985160&r2=985161&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/LocalFileRegisteredResource.java (original)
+++ sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/LocalFileRegisteredResource.java Fri Aug 13 11:38:01 2010
@@ -22,6 +22,7 @@ import java.io.File;
 import java.io.IOException;
 
 import org.apache.sling.osgi.installer.InstallableResource;
+import org.osgi.framework.BundleContext;
 
 /** RegisteredResource that stores data to a local temporary file */
 @SuppressWarnings("serial")
@@ -33,7 +34,7 @@ class LocalFileRegisteredResource extend
 	}
 
 	@Override
-	protected File getDataFile() {
+	protected File getDataFile(final BundleContext bc) {
 		if(storage == null) {
 	        try {
 	            storage = File.createTempFile(getClass().getName(), "test");

Modified: sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/MockBundleResource.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/MockBundleResource.java?rev=985161&r1=985160&r2=985161&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/MockBundleResource.java (original)
+++ sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/MockBundleResource.java Fri Aug 13 11:38:01 2010
@@ -20,7 +20,6 @@ package org.apache.sling.osgi.installer.
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.Serializable;
 import java.util.Dictionary;
 import java.util.HashMap;
 import java.util.Map;
@@ -29,7 +28,7 @@ import org.apache.sling.osgi.installer.I
 import org.osgi.framework.Constants;
 
 /** Mock RegisteredResource that simulates a bundle */
-public class MockBundleResource implements RegisteredResource, Serializable {
+public class MockBundleResource implements RegisteredResource {
 
     private static final long serialVersionUID = 1L;
     private final Map<String, Object> attributes = new HashMap<String, Object>();
@@ -75,59 +74,108 @@ public class MockBundleResource implemen
         ;
 	}
 
+	/**
+	 * @see org.apache.sling.osgi.installer.impl.RegisteredResource#cleanup()
+	 */
 	public void cleanup() {
 	    // nothing to do
 	}
 
+	/**
+	 * @see org.apache.sling.osgi.installer.impl.RegisteredResource#getAttributes()
+	 */
 	public Map<String, Object> getAttributes() {
 		return attributes;
 	}
 
+	/**
+	 * @see org.apache.sling.osgi.installer.impl.RegisteredResource#getDictionary()
+	 */
 	public Dictionary<String, Object> getDictionary() {
 		return null;
 	}
 
+	/**
+	 * @see org.apache.sling.osgi.installer.impl.RegisteredResource#getDigest()
+	 */
 	public String getDigest() {
 		return digest;
 	}
 
+	/**
+	 * @see org.apache.sling.osgi.installer.impl.RegisteredResource#getEntityId()
+	 */
 	public String getEntityId() {
 		return null;
 	}
 
+	/**
+	 * @see org.apache.sling.osgi.installer.impl.RegisteredResource#getInputStream()
+	 */
 	public InputStream getInputStream() throws IOException {
 		return null;
 	}
 
+	/**
+	 * @see org.apache.sling.osgi.installer.impl.RegisteredResource#getType()
+	 */
 	public String getType() {
 		return InstallableResource.TYPE_BUNDLE;
 	}
 
+	/**
+	 * @see org.apache.sling.osgi.installer.impl.RegisteredResource#getId()
+	 */
 	public String getId() {
 		return null;
 	}
 
+	/**
+	 * @see org.apache.sling.osgi.installer.impl.RegisteredResource#getURL()
+	 */
 	public String getURL() {
 		return null;
 	}
 
+    /**
+     * @see org.apache.sling.osgi.installer.impl.RegisteredResource#getUrlScheme()
+     */
     public String getUrlScheme() {
         return null;
     }
 
+    /**
+     * @see org.apache.sling.osgi.installer.impl.RegisteredResource#isInstallable()
+     */
     public boolean isInstallable() {
         return installable;
     }
 
+    /**
+     * @see org.apache.sling.osgi.installer.impl.RegisteredResource#setInstallable(boolean)
+     */
     public void setInstallable(boolean installable) {
         this.installable = installable;
     }
 
+    /**
+     * @see org.apache.sling.osgi.installer.impl.RegisteredResource#getPriority()
+     */
     public int getPriority() {
         return priority;
     }
 
+    /**
+     * @see org.apache.sling.osgi.installer.impl.RegisteredResource#getSerialNumber()
+     */
     public long getSerialNumber() {
         return serialNumber;
     }
+
+    /**
+     * @see java.lang.Comparable#compareTo(java.lang.Object)
+     */
+    public int compareTo(RegisteredResource o) {
+        return RegisteredResourceImpl.compare(this, o);
+    }
 }

Modified: sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/PersistentResourceListTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/PersistentResourceListTest.java?rev=985161&r1=985160&r2=985161&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/PersistentResourceListTest.java (original)
+++ sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/PersistentResourceListTest.java Fri Aug 13 11:38:01 2010
@@ -87,7 +87,7 @@ public class PersistentResourceListTest 
     private void addTestData(PersistentResourceList p) {
         for(int i = 0; i < TEST_SCALE; i++) {
             final String symbolicName = FAKE + i;
-            TreeSet<RegisteredResource> s = new TreeSet<RegisteredResource>(new RegisteredResourceComparator());
+            TreeSet<RegisteredResource> s = new TreeSet<RegisteredResource>();
             for(int j= TEST_SCALE - 2; j >= 1; j--) {
                 s.add(new MockBundleResource(symbolicName, getFakeVersion(i, j)));
             }

Modified: sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/RegisteredResourceComparatorTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/RegisteredResourceComparatorTest.java?rev=985161&r1=985160&r2=985161&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/RegisteredResourceComparatorTest.java (original)
+++ sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/RegisteredResourceComparatorTest.java Fri Aug 13 11:38:01 2010
@@ -53,7 +53,7 @@ public class RegisteredResourceComparato
     }
 
     private void assertOrder(RegisteredResource[] inOrder) {
-        final SortedSet<RegisteredResource> toTest = new TreeSet<RegisteredResource>(new RegisteredResourceComparator());
+        final SortedSet<RegisteredResource> toTest = new TreeSet<RegisteredResource>();
         for(int i = inOrder.length - 1 ; i >= 0; i--) {
             toTest.add(inOrder[i]);
         }
@@ -116,8 +116,7 @@ public class RegisteredResourceComparato
     public void testBundleDigests() {
         final RegisteredResource a = new MockBundleResource("a", "1.2.0", 0, "digestA");
         final RegisteredResource b = new MockBundleResource("a", "1.2.0", 0, "digestB");
-        final RegisteredResourceComparator c = new RegisteredResourceComparator();
-        assertEquals("Digests must not be included in bundles comparison", 0, c.compare(a, b));
+        assertEquals("Digests must not be included in bundles comparison", 0, a.compareTo(b));
     }
 
     @Test
@@ -148,8 +147,7 @@ public class RegisteredResourceComparato
         final RegisteredResource a = getConfig("pid", data, 0);
         data.put("foo", "changed");
         final RegisteredResource b = getConfig("pid", data, 0);
-        final RegisteredResourceComparator c = new RegisteredResourceComparator();
-        assertEquals("Digests must not be included in configs comparison", 0, c.compare(a, b));
+        assertEquals("Digests must not be included in configs comparison", 0, a.compareTo(b));
     }
 
     @Test
@@ -175,8 +173,7 @@ public class RegisteredResourceComparato
     public void testConfigAndBundle() throws IOException {
     	final RegisteredResource cfg = getConfig("pid", null, InstallableResource.DEFAULT_PRIORITY);
     	final RegisteredResource b = new MockBundleResource("a", "1.0");
-    	final RegisteredResourceComparator c = new RegisteredResourceComparator();
-    	assertEquals("bundle is > config when compared", 1, c.compare(b, cfg));
-    	assertEquals("config is < bundle when compared", -1, c.compare(cfg, b));
+    	assertEquals("bundle is > config when compared", 1, b.compareTo(cfg));
+    	assertEquals("config is < bundle when compared", -1, cfg.compareTo(b));
     }
 }
\ No newline at end of file

Modified: sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/RegisteredResourceTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/RegisteredResourceTest.java?rev=985161&r1=985160&r2=985161&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/RegisteredResourceTest.java (original)
+++ sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/RegisteredResourceTest.java Fri Aug 13 11:38:01 2010
@@ -77,9 +77,9 @@ public class RegisteredResourceTest {
 	    final File f = getTestBundle("testbundle-1.0.jar");
         final InputStream s = new FileInputStream(f);
 		final LocalFileRegisteredResource r = new LocalFileRegisteredResource(new InstallableResource("test:1.jar", s, null, "somedigest", null, null));
-		assertTrue("Local file exists", r.getDataFile().exists());
+		assertTrue("Local file exists", r.getDataFile(null).exists());
 
-		assertEquals("Local file length matches our data", f.length(), r.getDataFile().length());
+		assertEquals("Local file length matches our data", f.length(), r.getDataFile(null).length());
 	}
 
     @org.junit.Test public void testMissingDigest() throws Exception {
@@ -116,32 +116,4 @@ public class RegisteredResourceTest {
                 "Expecting configs with same data but different URLs to have different digests",
                 rA.getDigest().equals(rB.getDigest()));
     }
-
-    @org.junit.Test public void testUrlScheme() throws Exception {
-        final String [] badOnes = {
-                "",
-                ":colonTooEarly",
-                ":colonTooEarlyAgain:",
-        };
-        for(String url : badOnes) {
-            try {
-                new RegisteredResourceImpl(null,
-                        new InstallableResource("test", null, new Hashtable<String, Object>(), null, null, null),
-                        url);
-                fail("Expected bad URL '" + url + "' to throw IllegalArgumentException");
-            } catch(IllegalArgumentException asExpected) {
-            }
-        }
-
-        final String [] goodOnes = {
-                "noColon"
-        };
-
-        for(String url : goodOnes) {
-            final RegisteredResource r = new RegisteredResourceImpl(null,
-                    new InstallableResource("test", null, new Hashtable<String, Object>(), "digest1", null, null),
-                    url);
-            assertEquals("Expected scheme '" + url + "' for URL " + url, url, r.getUrlScheme());
-        }
-    }
 }
\ No newline at end of file

Modified: sling/trunk/installer/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/installer/pom.xml?rev=985161&r1=985160&r2=985161&view=diff
==============================================================================
--- sling/trunk/installer/pom.xml (original)
+++ sling/trunk/installer/pom.xml Fri Aug 13 11:38:01 2010
@@ -33,6 +33,7 @@
 	<modules>
 		<module>osgi/installer</module>
 		<module>osgi/it</module>
+		<module>fileinstall</module>
 		<module>jcr/jcrinstall</module>
 	</modules>
 </project>