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 2012/07/20 21:53:23 UTC

svn commit: r1363918 - in /sling/trunk/installer/core: ./ src/main/java/org/apache/sling/installer/api/tasks/ src/main/java/org/apache/sling/installer/core/impl/ src/main/java/org/apache/sling/installer/core/impl/tasks/ src/test/java/org/apache/sling/i...

Author: cziegeler
Date: Fri Jul 20 19:53:22 2012
New Revision: 1363918

URL: http://svn.apache.org/viewvc?rev=1363918&view=rev
Log:
SLING-2524 : Improve package refresh behaviour

Added:
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/AsyncWrapperInstallTask.java   (with props)
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleUtil.java   (with props)
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/RefreshBundlesTask.java   (with props)
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/TaskSupport.java   (with props)
Removed:
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/SynchronousRefreshPackagesTask.java
Modified:
    sling/trunk/installer/core/pom.xml
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/tasks/ChangeStateTask.java
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/tasks/InstallTask.java
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/tasks/InstallationContext.java
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/AbstractInstallTask.java
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/Activator.java
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/EntityResourceList.java
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/OsgiInstallerImpl.java
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/AbstractBundleTask.java
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleInstallTask.java
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleRemoveTask.java
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleStartTask.java
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleTaskCreator.java
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleUpdateTask.java
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/InstallerBundleUpdateTask.java
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/RefreshOptionalPackagesTask.java
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/SystemBundleUpdateTask.java
    sling/trunk/installer/core/src/test/java/org/apache/sling/installer/core/impl/TaskOrderingTest.java

Modified: sling/trunk/installer/core/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/pom.xml?rev=1363918&r1=1363917&r2=1363918&view=diff
==============================================================================
--- sling/trunk/installer/core/pom.xml (original)
+++ sling/trunk/installer/core/pom.xml Fri Jul 20 19:53:22 2012
@@ -63,7 +63,7 @@
 							org.apache.sling.installer.api;version=3.1.0,
                             org.apache.sling.installer.api.info;version=1.0.0,
                             org.apache.sling.installer.api.event;version=1.0.0,
-                            org.apache.sling.installer.api.tasks;version=1.2.0
+                            org.apache.sling.installer.api.tasks;version=1.3.0
                         </Export-Package>
 						<Private-Package>
 						    org.apache.sling.installer.core.impl.*
@@ -71,7 +71,7 @@
                         <Embed-Dependency>
                             org.apache.felix.configadmin;inline="org/apache/felix/cm/file/ConfigurationHandler.*",
                             org.osgi.compendium;inline="org/osgi/util/tracker/*",
-                            org.apache.sling.commons.osgi;inline="org/apache/sling/commons/osgi/ManifestHeader*.*"
+                            org.apache.sling.commons.osgi;inline="org/apache/sling/commons/osgi/ManifestHeader*.*|org/apache/sling/commons/osgi/PropertiesUtil.*"
                         </Embed-Dependency>
 					</instructions>
 				</configuration>
@@ -143,7 +143,7 @@
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.commons.osgi</artifactId>
-            <version>2.0.6</version>
+            <version>2.1.0</version>
             <scope>provided</scope>
         </dependency>
       <!-- We use a class from the config admin implementation to read config files -->

Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/tasks/ChangeStateTask.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/tasks/ChangeStateTask.java?rev=1363918&r1=1363917&r2=1363918&view=diff
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/tasks/ChangeStateTask.java (original)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/tasks/ChangeStateTask.java Fri Jul 20 19:53:22 2012
@@ -18,6 +18,8 @@
  */
 package org.apache.sling.installer.api.tasks;
 
+import java.util.Map;
+
 
 /**
  * Simple general task, setting the state of a registered resource.
@@ -29,16 +31,55 @@ public class ChangeStateTask extends Ins
 
     private final ResourceState state;
 
+    private final String[] removeAttributes;
+
+    private final Map<String, Object> addAttributes;
+
+    /**
+     * Change the state of the task
+     * @param r The resource group to change.
+     * @param s The new state.,
+     */
     public ChangeStateTask(final TaskResourceGroup r,
                            final ResourceState s) {
+        this(r, s, null, null);
+    }
+
+    /**
+     * Change the state of the task
+     * @param r The resource group to change.
+     * @param s The new state.,
+     * @param addAttributes    An optional map of attributes to set before the state is changed.
+     * @param removeAttributes A optional list of attributes to remove before the state is changed.
+     * @since 1.3
+     */
+    public ChangeStateTask(final TaskResourceGroup r,
+                           final ResourceState s,
+                           final Map<String, Object> addAttributes,
+                           final String[] removeAttributes) {
         super(r);
         this.state = s;
+        this.addAttributes = addAttributes;
+        this.removeAttributes = removeAttributes;
     }
 
     /**
      * @see org.apache.sling.installer.api.tasks.InstallTask#execute(org.apache.sling.installer.api.tasks.InstallationContext)
      */
     public void execute(final InstallationContext ctx) {
+        final TaskResource resource = this.getResource();
+        if ( resource != null ) {
+            if ( this.removeAttributes != null ) {
+                for(final String name : this.removeAttributes ) {
+                    resource.setAttribute(name, null);
+                }
+            }
+            if ( this.addAttributes != null ) {
+                for(final Map.Entry<String, Object> entry : this.addAttributes.entrySet()) {
+                    resource.setAttribute(entry.getKey(), entry.getValue());
+                }
+            }
+        }
         this.setFinishedState(this.state);
     }
 

Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/tasks/InstallTask.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/tasks/InstallTask.java?rev=1363918&r1=1363917&r2=1363918&view=diff
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/tasks/InstallTask.java (original)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/tasks/InstallTask.java Fri Jul 20 19:53:22 2012
@@ -33,6 +33,13 @@ package org.apache.sling.installer.api.t
  */
 public abstract class InstallTask implements Comparable<InstallTask> {
 
+    /**
+     * Attribute which is set by the OSGi installer for asynchronous execution.
+     * The value of the attribute is an Integer which is increased on each async call,
+     * it starts with the value <code>1</code>.
+     */
+    public static final String ASYNC_ATTR_NAME = "org.apache.sling.installer.api.tasks.ASyncInstallTask";
+
     /** The resource group this task is working on. */
     private final TaskResourceGroup resourceGroup;
 
@@ -121,4 +128,26 @@ public abstract class InstallTask implem
     public final int compareTo(final InstallTask o) {
         return getSortKey().compareTo(o.getSortKey());
     }
+
+    /**
+     * If this an asynchronous task it should return <code>true</code>
+     * The OSGi installer will set the attribute {@link #ASYNC_ATTR_NAME}
+     * with an integer value.
+     * The next time, after the asynchronous task has been run and
+     * the OSGi installer has restarted, this attribute will be set
+     * on the resource.
+     *
+     * Asynchronous tasks should only be used for tasks which require
+     * the OSGi installer to stop and force it to restart, like
+     * a bundle update of the installer itself or a system update.
+     * The OSGi installer stops itself for an asynchronous task and
+     * is not able to restart itself!
+     *
+     * @return If this is a async request, <code>true</code>
+     *         otherwise <code>false</code>
+     * @since 1.3
+     */
+    public boolean isAsynchronousTask() {
+        return false;
+    }
 }
\ No newline at end of file

Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/tasks/InstallationContext.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/tasks/InstallationContext.java?rev=1363918&r1=1363917&r2=1363918&view=diff
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/tasks/InstallationContext.java (original)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/tasks/InstallationContext.java Fri Jul 20 19:53:22 2012
@@ -57,6 +57,20 @@ public interface InstallationContext {
      * Add an async task.
      * This adds a task for asynchronous execution.
      * @since 1.2.0
+     * @deprecated A async task should return <code>true</code> for {@link InstallTask#isAsynchronousTask()}
+     *             and be add with {@link #addTaskToCurrentCycle(InstallTask)}
      */
+	@Deprecated
     void addAsyncTask(InstallTask t);
+
+    /**
+     * Inform the installer about a failed async task.
+     * This will restart the OSGi installer.
+     *
+     * This will also remove the {@link InstallTask#ASYNC_ATTR_NAME}
+     * attribute from the resource.
+     *
+     * @since 1.3.0
+     */
+    void asyncTaskFailed(InstallTask t);
 }

Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/AbstractInstallTask.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/AbstractInstallTask.java?rev=1363918&r1=1363917&r2=1363918&view=diff
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/AbstractInstallTask.java (original)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/AbstractInstallTask.java Fri Jul 20 19:53:22 2012
@@ -23,16 +23,24 @@ import org.apache.sling.installer.api.ta
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+/**
+ * Abstract base class providing an additional logger
+ */
 public abstract class AbstractInstallTask extends InstallTask {
 
-    public AbstractInstallTask(TaskResourceGroup erl) {
+    private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+    /**
+     * Constructor
+     */
+    public AbstractInstallTask(final TaskResourceGroup erl) {
         super(erl);
     }
 
-    private final Logger logger = LoggerFactory.getLogger(this.getClass());
-
+    /**
+     * Get a logger.
+     */
     protected Logger getLogger() {
         return this.logger;
     }
-
 }

Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/Activator.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/Activator.java?rev=1363918&r1=1363917&r2=1363918&view=diff
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/Activator.java (original)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/Activator.java Fri Jul 20 19:53:22 2012
@@ -66,7 +66,6 @@ public class Activator implements Bundle
         props.put(Constants.SERVICE_VENDOR, VENDOR);
 
         this.osgiControllerService = new OsgiInstallerImpl(context);
-        this.osgiControllerService.setDaemon(true);
 
         // register internal services
         this.registerServices(context);

Added: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/AsyncWrapperInstallTask.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/AsyncWrapperInstallTask.java?rev=1363918&view=auto
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/AsyncWrapperInstallTask.java (added)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/AsyncWrapperInstallTask.java Fri Jul 20 19:53:22 2012
@@ -0,0 +1,79 @@
+/*
+ * 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.sling.installer.core.impl;
+
+import org.apache.sling.installer.api.tasks.InstallTask;
+import org.apache.sling.installer.api.tasks.InstallationContext;
+import org.apache.sling.installer.api.tasks.ResourceState;
+import org.apache.sling.installer.api.tasks.TaskResource;
+import org.apache.sling.installer.api.tasks.TaskResourceGroup;
+
+/**
+ * Wrapper class to add the async flag.
+ * This is needed for pre 1.3 api usage
+ */
+public class AsyncWrapperInstallTask extends InstallTask {
+
+    private final InstallTask delegatee;
+
+    public AsyncWrapperInstallTask(final InstallTask delegatee) {
+        super(delegatee.getResourceGroup());
+        this.delegatee = delegatee;
+    }
+
+    @Override
+    public void execute(final InstallationContext ctx) {
+        this.delegatee.execute(ctx);
+    }
+
+    @Override
+    public String getSortKey() {
+        return this.delegatee.getSortKey();
+    }
+
+    @Override
+    public TaskResource getResource() {
+        return this.delegatee.getResource();
+    }
+
+    @Override
+    public TaskResourceGroup getResourceGroup() {
+        return this.delegatee.getResourceGroup();
+    }
+
+    @Override
+    public void setFinishedState(final ResourceState state) {
+        this.delegatee.setFinishedState(state);
+    }
+
+    @Override
+    public void setFinishedState(final ResourceState state, final String alias) {
+        this.delegatee.setFinishedState(state, alias);
+    }
+
+    @Override
+    public String toString() {
+        return this.delegatee.toString();
+    }
+
+    @Override
+    public boolean isAsynchronousTask() {
+        return true;
+    }
+}

Propchange: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/AsyncWrapperInstallTask.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/AsyncWrapperInstallTask.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/AsyncWrapperInstallTask.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/EntityResourceList.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/EntityResourceList.java?rev=1363918&r1=1363917&r2=1363918&view=diff
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/EntityResourceList.java (original)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/EntityResourceList.java Fri Jul 20 19:53:22 2012
@@ -252,8 +252,8 @@ public class EntityResourceList implemen
      * @see org.apache.sling.installer.api.tasks.TaskResourceGroup#setFinishState(org.apache.sling.installer.api.tasks.ResourceState, java.lang.String)
      */
     public void setFinishState(final ResourceState state, final String alias) {
-        this.setFinishState(state);
         this.alias = alias;
+        this.setFinishState(state);
     }
 
     private void cleanup(final RegisteredResource rr) {

Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/OsgiInstallerImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/OsgiInstallerImpl.java?rev=1363918&r1=1363917&r2=1363918&view=diff
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/OsgiInstallerImpl.java (original)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/OsgiInstallerImpl.java Fri Jul 20 19:53:22 2012
@@ -36,6 +36,7 @@ import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
 
+import org.apache.sling.commons.osgi.PropertiesUtil;
 import org.apache.sling.installer.api.InstallableResource;
 import org.apache.sling.installer.api.OsgiInstaller;
 import org.apache.sling.installer.api.ResourceChangeListener;
@@ -72,8 +73,7 @@ import org.slf4j.LoggerFactory;
  *  the main list at the end of the cycle.
  */
 public class OsgiInstallerImpl
-    extends Thread
-    implements OsgiInstaller, ResourceChangeListener, RetryHandler, InfoProvider {
+    implements OsgiInstaller, ResourceChangeListener, RetryHandler, InfoProvider, Runnable {
 
     /** The logger */
     private final Logger logger =  LoggerFactory.getLogger(this.getClass());
@@ -97,7 +97,7 @@ public class OsgiInstallerImpl
     private volatile boolean active = true;
 
     /** Are we still running? */
-    private volatile boolean backgroundThreadIsRunning = false;
+    private volatile Thread backgroundThread;
 
     /** Flag indicating that a retry event occured during tasks executions. */
     private volatile boolean retryDuringTaskExecution = false;
@@ -146,13 +146,17 @@ public class OsgiInstallerImpl
 
         this.listener.dispose();
 
-        if ( this.backgroundThreadIsRunning ) {
+        if ( this.backgroundThread != null ) {
             this.logger.debug("Waiting for installer thread to stop");
-            while ( this.backgroundThreadIsRunning ) {
-                try {
-                    this.join(50L);
-                } catch (InterruptedException e) {
-                    // we simply ignore this
+            while ( this.backgroundThread != null ) {
+                // use a local variable to avoid NPEs
+                final Thread t = this.backgroundThread;
+                if ( t != null ) {
+                    try {
+                        t.join(50L);
+                    } catch (final InterruptedException e) {
+                        // we simply ignore this
+                    }
                 }
             }
         }
@@ -163,6 +167,10 @@ public class OsgiInstallerImpl
         this.logger.info("Apache Sling OSGi Installer Service stopped.");
     }
 
+    public void start() {
+        this.startBackgroundThread();
+    }
+
     /**
      * Initialize the installer
      */
@@ -175,13 +183,20 @@ public class OsgiInstallerImpl
         this.updateHandlerTracker = new SortingServiceTracker<UpdateHandler>(ctx, UpdateHandler.class.getName(), null);
         this.updateHandlerTracker.open();
 
-        setName(getClass().getSimpleName());
         this.logger.info("Apache Sling OSGi Installer Service started.");
     }
 
-    @Override
+    private void startBackgroundThread() {
+        this.backgroundThread = new Thread(this);
+        this.backgroundThread.setName(getClass().getSimpleName());
+        this.backgroundThread.setDaemon(true);
+        this.backgroundThread.start();
+    }
+
+    /**
+     * @see java.lang.Runnable#run()
+     */
     public void run() {
-        this.backgroundThreadIsRunning = true;
         try {
             this.init();
 
@@ -226,7 +241,7 @@ public class OsgiInstallerImpl
             }
             this.listener.suspend();
         } finally {
-            this.backgroundThreadIsRunning = false;
+            this.backgroundThread = null;
         }
     }
 
@@ -582,7 +597,6 @@ public class OsgiInstallerImpl
     private ACTION executeTasks(final SortedSet<InstallTask> tasks) {
         if ( !tasks.isEmpty() ) {
 
-            final List<InstallTask> asyncTasks = new ArrayList<InstallTask>();
             final InstallationContext ctx = new InstallationContext() {
 
                 public void addTaskToNextCycle(final InstallTask t) {
@@ -593,22 +607,40 @@ public class OsgiInstallerImpl
                 }
 
                 public void addTaskToCurrentCycle(final InstallTask t) {
-                    logger.debug("Adding task to current cycle: {}", t);
+                    logger.debug("Adding {}task to current cycle: {}", t.isAsynchronousTask() ? "async " : "", t);
                     synchronized ( tasks ) {
                         tasks.add(t);
                     }
                 }
 
-                public void addAsyncTask(InstallTask t) {
-                    logger.debug("Adding async task: {}", t);
-                    synchronized (asyncTasks) {
-                        asyncTasks.add(t);
+                public void addAsyncTask(final InstallTask t) {
+                    if ( t.isAsynchronousTask() ) {
+                        logger.warn("Deprecated method addAsyncTask is called: {}", t);
+                        this.addTaskToCurrentCycle(t);
+                    } else {
+                        logger.warn("Deprecated method addAsyncTask is called with non async task(!): {}", t);
+                        this.addTaskToCurrentCycle(new AsyncWrapperInstallTask(t));
                     }
                 }
 
-                public void log(String message, Object... args) {
+                public void log(final String message, final Object... args) {
                     auditLogger.info(message, args);
                 }
+
+                public void asyncTaskFailed(final InstallTask t) {
+                    // persist all changes and retry restart
+                    // remove attribute
+                    if ( t.getResource() != null ) {
+                        t.getResource().setAttribute(InstallTask.ASYNC_ATTR_NAME, null);
+                    }
+                    persistentList.save();
+                    synchronized ( resourcesLock ) {
+                        if ( !active ) {
+                            active = true;
+                            startBackgroundThread();
+                        }
+                    }
+                }
             };
             while (this.active && !tasks.isEmpty()) {
                 InstallTask task = null;
@@ -616,8 +648,47 @@ public class OsgiInstallerImpl
                     task = tasks.first();
                     tasks.remove(task);
                 }
-                logger.debug("Executing task: {}", task);
+                // async tasks are executed "immediately"
+                if ( task.isAsynchronousTask() ) {
+                    logger.debug("Executing async task: {}", task);
+                    // set attribute
+                    final Integer oldValue;
+                    if ( task.getResource() != null ) {
+                        oldValue = (Integer)task.getResource().getAttribute(InstallTask.ASYNC_ATTR_NAME);
+                        final Integer newValue;
+                        if ( oldValue == null ) {
+                            newValue = 1;
+                        } else {
+                            newValue = oldValue + 1;
+                        }
+                        task.getResource().setAttribute(InstallTask.ASYNC_ATTR_NAME, newValue);
+                    } else {
+                        oldValue = null;
+                    }
+                    // save new state
+                    this.cleanupInstallableResources();
+                    final InstallTask aSyncTask = task;
+                    final Thread t = new Thread() {
+
+                        @Override
+                        public void run() {
+                            try {
+                                Thread.sleep(2000L);
+                            } catch (final InterruptedException ie) {
+                                // ignore
+                            }
+                            // reset attribute
+                            if ( aSyncTask.getResource() != null ) {
+                                aSyncTask.getResource().setAttribute(InstallTask.ASYNC_ATTR_NAME, oldValue);
+                            }
+                            aSyncTask.execute(ctx);
+                        }
+                    };
+                    t.start();
+                    return ACTION.SHUTDOWN;
+                }
                 try {
+                    logger.debug("Executing task: {}", task);
                     task.execute(ctx);
                 } catch (final Throwable t) {
                     logger.error("Uncaught exception during task execution!", t);
@@ -625,26 +696,6 @@ public class OsgiInstallerImpl
             }
             // save new state
             final boolean newCycle = this.cleanupInstallableResources();
-
-            // let's check if we have async tasks and no other tasks
-            if ( this.active && !asyncTasks.isEmpty() ) {
-                final InstallTask task = asyncTasks.get(0);
-                logger.debug("Executing async task: {}", task);
-                final Thread t = new Thread() {
-
-                    @Override
-                    public void run() {
-                        try {
-                            Thread.sleep(2000L);
-                        } catch (final InterruptedException ie) {
-                            // ignore
-                        }
-                        task.execute(ctx);
-                    }
-                };
-                t.start();
-                return ACTION.SHUTDOWN;
-            }
             if ( newCycle ) {
                 return ACTION.CYCLE;
             }
@@ -941,7 +992,7 @@ public class OsgiInstallerImpl
     private UpdateHandler findHandler(final String scheme) {
         final List<ServiceReference> references = this.updateHandlerTracker.getSortedServiceReferences();
         for(final ServiceReference ref : references) {
-            final String[] supportedSchemes = toStringArray(ref.getProperty(UpdateHandler.PROPERTY_SCHEMES));
+            final String[] supportedSchemes = PropertiesUtil.toStringArray(ref.getProperty(UpdateHandler.PROPERTY_SCHEMES));
             if ( supportedSchemes != null ) {
                 for(final String support : supportedSchemes ) {
                     if ( scheme.equals(support) ) {
@@ -954,25 +1005,6 @@ public class OsgiInstallerImpl
     }
 
     /**
-     * Returns the parameter as an array of Strings.
-     */
-    public static String[] toStringArray(final Object propValue) {
-        if (propValue == null) {
-            return null;
-
-        } else if (propValue instanceof String) {
-            // single string
-            return new String[] { (String) propValue };
-
-        } else if (propValue instanceof String[]) {
-            // String[]
-            return (String[]) propValue;
-
-        }
-        return null;
-    }
-
-    /**
      * @see org.apache.sling.installer.api.info.InfoProvider#getInstallationState()
      */
     public InstallationState getInstallationState() {

Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/AbstractBundleTask.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/AbstractBundleTask.java?rev=1363918&r1=1363917&r2=1363918&view=diff
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/AbstractBundleTask.java (original)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/AbstractBundleTask.java Fri Jul 20 19:53:22 2012
@@ -21,9 +21,7 @@ package org.apache.sling.installer.core.
 import org.apache.sling.installer.api.InstallableResource;
 import org.apache.sling.installer.api.tasks.TaskResourceGroup;
 import org.apache.sling.installer.core.impl.AbstractInstallTask;
-import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
 import org.osgi.service.packageadmin.PackageAdmin;
 import org.osgi.service.startlevel.StartLevel;
 
@@ -32,27 +30,27 @@ import org.osgi.service.startlevel.Start
  */
 public abstract class AbstractBundleTask extends AbstractInstallTask {
 
-    private final BundleTaskCreator creator;
+    private final TaskSupport support;
 
-    public AbstractBundleTask(final TaskResourceGroup erl, final BundleTaskCreator creator) {
+    public AbstractBundleTask(final TaskResourceGroup erl, final TaskSupport support) {
         super(erl);
-        this.creator = creator;
+        this.support = support;
     }
 
     protected PackageAdmin getPackageAdmin() {
-        return this.creator.getPackageAdmin();
+        return this.support.getPackageAdmin();
     }
 
     protected BundleContext getBundleContext() {
-        return this.creator.getBundleContext();
+        return this.support.getBundleContext();
     }
 
     protected StartLevel getStartLevel() {
-        return this.creator.getStartLevel();
+        return this.support.getStartLevel();
     }
 
-    protected BundleTaskCreator getCreator() {
-        return this.creator;
+    protected TaskSupport getTaskSupport() {
+        return this.support;
     }
 
     /**
@@ -99,51 +97,4 @@ public abstract class AbstractBundleTask
         }
         return String.valueOf(startLevel);
     }
-
-    /**
-     * Check if the bundle is active.
-     * This is true if the bundle has the active state or of the bundle
-     * is in the starting state and has the lazy activation policy.
-     * Or if the bundle is a fragment, it's considered active as well
-     */
-    protected boolean isBundleActive(final Bundle b) {
-        if ( b.getState() == Bundle.ACTIVE ) {
-            return true;
-        }
-        if ( b.getState() == Bundle.STARTING && isLazyActivatian(b) ) {
-            return true;
-        }
-        return ( getFragmentHostHeader(b) != null );
-    }
-
-    /**
-     * Gets the bundle's Fragment-Host header.
-     */
-    protected String getFragmentHostHeader(final Bundle b) {
-        return (String) b.getHeaders().get( Constants.FRAGMENT_HOST );
-    }
-
-    /**
-     * Check if the bundle has the lazy activation policy
-     */
-    private boolean isLazyActivatian(final Bundle b) {
-        return Constants.ACTIVATION_LAZY.equals(b.getHeaders().get(Constants.BUNDLE_ACTIVATIONPOLICY));
-    }
-
-    /**
-     * Refresh host bundle
-     */
-    protected void refreshHostBundle(final Bundle b) {
-        final String fragmentHostHeader = getFragmentHostHeader(b);
-        if (fragmentHostHeader != null) {
-            this.getLogger().debug("Need to do a refresh of the bundle's host");
-            for (final Bundle bundle : this.getBundleContext().getBundles()) {
-                if (fragmentHostHeader.equals(bundle.getSymbolicName())) {
-                    this.getLogger().debug("Found host bundle to refresh {}", bundle.getBundleId());
-                    this.getPackageAdmin().refreshPackages(new Bundle[] { bundle });
-                    break;
-                }
-            }
-        }
-    }
 }

Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleInstallTask.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleInstallTask.java?rev=1363918&r1=1363917&r2=1363918&view=diff
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleInstallTask.java (original)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleInstallTask.java Fri Jul 20 19:53:22 2012
@@ -19,6 +19,7 @@
 package org.apache.sling.installer.core.impl.tasks;
 
 import org.apache.sling.installer.api.tasks.InstallationContext;
+import org.apache.sling.installer.api.tasks.ResourceState;
 import org.apache.sling.installer.api.tasks.TaskResourceGroup;
 import org.osgi.framework.Bundle;
 import org.osgi.service.startlevel.StartLevel;
@@ -29,10 +30,10 @@ import org.osgi.service.startlevel.Start
  */
 public class BundleInstallTask extends AbstractBundleTask {
 
-    private static final String BUNDLE_INSTALL_ORDER = "50-";
+    private static final String BUNDLE_INSTALL_ORDER = "40-";
 
     public BundleInstallTask(final TaskResourceGroup r,
-            final BundleTaskCreator creator) {
+            final TaskSupport creator) {
         super(r, creator);
     }
 
@@ -56,10 +57,31 @@ public class BundleInstallTask extends A
                 }
             }
 
-            // mark this resource as installed and to be started
-            this.getResource().setAttribute(BundleTaskCreator.ATTR_START, "true");
-            ctx.addTaskToCurrentCycle(new BundleStartTask(getResourceGroup(), b.getBundleId(), this.getCreator()));
-        } catch (Exception ex) {
+            // fragment?
+            if ( BundleUtil.isSystemBundleFragment(b) ) {
+                this.setFinishedState(ResourceState.INSTALLED);
+                ctx.addTaskToCurrentCycle(new SystemBundleUpdateTask(null, this.getTaskSupport()));
+            } else {
+                final String fragmentHostHeader = BundleUtil.getFragmentHostHeader(b);
+                if (fragmentHostHeader != null) {
+                    this.getLogger().debug("Need to do a refresh of the bundle's host");
+                    for (final Bundle bundle : this.getBundleContext().getBundles()) {
+                        if (fragmentHostHeader.equals(bundle.getSymbolicName())) {
+                            this.getLogger().debug("Found host bundle to refresh {}", bundle.getBundleId());
+                            RefreshBundlesTask.markBundleForRefresh(ctx, this.getTaskSupport(), bundle);
+                            break;
+                        }
+                    }
+
+                    this.setFinishedState(ResourceState.INSTALLED);
+                } else {
+
+                    // mark this resource as to be started
+                    BundleUtil.markBundleStart(getResource());
+                    ctx.addTaskToCurrentCycle(new BundleStartTask(getResourceGroup(), b.getBundleId(), this.getTaskSupport()));
+                }
+            }
+        } catch (final Exception ex) {
             // if something goes wrong we simply try it again
             this.getLogger().debug("Exception during install of bundle " + this.getResource() + " : " + ex.getMessage() + ". Retrying later.", ex);
         }

Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleRemoveTask.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleRemoveTask.java?rev=1363918&r1=1363917&r2=1363918&view=diff
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleRemoveTask.java (original)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleRemoveTask.java Fri Jul 20 19:53:22 2012
@@ -34,7 +34,7 @@ public class BundleRemoveTask extends Ab
     private static final String BUNDLE_REMOVE_ORDER = "30-";
 
     public BundleRemoveTask(final TaskResourceGroup r,
-                            final BundleTaskCreator creator) {
+                            final TaskSupport creator) {
         super(r, creator);
     }
 
@@ -57,8 +57,11 @@ public class BundleRemoveTask extends Ab
             }
             b.uninstall();
             ctx.log("Uninstalled bundle {} from resource {}", b, getResource());
+            // if the bundle exported packages, we need to refresh
+            if ( BundleUtil.getFragmentHostHeader(b) == null ) {
+                RefreshBundlesTask.markBundleForRefresh(ctx, this.getTaskSupport(), b);
+            }
             this.setFinishedState(ResourceState.UNINSTALLED);
-            ctx.addTaskToCurrentCycle(new SynchronousRefreshPackagesTask(this.getCreator()));
         } catch (final BundleException be) {
             this.getLogger().debug("Exception during removal of bundle " + this.getResource() + " : " + be.getMessage() + ". Retrying later.", be);
         }

Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleStartTask.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleStartTask.java?rev=1363918&r1=1363917&r2=1363918&view=diff
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleStartTask.java (original)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleStartTask.java Fri Jul 20 19:53:22 2012
@@ -39,7 +39,7 @@ public class BundleStartTask extends Abs
     private final long bundleId;
     private final String sortKey;
 
-    public BundleStartTask(final TaskResourceGroup r, final long bundleId, final BundleTaskCreator btc) {
+    public BundleStartTask(final TaskResourceGroup r, final long bundleId, final TaskSupport btc) {
         super(r, btc);
         this.bundleId = bundleId;
         this.sortKey = BUNDLE_START_ORDER + new DecimalFormat("00000").format(bundleId);
@@ -55,6 +55,14 @@ public class BundleStartTask extends Abs
         return getClass().getSimpleName() + ": bundle " + bundleId;
     }
 
+    @Override
+    public void setFinishedState(final ResourceState state) {
+        if ( this.getResource() != null ) {
+            BundleUtil.clearBundleStart(this.getResource());
+        }
+        super.setFinishedState(state);
+    }
+
     /**
      * @see org.apache.sling.installer.api.tasks.InstallTask#execute(org.apache.sling.installer.api.tasks.InstallationContext)
      */
@@ -68,30 +76,18 @@ public class BundleStartTask extends Abs
             return;
         }
 
+        // and another sanity chheck
         final Bundle b = this.getBundleContext().getBundle(bundleId);
         if (b == null) {
             this.getLogger().info("Cannot start bundle, id not found: {}", bundleId);
+            this.setFinishedState(ResourceState.IGNORED);
             return;
         }
 
-        final String fragmentHostHeader = getFragmentHostHeader(b);
-        if (fragmentHostHeader != null) {
-            this.getLogger().debug("Need to do a refresh of the bundle's host");
-            for (final Bundle bundle : this.getBundleContext().getBundles()) {
-                if (fragmentHostHeader.equals(bundle.getSymbolicName())) {
-                    this.getLogger().debug("Found host bundle to refresh {}", bundle.getBundleId());
-                    this.getPackageAdmin().refreshPackages(new Bundle[] { bundle });
-                    break;
-                }
-            }
-
+        if (BundleUtil.isBundleActive(b) ) {
+            this.getLogger().debug("Bundle already started, no action taken: {}/{}", bundleId, b.getSymbolicName());
             this.setFinishedState(ResourceState.INSTALLED);
         } else {
-            if (isBundleActive(b) ) {
-                this.getLogger().debug("Bundle already started, no action taken: {}/{}", bundleId, b.getSymbolicName());
-                this.setFinishedState(ResourceState.INSTALLED);
-                return;
-            }
             // Try to start bundle, and if that doesn't work we'll need to retry
             try {
                 b.start();

Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleTaskCreator.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleTaskCreator.java?rev=1363918&r1=1363917&r2=1363918&view=diff
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleTaskCreator.java (original)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleTaskCreator.java Fri Jul 20 19:53:22 2012
@@ -36,9 +36,6 @@ import org.osgi.framework.Constants;
 import org.osgi.framework.FrameworkEvent;
 import org.osgi.framework.FrameworkListener;
 import org.osgi.framework.Version;
-import org.osgi.service.packageadmin.PackageAdmin;
-import org.osgi.service.startlevel.StartLevel;
-import org.osgi.util.tracker.ServiceTracker;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -53,24 +50,11 @@ public class BundleTaskCreator
      */
     private final static String FORCE_INSTALL_VERSION = "force.install.version";
 
-    private final static String SPECIAL_ATTR = "sling.osgi.installer.special";
-
     /** The logger */
     private final Logger logger =  LoggerFactory.getLogger(this.getClass());
 
-    public static final String ATTR_START = "sling.osgi.installer.start.bundle";
-
-    /** Interface of the package admin */
-    private static String PACKAGE_ADMIN_NAME = PackageAdmin.class.getName();
-
-    /** Interface of the start level */
-    private static String START_LEVEL_NAME = StartLevel.class.getName();
-
-    /** Tracker for the package admin. */
-    private ServiceTracker packageAdminTracker;
-
-    /** Tracker for the start level service. */
-    private ServiceTracker startLevelTracker;
+    /** Support service for the tasks */
+    private TaskSupport taskSupport;
 
     /** The bundle context. */
     private BundleContext bundleContext;
@@ -88,11 +72,7 @@ public class BundleTaskCreator
         this.bundleContext.addBundleListener(this);
         this.bundleContext.addFrameworkListener(this);
 
-        // create and start tracker
-        this.packageAdminTracker = new ServiceTracker(bc, PACKAGE_ADMIN_NAME, null);
-        this.packageAdminTracker.open();
-        this.startLevelTracker = new ServiceTracker(bc, START_LEVEL_NAME, null);
-        this.startLevelTracker.open();
+        this.taskSupport = new TaskSupport(bc);
     }
 
     /**
@@ -103,13 +83,9 @@ public class BundleTaskCreator
             this.bundleContext.removeBundleListener(this);
             this.bundleContext.removeFrameworkListener(this);
         }
-        if ( this.packageAdminTracker != null ) {
-            this.packageAdminTracker.close();
-            this.packageAdminTracker = null;
-        }
-        if ( this.startLevelTracker != null ) {
-            this.startLevelTracker.close();
-            this.startLevelTracker = null;
+        if ( this.taskSupport != null ) {
+            this.taskSupport.deactivate();
+            this.taskSupport = null;
         }
     }
 
@@ -141,18 +117,6 @@ public class BundleTaskCreator
         return "Apache Sling Bundle Install Task Factory";
     }
 
-    public BundleContext getBundleContext() {
-        return this.bundleContext;
-    }
-
-    public StartLevel getStartLevel() {
-        return (StartLevel) this.startLevelTracker.getService();
-    }
-
-    public PackageAdmin getPackageAdmin() {
-        return (PackageAdmin)this.packageAdminTracker.getService();
-    }
-
 	/**
      * Create a bundle task - install, update or remove
      *
@@ -204,7 +168,7 @@ public class BundleTaskCreator
 	                    logger.debug("Prevent completely uninstalling installer bundle {}", symbolicName);
 	                    result = new ChangeStateTask(resourceList, ResourceState.UNINSTALLED);
 	                } else {
-	                    result = new BundleRemoveTask(resourceList, this);
+	                    result = new BundleRemoveTask(resourceList, this.taskSupport);
 	                }
 	            }
 		    } else {
@@ -215,69 +179,74 @@ public class BundleTaskCreator
 
 		// Install
 		} else {
-		    // for install and update, we want the bundle with the highest version
-	        final BundleInfo info = this.getBundleInfo(symbolicName, null);
-		    // check if we should start the bundle as we installed it in the previous run
-		    if (info == null) {
-			    // bundle is not installed yet: install
-			    result = new BundleInstallTask(resourceList, this);
-		    } else if ( toActivate.getAttribute(ATTR_START) != null ) {
-	            result = new BundleStartTask(resourceList, info.id, this);
-			} else {
-	            boolean doUpdate = false;
-
-	            final Version newVersion = new Version((String)toActivate.getAttribute(Constants.BUNDLE_VERSION));
-			    final int compare = info.version.compareTo(newVersion);
-                if (compare < 0) {
-                    // installed version is lower -> update
-                    doUpdate = true;
-                } else if (compare > 0) {
-                    final String forceVersion = (String) toActivate.getAttribute(FORCE_INSTALL_VERSION);
-                    if ( forceVersion != null && info.version.compareTo(new Version(forceVersion)) == 0 ) {
+		    // check for installer and system update
+		    final Integer asyncTaskCounter = (Integer)toActivate.getAttribute(InstallTask.ASYNC_ATTR_NAME);
+		    if ( asyncTaskCounter != null ) {
+                if ( isInstallerCoreBundle ) {
+                    result = new InstallerBundleUpdateTask(resourceList, this.taskSupport);
+                } else {
+                    // system bundle
+                    result = new ChangeStateTask(resourceList, ResourceState.INSTALLED, null,
+                                    new String[] {InstallTask.ASYNC_ATTR_NAME});
+                }
+		    } else {
+    		    // for install and update, we want the bundle with the highest version
+    	        final BundleInfo info = this.getBundleInfo(symbolicName, null);
+
+    		    // check if we should start the bundle as we installed it in the previous run
+    		    if (info == null) {
+    			    // bundle is not installed yet: install
+    			    result = new BundleInstallTask(resourceList, this.taskSupport);
+    		    } else if ( BundleUtil.isBundleStart(toActivate) ) {
+    	            result = new BundleStartTask(resourceList, info.id, this.taskSupport);
+    			} else {
+    	            boolean doUpdate = false;
+
+    	            final Version newVersion = new Version((String)toActivate.getAttribute(Constants.BUNDLE_VERSION));
+    			    final int compare = info.version.compareTo(newVersion);
+                    if (compare < 0) {
+                        // installed version is lower -> update
                         doUpdate = true;
-                    } else {
-                        logger.debug("Bundle " + info.symbolicName + " " + newVersion
-                                    + " is not installed, bundle with higher version is already installed.");
-                    }
-			    } else if (compare == 0 && BundleInfo.isSnapshot(newVersion)) {
-			        // check if system bundle or installer bundle
-			        if ( isInstallerCoreBundle || Constants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(symbolicName) ) {
-			            if ( toActivate.getAttribute(SPECIAL_ATTR) != null ) {
-			                toActivate.setAttribute(SPECIAL_ATTR, null);
-			                result = new ChangeStateTask(resourceList, ResourceState.INSTALLED);
-			                return result;
+                    } else if (compare > 0) {
+                        final String forceVersion = (String) toActivate.getAttribute(FORCE_INSTALL_VERSION);
+                        if ( forceVersion != null && info.version.compareTo(new Version(forceVersion)) == 0 ) {
+                            doUpdate = true;
+                        } else {
+                            logger.debug("Bundle " + info.symbolicName + " " + newVersion
+                                        + " is not installed, bundle with higher version is already installed.");
+                        }
+    			    } else if (compare == 0 && BundleInfo.isSnapshot(newVersion)) {
+
+                        // installed, same version but SNAPSHOT
+    			        doUpdate = true;
+    			    }
+                    if (doUpdate) {
+
+                        logger.debug("Scheduling update of {}", toActivate);
+                        // check if this is the system bundle
+                        if ( Constants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(symbolicName) ) {
+                            result = new SystemBundleUpdateTask(resourceList, this.taskSupport);
+                            // check if this is a installer update
+                        } else if ( isInstallerCoreBundle ) {
+                            result = new InstallerBundleUpdateTask(resourceList, this.taskSupport);
+                        } else {
+                            result = new BundleUpdateTask(resourceList, this.taskSupport);
                         }
-		                toActivate.setAttribute(SPECIAL_ATTR, "installingsnapshot");
-			        }
-			        // installed, same version but SNAPSHOT
-			        doUpdate = true;
-			    }
-                if (doUpdate) {
-
-                    logger.debug("Scheduling update of {}", toActivate);
-                    // check if this is the system bundle
-                    if ( Constants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(symbolicName) ) {
-                        result = new SystemBundleUpdateTask(resourceList, this);
-                        // check if this is a installer update
-                    } else if ( isInstallerCoreBundle ) {
-                        result = new InstallerBundleUpdateTask(resourceList, this);
+                    } else if ( compare == 0 && (isInstallerCoreBundle || Constants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(symbolicName)) ) {
+                        // the installer core bundle / system bundle has been updated, just set state
+                        result = new ChangeStateTask(resourceList, ResourceState.INSTALLED);
                     } else {
-                        result = new BundleUpdateTask(resourceList, this);
+                        logger.debug("Nothing to install for {}, same version {} already installed.", toActivate, newVersion);
+                        result = new ChangeStateTask(resourceList, ResourceState.IGNORED);
                     }
-                } else if ( compare == 0 && (isInstallerCoreBundle || Constants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(symbolicName)) ) {
-                    // the installer core bundle / system bundle has been updated, just set state
-                    result = new ChangeStateTask(resourceList, ResourceState.INSTALLED);
-                } else {
-                    logger.debug("Nothing to install for {}, same version {} already installed.", toActivate, newVersion);
-                    result = new ChangeStateTask(resourceList, ResourceState.IGNORED);
-                }
-			}
-		    toActivate.setAttribute(FORCE_INSTALL_VERSION, null);
+    			}
+		    }
+            toActivate.setAttribute(FORCE_INSTALL_VERSION, null);
 		}
 		return result;
 	}
 
     protected BundleInfo getBundleInfo(final String symbolicName, final String version) {
-        return BundleInfo.getBundleInfo(this.getBundleContext(), symbolicName, version);
+        return BundleInfo.getBundleInfo(this.bundleContext, symbolicName, version);
     }
 }

Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleUpdateTask.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleUpdateTask.java?rev=1363918&r1=1363917&r2=1363918&view=diff
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleUpdateTask.java (original)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleUpdateTask.java Fri Jul 20 19:53:22 2012
@@ -32,12 +32,10 @@ import org.osgi.service.startlevel.Start
  */
 public class BundleUpdateTask extends AbstractBundleTask {
 
-    private static final String BUNDLE_UPDATE_ORDER = "40-";
-
-    private boolean canRetry = true;
+    private static final String BUNDLE_UPDATE_ORDER = "50-";
 
     public BundleUpdateTask(final TaskResourceGroup r,
-                            final BundleTaskCreator creator) {
+                            final TaskSupport creator) {
         super(r, creator);
     }
 
@@ -47,8 +45,8 @@ public class BundleUpdateTask extends Ab
      * is in the starting state and has the lazy activation policy.
      * Or if the bundle is a fragment, it's considered active as well
      */
-    protected boolean isBundleActive(final Bundle b) {
-        if ( super.isBundleActive(b) ) {
+    private boolean isBundleActive(final Bundle b) {
+        if ( BundleUtil.isBundleActive(b) ) {
             return true;
         }
         final StartLevel startLevelService = this.getStartLevel();
@@ -58,7 +56,7 @@ public class BundleUpdateTask extends Ab
     /**
      * @see org.apache.sling.installer.api.tasks.InstallTask#execute(org.apache.sling.installer.api.tasks.InstallationContext)
      */
-    public void execute(InstallationContext ctx) {
+    public void execute(final InstallationContext ctx) {
         final String symbolicName = (String)getResource().getAttribute(Constants.BUNDLE_SYMBOLICNAME);
         final Bundle b = BundleInfo.getMatchingBundle(this.getBundleContext(), symbolicName, null);
         if (b == null) {
@@ -103,27 +101,33 @@ public class BundleUpdateTask extends Ab
             ctx.log("Updated bundle {} from resource {}", b, getResource());
 
             if (reactivate) {
-                if ( isSystemBundleFragment(b) ) {
+                if ( BundleUtil.isSystemBundleFragment(b) ) {
                     this.setFinishedState(ResourceState.INSTALLED);
-                    ctx.addTaskToCurrentCycle(new SystemBundleUpdateTask(null, this.getCreator()));
-                } else if ( this.getFragmentHostHeader(b) != null ) {
-                    // if this is a fragment, we're done after a refresh
-                    this.getPackageAdmin().refreshPackages(new Bundle[] {b});
+                    ctx.addTaskToCurrentCycle(new SystemBundleUpdateTask(null, this.getTaskSupport()));
+                } else if ( BundleUtil.getFragmentHostHeader(b) != null ) {
+                    // if this is a fragment, we're done after a refresh of the host
+                    final String fragmentHostHeader = BundleUtil.getFragmentHostHeader(b);
+                    this.getLogger().debug("Need to do a refresh of the bundle's host");
+                    for (final Bundle bundle : this.getBundleContext().getBundles()) {
+                        if (fragmentHostHeader.equals(bundle.getSymbolicName())) {
+                            this.getLogger().debug("Found host bundle to refresh {}", bundle.getBundleId());
+                            RefreshBundlesTask.markBundleForRefresh(ctx, this.getTaskSupport(), bundle);
+                            break;
+                        }
+                    }
                     this.setFinishedState(ResourceState.INSTALLED);
                 } else {
-                    this.getResource().setAttribute(BundleTaskCreator.ATTR_START, "true");
-                    ctx.addTaskToCurrentCycle(new BundleStartTask(this.getResourceGroup(), b.getBundleId(), this.getCreator()));
-                    ctx.addTaskToCurrentCycle(new SynchronousRefreshPackagesTask(this.getCreator()));
+                    BundleUtil.markBundleStart(this.getResource());
+                    RefreshBundlesTask.markBundleForRefresh(ctx, this.getTaskSupport(), b);
+                    ctx.addTaskToCurrentCycle(new BundleStartTask(this.getResourceGroup(), b.getBundleId(), this.getTaskSupport()));
                 }
             } else {
                 this.setFinishedState(ResourceState.INSTALLED);
             }
             this.getLogger().debug("Bundle updated: {}/{}", b.getBundleId(), b.getSymbolicName());
-    	} catch (Exception e) {
-            if ( !canRetry ) {
-                this.getLogger().warn("Removing failing tasks - unable to retry: " + this, e);
-                this.setFinishedState(ResourceState.IGNORED);
-            }
+    	} catch (final Exception e) {
+            this.getLogger().warn("Removing failing tasks - unable to retry: " + this, e);
+            this.setFinishedState(ResourceState.IGNORED);
     	}
     }
 
@@ -132,9 +136,4 @@ public class BundleUpdateTask extends Ab
         return BUNDLE_UPDATE_ORDER + getSortableStartLevel() + "-" + getResource().getEntityId();
     }
 
-    private boolean isSystemBundleFragment(final Bundle installedBundle) {
-        final String fragmentHeader = this.getFragmentHostHeader(installedBundle);
-        return fragmentHeader != null
-            && fragmentHeader.indexOf(Constants.EXTENSION_DIRECTIVE) > 0;
-    }
 }
\ No newline at end of file

Added: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleUtil.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleUtil.java?rev=1363918&view=auto
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleUtil.java (added)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleUtil.java Fri Jul 20 19:53:22 2012
@@ -0,0 +1,76 @@
+/*
+ * 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.sling.installer.core.impl.tasks;
+
+import org.apache.sling.installer.api.tasks.TaskResource;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+
+public abstract class BundleUtil {
+
+    private static final String ATTR_START = "sling.osgi.installer.start.bundle";
+
+    public static void markBundleStart(final TaskResource rsrc) {
+        rsrc.setAttribute(ATTR_START, "true");
+    }
+
+    public static boolean isBundleStart(final TaskResource rsrc) {
+        return rsrc.getAttribute(ATTR_START) != null;
+    }
+
+    public static void clearBundleStart(final TaskResource rsrc) {
+        rsrc.setAttribute(ATTR_START, null);
+    }
+
+    public static boolean isSystemBundleFragment(final Bundle installedBundle) {
+        final String fragmentHeader = getFragmentHostHeader(installedBundle);
+        return fragmentHeader != null
+            && fragmentHeader.indexOf(Constants.EXTENSION_DIRECTIVE) > 0;
+    }
+
+    /**
+     * Check if the bundle is active.
+     * This is true if the bundle has the active state or of the bundle
+     * is in the starting state and has the lazy activation policy.
+     * Or if the bundle is a fragment, it's considered active as well
+     */
+    public static boolean isBundleActive(final Bundle b) {
+        if ( b.getState() == Bundle.ACTIVE ) {
+            return true;
+        }
+        if ( b.getState() == Bundle.STARTING && isLazyActivatian(b) ) {
+            return true;
+        }
+        return ( getFragmentHostHeader(b) != null );
+    }
+
+    /**
+     * Gets the bundle's Fragment-Host header.
+     */
+    public static String getFragmentHostHeader(final Bundle b) {
+        return (String) b.getHeaders().get( Constants.FRAGMENT_HOST );
+    }
+
+    /**
+     * Check if the bundle has the lazy activation policy
+     */
+    public static boolean isLazyActivatian(final Bundle b) {
+        return Constants.ACTIVATION_LAZY.equals(b.getHeaders().get(Constants.BUNDLE_ACTIVATIONPOLICY));
+    }
+}

Propchange: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleUtil.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleUtil.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleUtil.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/InstallerBundleUpdateTask.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/InstallerBundleUpdateTask.java?rev=1363918&r1=1363917&r2=1363918&view=diff
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/InstallerBundleUpdateTask.java (original)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/InstallerBundleUpdateTask.java Fri Jul 20 19:53:22 2012
@@ -20,62 +20,58 @@ package org.apache.sling.installer.core.
 
 import org.apache.sling.installer.api.tasks.InstallTask;
 import org.apache.sling.installer.api.tasks.InstallationContext;
+import org.apache.sling.installer.api.tasks.ResourceState;
 import org.apache.sling.installer.api.tasks.TaskResourceGroup;
 import org.apache.sling.installer.core.impl.AbstractInstallTask;
 import org.osgi.framework.Bundle;
-import org.osgi.service.packageadmin.PackageAdmin;
 
 /**
  * Update the installer itself
  */
 public class InstallerBundleUpdateTask extends AbstractInstallTask {
 
-    private static final String BUNDLE_UPDATE_ORDER = "98-";
+    private static final String BUNDLE_UPDATE_ORDER = "02-";
 
-    private final BundleTaskCreator creator;
+    private final TaskSupport taskSupport;
+
+    private final Integer count;
 
     public InstallerBundleUpdateTask(final TaskResourceGroup r,
-                                     final BundleTaskCreator creator) {
+                                     final TaskSupport taskSupport) {
         super(r);
-        this.creator = creator;
+        this.taskSupport = taskSupport;
+        this.count = (Integer)this.getResource().getAttribute(InstallTask.ASYNC_ATTR_NAME);
     }
 
     /**
      * @see org.apache.sling.installer.api.tasks.InstallTask#execute(org.apache.sling.installer.api.tasks.InstallationContext)
      */
     public void execute(final InstallationContext ctx) {
-        final Bundle b = this.creator.getBundleContext().getBundle();
-        final PackageAdmin pa = this.creator.getPackageAdmin();
-
-        ctx.addAsyncTask(new InstallTask(this.getResourceGroup()) {
-
-            @Override
-            public String getSortKey() {
-                return BUNDLE_UPDATE_ORDER + getResource().getEntityId();
+        final Bundle b = this.taskSupport.getBundleContext().getBundle();
+        if ( this.count == null ) {
+            // first step: update bundle
+
+            try {
+                b.update(getResource().getInputStream());
+                ctx.log("Updated bundle {} from resource {}", b, getResource());
+            } catch (final Exception e) {
+                getLogger().warn("Removing failing tasks - unable to retry: " + this, e);
+                this.setFinishedState(ResourceState.IGNORED);
+                ctx.asyncTaskFailed(this);
             }
+        } else if ( this.count == 1 ) {
+            // second step: refresh
+            this.taskSupport.getPackageAdmin().refreshPackages(new Bundle[] {b});
+        } else {
+            // finished
+            this.getResource().setAttribute(ASYNC_ATTR_NAME, null);
+            this.setFinishedState(ResourceState.INSTALLED);
+        }
+    }
 
-            @Override
-            public void execute(final InstallationContext ctx) {
-                try {
-                    b.update(getResource().getInputStream());
-                    ctx.log("Updated bundle {} from resource {}", b, getResource());
-
-                    if ( pa != null ) {
-                        // wait for asynchronous bundle start tasks to finish
-                        try {
-                            Thread.sleep(2000L);
-                        } catch (final InterruptedException ignore) {
-                            // just ignore
-                        }
-
-                        pa.refreshPackages( new Bundle[] { b } );
-                    }
-                    getLogger().debug("Bundle updated: {}/{}", b.getBundleId(), b.getSymbolicName());
-                } catch (final Exception e) {
-                    getLogger().warn("Removing failing tasks - unable to retry: " + this, e);
-                }
-            }
-        });
+    @Override
+    public boolean isAsynchronousTask() {
+        return this.count == null || this.count == 1;
     }
 
     @Override

Added: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/RefreshBundlesTask.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/RefreshBundlesTask.java?rev=1363918&view=auto
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/RefreshBundlesTask.java (added)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/RefreshBundlesTask.java Fri Jul 20 19:53:22 2012
@@ -0,0 +1,84 @@
+/*
+ * 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.sling.installer.core.impl.tasks;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.sling.installer.api.tasks.InstallationContext;
+import org.osgi.framework.Bundle;
+
+/**
+ * Refresh a set of bundles.
+ */
+public class RefreshBundlesTask extends AbstractBundleTask {
+
+    private static final String REFRESH_PACKAGES_ORDER = "60-";
+
+    /** Global set of bundles to refresh. */
+    private static final Set<Long> BUNDLE_IDS = new HashSet<Long>();
+
+    public static void markBundleForRefresh(final InstallationContext ctx,
+                    final TaskSupport btc,
+                    final Bundle bundle) {
+        synchronized ( BUNDLE_IDS ) {
+            BUNDLE_IDS.add(bundle.getBundleId());
+            ctx.addTaskToCurrentCycle(new RefreshBundlesTask(btc));
+        }
+    }
+
+    public RefreshBundlesTask(final TaskSupport btc) {
+	    super(null, btc);
+	}
+
+	@Override
+	public String getSortKey() {
+		return REFRESH_PACKAGES_ORDER;
+	}
+
+	@Override
+	public String toString() {
+		return getClass().getSimpleName();
+	}
+
+    /**
+     * @see org.apache.sling.installer.api.tasks.InstallTask#execute(org.apache.sling.installer.api.tasks.InstallationContext)
+     */
+    public void execute(final InstallationContext ctx) {
+        final List<Bundle> bundles = new ArrayList<Bundle>();
+        synchronized ( BUNDLE_IDS ) {
+            for(final Long id : BUNDLE_IDS) {
+                final Bundle b = this.getBundleContext().getBundle(id);
+                if ( b != null ) {
+                    getLogger().debug("Refreshing bundle {}", b);
+                    bundles.add(b);
+                } else {
+                    getLogger().debug("Unable to refresh bundle {} - already gone.", id);
+                }
+            }
+            BUNDLE_IDS.clear();
+        }
+        if ( bundles.size() > 0 ) {
+            ctx.log("Refreshing bundles {}", bundles);
+            this.getPackageAdmin().refreshPackages(bundles.toArray(new Bundle[bundles.size()]));
+        }
+	}
+}

Propchange: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/RefreshBundlesTask.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/RefreshBundlesTask.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/RefreshBundlesTask.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/RefreshOptionalPackagesTask.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/RefreshOptionalPackagesTask.java?rev=1363918&r1=1363917&r2=1363918&view=diff
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/RefreshOptionalPackagesTask.java (original)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/RefreshOptionalPackagesTask.java Fri Jul 20 19:53:22 2012
@@ -41,11 +41,11 @@ public class RefreshOptionalPackagesTask
     private static final String MARKER = DIRECTIVE + ":=" + DIRECTIVE_OPTIONAL;
 
     /** Tracker for the package admin. */
-    private final BundleTaskCreator bundleTaskCreator;
+    private final TaskSupport taskSupport;
 
-	public RefreshOptionalPackagesTask(final BundleTaskCreator bundleTaskCreator) {
+	public RefreshOptionalPackagesTask(final TaskSupport taskSupport) {
 	    super(null);
-	    this.bundleTaskCreator = bundleTaskCreator;
+	    this.taskSupport = taskSupport;
 	}
 
 	@Override
@@ -58,20 +58,16 @@ public class RefreshOptionalPackagesTask
 		return getClass().getSimpleName();
 	}
 
-    private PackageAdmin getPackageAdmin() {
-        return this.bundleTaskCreator.getPackageAdmin();
-    }
-
     /**
      * @see org.apache.sling.installer.api.tasks.InstallTask#execute(org.apache.sling.installer.api.tasks.InstallationContext)
      */
     public void execute(final InstallationContext ctx) {
         getLogger().info("** Invoking refresh optional packages!");
-        final PackageAdmin packageAdmin = this.getPackageAdmin();
+        final PackageAdmin packageAdmin = this.taskSupport.getPackageAdmin();
 
         ExportedPackage[] exports = null;
         final List<Bundle> refreshBundles = new ArrayList<Bundle>();
-        final Bundle[] bundles = this.bundleTaskCreator.getBundleContext().getBundles();
+        final Bundle[] bundles = this.taskSupport.getBundleContext().getBundles();
         for(final Bundle bundle : bundles) {
             if ( bundle.getState() == Bundle.RESOLVED || bundle.getState() == Bundle.ACTIVE ) {
                 final String importHeader = (String)bundle.getHeaders().get(Constants.IMPORT_PACKAGE);

Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/SystemBundleUpdateTask.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/SystemBundleUpdateTask.java?rev=1363918&r1=1363917&r2=1363918&view=diff
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/SystemBundleUpdateTask.java (original)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/SystemBundleUpdateTask.java Fri Jul 20 19:53:22 2012
@@ -21,7 +21,6 @@ package org.apache.sling.installer.core.
 import java.io.IOException;
 import java.io.InputStream;
 
-import org.apache.sling.installer.api.tasks.InstallTask;
 import org.apache.sling.installer.api.tasks.InstallationContext;
 import org.apache.sling.installer.api.tasks.ResourceState;
 import org.apache.sling.installer.api.tasks.TaskResourceGroup;
@@ -34,80 +33,60 @@ import org.osgi.framework.BundleExceptio
  */
 public class SystemBundleUpdateTask extends AbstractInstallTask {
 
-    private static final String BUNDLE_UPDATE_ORDER = "99-";
+    private static final String BUNDLE_UPDATE_ORDER = "01-";
 
     private static final String SYSTEM_BUNDLE_UPDATE_ORDER = BUNDLE_UPDATE_ORDER + "systembundle(0)";
 
-    private final BundleTaskCreator creator;
+    private final TaskSupport taskSupport;
 
     public SystemBundleUpdateTask(final TaskResourceGroup r,
-            final BundleTaskCreator creator) {
+            final TaskSupport taskSupport) {
         super(r);
-        this.creator = creator;
+        this.taskSupport = taskSupport;
     }
 
     @Override
     public void execute(final InstallationContext ctx) {
-        final Bundle systemBundle = this.creator.getBundleContext().getBundle(0);
+        final Bundle systemBundle = this.taskSupport.getBundleContext().getBundle(0);
         // sanity check
         if ( systemBundle == null ) {
+            this.setFinishedState(ResourceState.IGNORED);
+            ctx.asyncTaskFailed(this);
             return;
         }
 
         // restart system bundle
         if ( this.getResource() == null ) {
-            // do an async update
-            ctx.addAsyncTask(new InstallTask(this.getResourceGroup()) {
-
-                @Override
-                public String getSortKey() {
-                    return SYSTEM_BUNDLE_UPDATE_ORDER;
-                }
-
-                @Override
-                public void execute(final InstallationContext ctx) {
-                    try {
-                        systemBundle.update();
-                    } catch (final BundleException e) {
-                        getLogger().warn("Updating system bundle failed - unable to retry: " + this, e);
-                    }
-                }
-            });
+            try {
+                systemBundle.update();
+            } catch (final BundleException e) {
+                getLogger().warn("Updating system bundle failed - unable to retry: " + this, e);
+                this.setFinishedState(ResourceState.IGNORED);
+                ctx.asyncTaskFailed(this);
+            }
         } else {
             InputStream is = null;
             try {
                 is = getResource().getInputStream();
                 if (is == null) {
-                    throw new IllegalStateException(
-                            "RegisteredResource provides null InputStream, cannot update bundle: "
+                    getLogger().warn(
+                            "RegisteredResource provides null InputStream, cannot update system bundle: "
                             + getResource());
-                }
-                // delayed system bundle update
-                final InputStream backgroundIS = is;
-                is = null;
-                ctx.addAsyncTask(new InstallTask(this.getResourceGroup()) {
-
-                    @Override
-                    public String getSortKey() {
-                        return BUNDLE_UPDATE_ORDER + getResource().getURL();
-                    }
-
-                    @Override
-                    public void execute(final InstallationContext ctx) {
-                        try {
-                            systemBundle.update(backgroundIS);
-                        } catch (final BundleException e) {
-                            getLogger().warn("Updating system bundle failed - unable to retry: " + this, e);
-                        } finally {
-                            try {
-                                backgroundIS.close();
-                            } catch (final IOException ignore) {}
-                        }
+                    this.setFinishedState(ResourceState.IGNORED);
+                    ctx.asyncTaskFailed(this);
+                } else {
+                    try {
+                        systemBundle.update(is);
+                    } catch (final BundleException e) {
+                        getLogger().warn("Updating system bundle failed - unable to retry: " + this, e);
+                        this.setFinishedState(ResourceState.IGNORED);
+                        ctx.asyncTaskFailed(this);
                     }
-                });
+                }
             } catch (final IOException e) {
-                this.getLogger().warn("Removing failing tasks - unable to retry: " + this, e);
+                this.getLogger().warn("Removing failing task - unable to retry: " + this, e);
                 this.setFinishedState(ResourceState.IGNORED);
+                ctx.asyncTaskFailed(this);
             } finally {
                 if ( is != null ) {
                     try {
@@ -119,6 +98,11 @@ public class SystemBundleUpdateTask exte
     }
 
     @Override
+    public boolean isAsynchronousTask() {
+        return true;
+    }
+
+    @Override
     public String getSortKey() {
         if ( getResource() == null ) {
             return SYSTEM_BUNDLE_UPDATE_ORDER;

Added: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/TaskSupport.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/TaskSupport.java?rev=1363918&view=auto
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/TaskSupport.java (added)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/TaskSupport.java Fri Jul 20 19:53:22 2012
@@ -0,0 +1,80 @@
+/*
+ * 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.sling.installer.core.impl.tasks;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.service.packageadmin.PackageAdmin;
+import org.osgi.service.startlevel.StartLevel;
+import org.osgi.util.tracker.ServiceTracker;
+
+/**
+ * Support class for the tasks.
+ */
+public class TaskSupport {
+
+    /** Interface of the package admin */
+    private static String PACKAGE_ADMIN_NAME = PackageAdmin.class.getName();
+
+    /** Interface of the start level */
+    private static String START_LEVEL_NAME = StartLevel.class.getName();
+
+    /** Tracker for the package admin. */
+    private final ServiceTracker packageAdminTracker;
+
+    /** Tracker for the start level service. */
+    private final ServiceTracker startLevelTracker;
+
+    /** The bundle context. */
+    private final BundleContext bundleContext;
+
+    public TaskSupport(final BundleContext bc) {
+        this.bundleContext = bc;
+
+        // create and start tracker
+        this.packageAdminTracker = new ServiceTracker(bc, PACKAGE_ADMIN_NAME, null);
+        this.packageAdminTracker.open();
+        this.startLevelTracker = new ServiceTracker(bc, START_LEVEL_NAME, null);
+        this.startLevelTracker.open();
+    }
+
+    /**
+     * Deactivate this helper.
+     */
+    public void deactivate() {
+        if ( this.packageAdminTracker != null ) {
+            this.packageAdminTracker.close();
+        }
+        if ( this.startLevelTracker != null ) {
+            this.startLevelTracker.close();
+        }
+    }
+
+    public BundleContext getBundleContext() {
+        return this.bundleContext;
+    }
+
+    public StartLevel getStartLevel() {
+        return (StartLevel) this.startLevelTracker.getService();
+    }
+
+    public PackageAdmin getPackageAdmin() {
+        return (PackageAdmin)this.packageAdminTracker.getService();
+    }
+
+}

Propchange: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/TaskSupport.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/TaskSupport.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/TaskSupport.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: sling/trunk/installer/core/src/test/java/org/apache/sling/installer/core/impl/TaskOrderingTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/test/java/org/apache/sling/installer/core/impl/TaskOrderingTest.java?rev=1363918&r1=1363917&r2=1363918&view=diff
==============================================================================
--- sling/trunk/installer/core/src/test/java/org/apache/sling/installer/core/impl/TaskOrderingTest.java (original)
+++ sling/trunk/installer/core/src/test/java/org/apache/sling/installer/core/impl/TaskOrderingTest.java Fri Jul 20 19:53:22 2012
@@ -34,7 +34,7 @@ import org.apache.sling.installer.core.i
 import org.apache.sling.installer.core.impl.tasks.BundleStartTask;
 import org.apache.sling.installer.core.impl.tasks.BundleUpdateTask;
 import org.apache.sling.installer.core.impl.tasks.MockInstallationListener;
-import org.apache.sling.installer.core.impl.tasks.SynchronousRefreshPackagesTask;
+import org.apache.sling.installer.core.impl.tasks.RefreshBundlesTask;
 
 /** Test the ordering and duplicates elimination of
  * 	OsgiControllerTasks
@@ -85,10 +85,10 @@ public class TaskOrderingTest {
 		int testIndex = 1;
 		final InstallTask [] tasksInOrder = {
 		    new BundleRemoveTask(getRegisteredResource("test:url"), null),
+            new BundleInstallTask(getRegisteredResource("test:url"), null),
 		    new BundleUpdateTask(getRegisteredResource("test:url"), null),
-		    new BundleInstallTask(getRegisteredResource("test:url"), null),
-			new SynchronousRefreshPackagesTask(null),
-			new BundleStartTask(null, 0, null),
+            new RefreshBundlesTask(null),
+			new BundleStartTask(null, 0, null)
 		};
 
 		taskSet.clear();
@@ -134,8 +134,8 @@ public class TaskOrderingTest {
 		final InstallTask [] tasksInOrder = {
 			new BundleInstallTask(getRegisteredResource("test:someURIa.nothing"), null),
             new BundleInstallTask(getRegisteredResource("test:someURIb.nothing"), null),
-			new SynchronousRefreshPackagesTask(null),
-			new BundleStartTask(null, 0, null),
+            new RefreshBundlesTask(null),
+			new BundleStartTask(null, 0, null)
 		};
 
 		taskSet.clear();
@@ -158,31 +158,31 @@ public class TaskOrderingTest {
 		int testIndex = 1;
 		final InstallTask [] tasksInOrder = {
 		    new BundleRemoveTask(getRegisteredResource("test:url"), null),
-			new SynchronousRefreshPackagesTask(null),
+            new RefreshBundlesTask(null),
 			new BundleStartTask(null, 0, null),
-			new BundleStartTask(null, 1, null),
+			new BundleStartTask(null, 1, null)
 		};
 
 		taskSet.clear();
 		taskSet.add(tasksInOrder[3]);
 		taskSet.add(tasksInOrder[3]);
-		taskSet.add(new SynchronousRefreshPackagesTask(null));
+		taskSet.add(new RefreshBundlesTask(null));
 		taskSet.add(tasksInOrder[2]);
 		taskSet.add(tasksInOrder[2]);
 		taskSet.add(tasksInOrder[1]);
-		taskSet.add(new SynchronousRefreshPackagesTask(null));
-		taskSet.add(new SynchronousRefreshPackagesTask(null));
+		taskSet.add(new RefreshBundlesTask(null));
+		taskSet.add(new RefreshBundlesTask(null));
 		taskSet.add(tasksInOrder[0]);
 		taskSet.add(tasksInOrder[3]);
-		taskSet.add(new SynchronousRefreshPackagesTask(null));
+		taskSet.add(new RefreshBundlesTask(null));
 		taskSet.add(tasksInOrder[3]);
 		taskSet.add(tasksInOrder[2]);
-		taskSet.add(new SynchronousRefreshPackagesTask(null));
+		taskSet.add(new RefreshBundlesTask(null));
 		taskSet.add(tasksInOrder[2]);
 		taskSet.add(tasksInOrder[1]);
-		taskSet.add(new SynchronousRefreshPackagesTask(null));
+		taskSet.add(new RefreshBundlesTask(null));
 		taskSet.add(tasksInOrder[1]);
-		taskSet.add(new SynchronousRefreshPackagesTask(null));
+		taskSet.add(new RefreshBundlesTask(null));
 
 		assertOrder(testIndex++, taskSet, tasksInOrder);
 	}