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/19 13:36:10 UTC

svn commit: r1363303 - in /sling/trunk/installer/core: ./ src/main/java/org/apache/sling/installer/api/info/ src/main/java/org/apache/sling/installer/core/impl/ src/main/java/org/apache/sling/installer/core/impl/console/

Author: cziegeler
Date: Thu Jul 19 11:36:09 2012
New Revision: 1363303

URL: http://svn.apache.org/viewvc?rev=1363303&view=rev
Log:
SLING-2528 : Allow resources to be queried from the OSGi Installer service

Added:
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/info/
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/info/InfoProvider.java   (with props)
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/info/InstallationState.java   (with props)
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/info/Resource.java   (with props)
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/info/ResourceGroup.java   (with props)
Modified:
    sling/trunk/installer/core/pom.xml
    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/OsgiInstallerImpl.java
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/console/OsgiInstallerWebConsolePlugin.java

Modified: sling/trunk/installer/core/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/pom.xml?rev=1363303&r1=1363302&r2=1363303&view=diff
==============================================================================
--- sling/trunk/installer/core/pom.xml (original)
+++ sling/trunk/installer/core/pom.xml Thu Jul 19 11:36:09 2012
@@ -61,6 +61,7 @@
                         </DynamicImport-Package>
 						<Export-Package>
 							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
                         </Export-Package>

Added: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/info/InfoProvider.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/info/InfoProvider.java?rev=1363303&view=auto
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/info/InfoProvider.java (added)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/info/InfoProvider.java Thu Jul 19 11:36:09 2012
@@ -0,0 +1,35 @@
+/*
+ * 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.api.info;
+
+
+/**
+ * The info provider delivers information about the current state of the
+ * OSGi installer
+ *
+ * @since 1.0
+ */
+public interface InfoProvider {
+
+    /**
+     * Return the current installation state.
+     * The installation state is a snapshot of the state at method call time.
+     */
+    InstallationState getInstallationState();
+}

Propchange: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/info/InfoProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

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

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

Added: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/info/InstallationState.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/info/InstallationState.java?rev=1363303&view=auto
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/info/InstallationState.java (added)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/info/InstallationState.java Thu Jul 19 11:36:09 2012
@@ -0,0 +1,52 @@
+/*
+ * 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.api.info;
+
+import java.util.List;
+
+import org.apache.sling.installer.api.tasks.RegisteredResource;
+
+/**
+ * The state of the OSGi installer at a given time.
+ *
+ * @since 1.0
+ */
+public interface InstallationState {
+
+    /**
+     * Active resource groups
+     * These resource groups are currently in processing. The first resource
+     * of each group is being processing.
+     * @return All active resource groups
+     */
+    List<ResourceGroup> getActiveResources();
+
+    /**
+     * Installed resource groups
+     * These resources groups are processed.
+     * @return All installed resource groups
+     */
+    List<ResourceGroup> getInstalledResources();
+
+    /**
+     * Return all untransformed resources
+     * @return All untransformed resources.
+     */
+    List<RegisteredResource> getUntransformedResources();
+}

Propchange: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/info/InstallationState.java
------------------------------------------------------------------------------
    svn:eol-style = native

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

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

Added: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/info/Resource.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/info/Resource.java?rev=1363303&view=auto
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/info/Resource.java (added)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/info/Resource.java Thu Jul 19 11:36:09 2012
@@ -0,0 +1,50 @@
+/*
+ * 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.api.info;
+
+import org.apache.sling.installer.api.tasks.RegisteredResource;
+import org.apache.sling.installer.api.tasks.ResourceState;
+import org.osgi.framework.Version;
+
+
+/**
+ * A resource provides all relevant information about a registered
+ * resource.
+ *
+ * @since 1.0
+ */
+public interface Resource extends RegisteredResource {
+
+    /**
+     * Get the current state of the resource.
+     */
+    ResourceState getState();
+
+    /**
+     * Return the version of the artifact.
+     * @return The version of the artifact or <code>null</code>
+     */
+    Version getVersion();
+
+    /**
+     * When did the last change happen?
+     * @return -1 if no change , 0 if unknown, > 0 otherwise
+     */
+    long getLastChange();
+}

Propchange: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/info/Resource.java
------------------------------------------------------------------------------
    svn:eol-style = native

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

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

Added: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/info/ResourceGroup.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/info/ResourceGroup.java?rev=1363303&view=auto
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/info/ResourceGroup.java (added)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/info/ResourceGroup.java Thu Jul 19 11:36:09 2012
@@ -0,0 +1,41 @@
+/*
+ * 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.api.info;
+
+import java.util.List;
+
+/**
+ * This is a group of resources all pointing to the same artifact,
+ * but maybe in different versions or locations.
+ * @since 1.0
+ */
+public interface ResourceGroup {
+
+    /**
+     * Get all resources for this group.
+     * @return The list of resources.
+     */
+    List<Resource> getResources();
+
+    /**
+     * Get the current alias for this group.
+     * @return The alias or <code>null</code>
+     */
+    String getAlias();
+}

Propchange: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/info/ResourceGroup.java
------------------------------------------------------------------------------
    svn:eol-style = native

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

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

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=1363303&r1=1363302&r2=1363303&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 Thu Jul 19 11:36:09 2012
@@ -25,6 +25,7 @@ import java.util.List;
 
 import org.apache.sling.installer.api.OsgiInstaller;
 import org.apache.sling.installer.api.ResourceChangeListener;
+import org.apache.sling.installer.api.info.InfoProvider;
 import org.apache.sling.installer.api.tasks.InstallTaskFactory;
 import org.apache.sling.installer.api.tasks.ResourceTransformer;
 import org.apache.sling.installer.api.tasks.RetryHandler;
@@ -74,6 +75,7 @@ public class Activator implements Bundle
         this.osgiControllerService.start();
         final String [] serviceInterfaces = {
                 OsgiInstaller.class.getName(),
+                InfoProvider.class.getName(),
                 ResourceChangeListener.class.getName(),
                 RetryHandler.class.getName()
         };

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=1363303&r1=1363302&r2=1363303&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 Thu Jul 19 11:36:09 2012
@@ -23,6 +23,8 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.Dictionary;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -39,6 +41,10 @@ import org.apache.sling.installer.api.Os
 import org.apache.sling.installer.api.ResourceChangeListener;
 import org.apache.sling.installer.api.UpdateHandler;
 import org.apache.sling.installer.api.UpdateResult;
+import org.apache.sling.installer.api.info.InfoProvider;
+import org.apache.sling.installer.api.info.InstallationState;
+import org.apache.sling.installer.api.info.Resource;
+import org.apache.sling.installer.api.info.ResourceGroup;
 import org.apache.sling.installer.api.tasks.InstallTask;
 import org.apache.sling.installer.api.tasks.InstallTaskFactory;
 import org.apache.sling.installer.api.tasks.InstallationContext;
@@ -52,6 +58,7 @@ import org.apache.sling.installer.api.ta
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -66,7 +73,7 @@ import org.slf4j.LoggerFactory;
  */
 public class OsgiInstallerImpl
     extends Thread
-    implements OsgiInstaller, ResourceChangeListener, RetryHandler {
+    implements OsgiInstaller, ResourceChangeListener, RetryHandler, InfoProvider {
 
     /** The logger */
     private final Logger logger =  LoggerFactory.getLogger(this.getClass());
@@ -254,14 +261,6 @@ public class OsgiInstallerImpl
         }
     }
 
-    public Object getResourcesLock() {
-        return this.resourcesLock;
-    }
-
-    public PersistentResourceList getPersistentResourceList() {
-        return this.persistentList;
-    }
-
     /**
      * Create new installable resources for all installable resources.
      * The new versions has a set resource type.
@@ -972,4 +971,137 @@ public class OsgiInstallerImpl
         }
         return null;
     }
+
+    /**
+     * @see org.apache.sling.installer.api.info.InfoProvider#getInstallationState()
+     */
+    public InstallationState getInstallationState() {
+        synchronized ( this.resourcesLock ) {
+            final InstallationState state = new InstallationState() {
+
+                private final List<ResourceGroup> activeResources = new ArrayList<ResourceGroup>();
+                private final List<ResourceGroup> installedResources = new ArrayList<ResourceGroup>();
+                private final List<RegisteredResource> untransformedResources = new ArrayList<RegisteredResource>();
+
+                public List<ResourceGroup> getActiveResources() {
+                    return activeResources;
+                }
+
+                public List<ResourceGroup> getInstalledResources() {
+                    return installedResources;
+                }
+
+                public List<RegisteredResource> getUntransformedResources() {
+                    return untransformedResources;
+                }
+
+            };
+
+            for(final String entityId : this.persistentList.getEntityIds()) {
+                final EntityResourceList group = this.persistentList.getEntityResourceList(entityId);
+
+                final String alias = group.getAlias();
+                final List<Resource> resources = new ArrayList<Resource>();
+                for(final TaskResource tr : group.getResources()) {
+                    resources.add(new Resource() {
+
+                        public String getScheme() {
+                            return tr.getScheme();
+                        }
+
+                        public String getURL() {
+                            return tr.getURL();
+                        }
+
+                        public String getType() {
+                            return tr.getType();
+                        }
+
+                        public InputStream getInputStream() throws IOException {
+                            return tr.getInputStream();
+                        }
+
+                        public Dictionary<String, Object> getDictionary() {
+                            return tr.getDictionary();
+                        }
+
+                        public String getDigest() {
+                            return tr.getDigest();
+                        }
+
+                        public int getPriority() {
+                            return tr.getPriority();
+                        }
+
+                        public String getEntityId() {
+                            return tr.getEntityId();
+                        }
+
+                        public ResourceState getState() {
+                            return tr.getState();
+                        }
+
+                        public Version getVersion() {
+                            return tr.getVersion();
+                        }
+
+                        public long getLastChange() {
+                            return ((RegisteredResourceImpl)tr).getLastChange();
+                        }
+                    });
+                }
+                final ResourceGroup rg = new ResourceGroup() {
+
+                    public List<Resource> getResources() {
+                        return resources;
+                    }
+
+                    public String getAlias() {
+                        return alias;
+                    }
+                };
+                if ( group.getActiveResource() != null ) {
+                    state.getActiveResources().add(rg);
+                } else {
+                    state.getInstalledResources().add(rg);
+                }
+            }
+
+            Collections.sort(state.getActiveResources(), COMPARATOR);
+            Collections.sort(state.getInstalledResources(), COMPARATOR);
+
+            state.getUntransformedResources().addAll(this.persistentList.getUntransformedResources());
+
+            return state;
+        }
+    }
+
+    private static final Comparator<ResourceGroup> COMPARATOR = new Comparator<ResourceGroup>() {
+
+        public int compare(ResourceGroup o1, ResourceGroup o2) {
+            RegisteredResource r1 = null;
+            RegisteredResource r2 = null;
+            if ( o1.getResources().size() > 0 ) {
+                r1 = o1.getResources().iterator().next();
+            }
+            if ( o2.getResources().size() > 0 ) {
+                r2 = o2.getResources().iterator().next();
+            }
+            int result;
+            if ( r1 == null && r2 == null ) {
+                result = 0;
+            } else if ( r1 == null ) {
+                result = -1;
+            } else if ( r2 == null ) {
+                result = 1;
+            } else {
+                result = r1.getType().compareTo(r2.getType());
+                if ( result == 0 ) {
+                    result = r1.getEntityId().compareTo(r2.getEntityId());
+                }
+            }
+            return result;
+        }
+
+    };
 }
\ No newline at end of file

Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/console/OsgiInstallerWebConsolePlugin.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/console/OsgiInstallerWebConsolePlugin.java?rev=1363303&r1=1363302&r2=1363303&view=diff
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/console/OsgiInstallerWebConsolePlugin.java (original)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/console/OsgiInstallerWebConsolePlugin.java Thu Jul 19 11:36:09 2012
@@ -22,97 +22,31 @@ import java.io.IOException;
 import java.io.PrintWriter;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
-import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
 import java.util.Date;
 import java.util.Iterator;
-import java.util.List;
 
 import javax.servlet.GenericServlet;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 
 import org.apache.sling.installer.api.InstallableResource;
+import org.apache.sling.installer.api.info.InfoProvider;
+import org.apache.sling.installer.api.info.InstallationState;
+import org.apache.sling.installer.api.info.Resource;
+import org.apache.sling.installer.api.info.ResourceGroup;
 import org.apache.sling.installer.api.tasks.RegisteredResource;
 import org.apache.sling.installer.api.tasks.ResourceState;
-import org.apache.sling.installer.api.tasks.TaskResource;
-import org.apache.sling.installer.core.impl.EntityResourceList;
-import org.apache.sling.installer.core.impl.OsgiInstallerImpl;
-import org.apache.sling.installer.core.impl.RegisteredResourceImpl;
 
 @SuppressWarnings("serial")
 public class OsgiInstallerWebConsolePlugin extends GenericServlet {
 
-    private final OsgiInstallerImpl installer;
+    private final InfoProvider installer;
 
-    public OsgiInstallerWebConsolePlugin(final OsgiInstallerImpl installer) {
+    public OsgiInstallerWebConsolePlugin(final InfoProvider installer) {
         this.installer = installer;
     }
 
-    /**
-     * Internal class to collect the current state.
-     */
-    private static final class State {
-        public final List<EntityResourceList> activeResources = new ArrayList<EntityResourceList>();
-        public final List<EntityResourceList> installedResources = new ArrayList<EntityResourceList>();
-        public final List<RegisteredResource> untransformedResources = new ArrayList<RegisteredResource>();
-    }
-
-    private static final Comparator<EntityResourceList> COMPARATOR = new Comparator<EntityResourceList>() {
-
-        public int compare(EntityResourceList o1, EntityResourceList o2) {
-            RegisteredResource r1 = null;
-            RegisteredResource r2 = null;
-            if ( o1.getResources().size() > 0 ) {
-                r1 = o1.getResources().iterator().next();
-            }
-            if ( o2.getResources().size() > 0 ) {
-                r2 = o2.getResources().iterator().next();
-            }
-            int result;
-            if ( r1 == null && r2 == null ) {
-                result = 0;
-            } else if ( r1 == null ) {
-                result = -1;
-            } else if ( r2 == null ) {
-                result = 1;
-            } else {
-                result = r1.getType().compareTo(r2.getType());
-                if ( result == 0 ) {
-                    result = r1.getEntityId().compareTo(r2.getEntityId());
-                }
-            }
-            return result;
-        }
-
-    };
-
-    /**
-     * Get the current installer state.
-     * This method should be called from within a synchronized block for the resources!
-     */
-    private State getCurrentState() {
-        final State state = new State();
-
-        for(final String entityId : this.installer.getPersistentResourceList().getEntityIds()) {
-            final EntityResourceList group = this.installer.getPersistentResourceList().getEntityResourceList(entityId);
-            if ( group.getActiveResource() != null ) {
-                state.activeResources.add(group);
-            } else {
-                state.installedResources.add(group);
-            }
-        }
-
-        Collections.sort(state.activeResources, COMPARATOR);
-        Collections.sort(state.installedResources, COMPARATOR);
-
-        state.untransformedResources.addAll(this.installer.getPersistentResourceList().getUntransformedResources());
-
-        return state;
-    }
-
     private String getType(final RegisteredResource rsrc) {
         final String type = rsrc.getType();
         if ( type.equals(InstallableResource.TYPE_BUNDLE) ) {
@@ -136,7 +70,7 @@ public class OsgiInstallerWebConsolePlug
         return (alias == null ? id : id + '\n' + alias);
     }
 
-    private String getURL(final TaskResource rsrc) {
+    private String getURL(final Resource rsrc) {
         if ( rsrc.getVersion() != null ) {
             return rsrc.getURL() + " (" + rsrc.getVersion() + ")";
         }
@@ -168,102 +102,100 @@ public class OsgiInstallerWebConsolePlug
         final PrintWriter pw = res.getWriter();
 
         pw.print("<p class='statline ui-state-highlight'>Apache Sling OSGi Installer</p>");
-        synchronized ( this.installer.getResourcesLock() ) {
-            final State state = this.getCurrentState();
+        final InstallationState state = this.installer.getInstallationState();
 
-            String rt = null;
-            for(final EntityResourceList group : state.activeResources) {
-                final TaskResource toActivate = group.getActiveResource();
-                if ( !toActivate.getType().equals(rt) ) {
+        String rt = null;
+        for(final ResourceGroup group : state.getActiveResources()) {
+            final Resource toActivate = group.getResources().get(0);
+            if ( !toActivate.getType().equals(rt) ) {
+                if ( rt != null ) {
+                    pw.println("</tbody></table>");
+                }
+                pw.println("<div class='ui-widget-header ui-corner-top buttonGroup' style='height: 15px;'>");
+                pw.printf("<span style='float: left; margin-left: 1em;'>Active Resources - %s</span>", getType(toActivate));
+                pw.println("</div>");
+                pw.println("<table class='nicetable'><tbody>");
+                pw.printf("<tr><th>Entity ID</th><th>Digest/Priority</th><th>URL (Version)</th><th>State</th></tr>");
+                rt = toActivate.getType();
+            }
+            pw.printf("<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>",
+                    getEntityId(toActivate, group.getAlias()),
+                    getInfo(toActivate),
+                    getURL(toActivate),
+                    toActivate.getState());
+        }
+        if ( rt != null ) {
+            pw.println("</tbody></table>");
+        }
+        rt = null;
+
+        for(final ResourceGroup group : state.getInstalledResources()) {
+            final Collection<Resource> resources = group.getResources();
+            if (resources.size() > 0) {
+                final Iterator<Resource> iter = resources.iterator();
+                final Resource first = iter.next();
+                if ( !first.getType().equals(rt) ) {
                     if ( rt != null ) {
                         pw.println("</tbody></table>");
                     }
                     pw.println("<div class='ui-widget-header ui-corner-top buttonGroup' style='height: 15px;'>");
-                    pw.printf("<span style='float: left; margin-left: 1em;'>Active Resources - %s</span>", getType(toActivate));
+                    pw.printf("<span style='float: left; margin-left: 1em;'>Processed Resources - %s</span>", getType(first));
                     pw.println("</div>");
                     pw.println("<table class='nicetable'><tbody>");
                     pw.printf("<tr><th>Entity ID</th><th>Digest/Priority</th><th>URL (Version)</th><th>State</th></tr>");
-                    rt = toActivate.getType();
+                    rt = first.getType();
                 }
-                pw.printf("<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>",
-                        getEntityId(toActivate, group.getAlias()),
-                        getInfo(toActivate),
-                        getURL(toActivate),
-                        toActivate.getState());
-            }
-            if ( rt != null ) {
-                pw.println("</tbody></table>");
-            }
-            rt = null;
-
-            for(final EntityResourceList group : state.installedResources) {
-                final Collection<TaskResource> resources = group.getResources();
-                if (resources.size() > 0) {
-                    final Iterator<TaskResource> iter = resources.iterator();
-                    final TaskResource first = iter.next();
-                    if ( !first.getType().equals(rt) ) {
-                        if ( rt != null ) {
-                            pw.println("</tbody></table>");
-                        }
-                        pw.println("<div class='ui-widget-header ui-corner-top buttonGroup' style='height: 15px;'>");
-                        pw.printf("<span style='float: left; margin-left: 1em;'>Processed Resources - %s</span>", getType(first));
-                        pw.println("</div>");
-                        pw.println("<table class='nicetable'><tbody>");
-                        pw.printf("<tr><th>Entity ID</th><th>Digest/Priority</th><th>URL (Version)</th><th>State</th></tr>");
-                        rt = first.getType();
-                    }
-                    pw.print("<tr><td>");
-                    pw.print(getEntityId(first, group.getAlias()));
-                    pw.print("</td><td>");
-                    pw.print(getInfo(first));
-                    pw.print("</td><td>");
-                    pw.print(getURL(first));
-                    pw.print("</td><td>");
-                    pw.print(first.getState());
-                    if ( first.getState() == ResourceState.INSTALLED ) {
-                        final long lastChange = ((RegisteredResourceImpl)first).getLastChange();
-                        if ( lastChange > 0 ) {
-                            pw.print("<br/>");
-                            pw.print(formatDate(lastChange));
-                        }
-                    }
-                    pw.print("</td></tr>");
-
-                    while ( iter.hasNext() ) {
-                        final TaskResource resource = iter.next();
-                        pw.printf("<tr><td></td><td>%s</td><td>%s</td><td>%s</td></tr>",
-                            getInfo(resource),
-                            getURL(resource),
-                            resource.getState());
-                    }
-                }
-            }
-            if ( rt != null ) {
-                pw.println("</tbody></table>");
-            }
-
-            rt = null;
-            for(final RegisteredResource registeredResource : state.untransformedResources) {
-                if ( !registeredResource.getType().equals(rt) ) {
-                    if ( rt != null ) {
-                        pw.println("</tbody></table>");
-                    }
-                    pw.println("<div class='ui-widget-header ui-corner-top buttonGroup' style='height: 15px;'>");
-                    pw.printf("<span style='float: left; margin-left: 1em;'>Untransformed Resources - %s</span>", getType(registeredResource));
-                    pw.println("</div>");
-                    pw.println("<table class='nicetable'><tbody>");
-                    pw.printf("<tr><th>Digest/Priority</th><th>URL</th></tr>");
-
-                    rt = registeredResource.getType();
+                pw.print("<tr><td>");
+                pw.print(getEntityId(first, group.getAlias()));
+                pw.print("</td><td>");
+                pw.print(getInfo(first));
+                pw.print("</td><td>");
+                pw.print(getURL(first));
+                pw.print("</td><td>");
+                pw.print(first.getState());
+                if ( first.getState() == ResourceState.INSTALLED ) {
+                    final long lastChange = first.getLastChange();
+                    if ( lastChange > 0 ) {
+                        pw.print("<br/>");
+                        pw.print(formatDate(lastChange));
+                    }
+                }
+                pw.print("</td></tr>");
+
+                while ( iter.hasNext() ) {
+                    final Resource resource = iter.next();
+                    pw.printf("<tr><td></td><td>%s</td><td>%s</td><td>%s</td></tr>",
+                        getInfo(resource),
+                        getURL(resource),
+                        resource.getState());
                 }
-                pw.printf("<tr><td>%s</td><td>%s</td></tr>",
-                    getInfo(registeredResource),
-                    registeredResource.getURL());
-            }
-            if ( rt != null ) {
-                pw.println("</tbody></table>");
             }
         }
+        if ( rt != null ) {
+            pw.println("</tbody></table>");
+        }
+
+        rt = null;
+        for(final RegisteredResource registeredResource : state.getUntransformedResources()) {
+            if ( !registeredResource.getType().equals(rt) ) {
+                if ( rt != null ) {
+                    pw.println("</tbody></table>");
+                }
+                pw.println("<div class='ui-widget-header ui-corner-top buttonGroup' style='height: 15px;'>");
+                pw.printf("<span style='float: left; margin-left: 1em;'>Untransformed Resources - %s</span>", getType(registeredResource));
+                pw.println("</div>");
+                pw.println("<table class='nicetable'><tbody>");
+                pw.printf("<tr><th>Digest/Priority</th><th>URL</th></tr>");
+
+                rt = registeredResource.getType();
+            }
+            pw.printf("<tr><td>%s</td><td>%s</td></tr>",
+                getInfo(registeredResource),
+                registeredResource.getURL());
+        }
+        if ( rt != null ) {
+            pw.println("</tbody></table>");
+        }
     }
 
     /**
@@ -275,65 +207,63 @@ public class OsgiInstallerWebConsolePlug
         }
         pw.println("Apache Sling OSGi Installer");
         pw.println("===========================");
-        synchronized ( this.installer.getResourcesLock() ) {
-            final State state = this.getCurrentState();
-            pw.println("Active Resources");
-            pw.println("----------------");
-            String rt = null;
-            for(final EntityResourceList group : state.activeResources) {
-                final TaskResource toActivate = group.getActiveResource();
-                if ( !toActivate.getType().equals(rt) ) {
-                    pw.printf("%s:%n", getType(toActivate));
-                    rt = toActivate.getType();
+        final InstallationState state = this.installer.getInstallationState();
+        pw.println("Active Resources");
+        pw.println("----------------");
+        String rt = null;
+        for(final ResourceGroup group : state.getActiveResources()) {
+            final Resource toActivate = group.getResources().get(0);
+            if ( !toActivate.getType().equals(rt) ) {
+                pw.printf("%s:%n", getType(toActivate));
+                rt = toActivate.getType();
+            }
+            pw.printf("- %s: %s, %s, %s%n",
+                    getEntityId(toActivate, group.getAlias()),
+                    getInfo(toActivate),
+                    getURL(toActivate),
+                    toActivate.getState());
+        }
+        pw.println();
+
+        pw.println("Processed Resources");
+        pw.println("-------------------");
+        rt = null;
+        for(final ResourceGroup group : state.getInstalledResources()) {
+            final Collection<Resource> resources = group.getResources();
+            if (resources.size() > 0) {
+                final Iterator<Resource> iter = resources.iterator();
+                final Resource first = iter.next();
+                if ( !first.getType().equals(rt) ) {
+                    pw.printf("%s:%n", getType(first));
+                    rt = first.getType();
+                }
+                pw.printf("* %s: %s, %s, %s%n",
+                        getEntityId(first, group.getAlias()),
+                        getInfo(first),
+                        getURL(first),
+                        first.getState());
+                while ( iter.hasNext() ) {
+                    final Resource resource = iter.next();
+                    pw.printf("  - %s, %s, %s%n",
+                        getInfo(resource),
+                        getURL(resource),
+                        resource.getState());
                 }
-                pw.printf("- %s: %s, %s, %s%n",
-                        getEntityId(toActivate, group.getAlias()),
-                        getInfo(toActivate),
-                        getURL(toActivate),
-                        toActivate.getState());
             }
-            pw.println();
-
-            pw.println("Processed Resources");
-            pw.println("-------------------");
-            rt = null;
-            for(final EntityResourceList group : state.installedResources) {
-                final Collection<TaskResource> resources = group.getResources();
-                if (resources.size() > 0) {
-                    final Iterator<TaskResource> iter = resources.iterator();
-                    final TaskResource first = iter.next();
-                    if ( !first.getType().equals(rt) ) {
-                        pw.printf("%s:%n", getType(first));
-                        rt = first.getType();
-                    }
-                    pw.printf("* %s: %s, %s, %s%n",
-                            getEntityId(first, group.getAlias()),
-                            getInfo(first),
-                            getURL(first),
-                            first.getState());
-                    while ( iter.hasNext() ) {
-                        final TaskResource resource = iter.next();
-                        pw.printf("  - %s, %s, %s%n",
-                            getInfo(resource),
-                            getURL(resource),
-                            resource.getState());
-                    }
-                }
-            }
-            pw.println();
-
-            pw.println("Untransformed Resources");
-            pw.println("-----------------------");
-            rt = null;
-            for(final RegisteredResource registeredResource : state.untransformedResources) {
-                if ( !registeredResource.getType().equals(rt) ) {
-                    pw.printf("%s:%n", getType(registeredResource));
-                    rt = registeredResource.getType();
-                }
-                pw.printf("- %s, %s%n",
-                        getInfo(registeredResource),
-                        registeredResource.getURL());
+        }
+        pw.println();
+
+        pw.println("Untransformed Resources");
+        pw.println("-----------------------");
+        rt = null;
+        for(final RegisteredResource registeredResource : state.getUntransformedResources()) {
+            if ( !registeredResource.getType().equals(rt) ) {
+                pw.printf("%s:%n", getType(registeredResource));
+                rt = registeredResource.getType();
             }
+            pw.printf("- %s, %s%n",
+                    getInfo(registeredResource),
+                    registeredResource.getURL());
         }
     }
 }