You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by fm...@apache.org on 2008/01/22 15:24:57 UTC

svn commit: r614204 [2/3] - in /incubator/sling/trunk/osgi/console-web: ./ src/main/java/org/apache/sling/osgi/console/web/ src/main/java/org/apache/sling/osgi/console/web/internal/ src/main/java/org/apache/sling/osgi/console/web/internal/compendium/ s...

Copied: incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/core/StartAction.java (from r613401, incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/StartAction.java)
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/core/StartAction.java?p2=incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/core/StartAction.java&p1=incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/StartAction.java&r1=613401&r2=614204&rev=614204&view=diff
==============================================================================
--- incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/StartAction.java (original)
+++ incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/core/StartAction.java Tue Jan 22 06:24:42 2008
@@ -14,20 +14,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sling.osgi.console.web.internal;
+package org.apache.sling.osgi.console.web.internal.core;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleException;
+import org.osgi.service.log.LogService;
 
-/**
- * The <code>StopAction</code> TODO
- *
- * @scr.component metatype="false"
- * @scr.service
- */
 public class StartAction extends BundleAction {
 
     public static final String NAME = "start";
@@ -41,11 +36,6 @@
         return LABEL;
     }
 
-    /*
-     * (non-Javadoc)
-     *
-     * @see org.apache.sling.manager.web.internal.internal.Action#performAction(javax.servlet.http.HttpServletRequest)
-     */
     public boolean performAction(HttpServletRequest request, HttpServletResponse response) {
 
         long bundleId = this.getBundleId(request);
@@ -55,7 +45,7 @@
                 try {
                     bundle.start();
                 } catch (BundleException be) {
-                    this.log(bundle, "Cannot start", be);
+                    getLog().log(LogService.LOG_ERROR, "Cannot start", be);
                 }
 
             }

Copied: incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/core/StopAction.java (from r613401, incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/StopAction.java)
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/core/StopAction.java?p2=incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/core/StopAction.java&p1=incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/StopAction.java&r1=613401&r2=614204&rev=614204&view=diff
==============================================================================
--- incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/StopAction.java (original)
+++ incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/core/StopAction.java Tue Jan 22 06:24:42 2008
@@ -14,19 +14,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sling.osgi.console.web.internal;
+package org.apache.sling.osgi.console.web.internal.core;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleException;
+import org.osgi.service.log.LogService;
 
 /**
  * The <code>StopAction</code> TODO
- *
- * @scr.component metatype="false"
- * @scr.service
  */
 public class StopAction extends BundleAction {
 
@@ -41,11 +39,6 @@
         return LABEL;
     }
 
-    /*
-     * (non-Javadoc)
-     *
-     * @see org.apache.sling.manager.web.internal.internal.Action#performAction(javax.servlet.http.HttpServletRequest)
-     */
     public boolean performAction(HttpServletRequest request, HttpServletResponse response) {
 
         long bundleId = this.getBundleId(request);
@@ -55,7 +48,7 @@
                 try {
                     bundle.stop();
                 } catch (BundleException be) {
-                    this.log(bundle, "Cannot stop", be);
+                    getLog().log(LogService.LOG_ERROR, "Cannot stop", be);
                 }
 
             }

Copied: incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/core/UninstallAction.java (from r613401, incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/UninstallAction.java)
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/core/UninstallAction.java?p2=incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/core/UninstallAction.java&p1=incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/UninstallAction.java&r1=613401&r2=614204&rev=614204&view=diff
==============================================================================
--- incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/UninstallAction.java (original)
+++ incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/core/UninstallAction.java Tue Jan 22 06:24:42 2008
@@ -14,20 +14,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sling.osgi.console.web.internal;
+package org.apache.sling.osgi.console.web.internal.core;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleException;
+import org.osgi.service.log.LogService;
 
-/**
- * The <code>StopAction</code> TODO
- *
- * @scr.component metatype="false"
- * @scr.service
- */
 public class UninstallAction extends BundleAction {
 
     public static final String NAME = "uninstall";
@@ -41,11 +36,6 @@
         return LABEL;
     }
 
-    /*
-     * (non-Javadoc)
-     *
-     * @see org.apache.sling.manager.web.internal.internal.Action#performAction(javax.servlet.http.HttpServletRequest)
-     */
     public boolean performAction(HttpServletRequest request, HttpServletResponse response) {
 
         long bundleId = this.getBundleId(request);
@@ -55,7 +45,7 @@
                 try {
                     bundle.uninstall();
                 } catch (BundleException be) {
-                    this.log(bundle, "Cannot uninstall", be);
+                    getLog().log(LogService.LOG_ERROR, "Cannot uninstall", be);
                 }
 
             }

Copied: incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/core/UpdateAction.java (from r613401, incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/UpdateAction.java)
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/core/UpdateAction.java?p2=incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/core/UpdateAction.java&p1=incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/UpdateAction.java&r1=613401&r2=614204&rev=614204&view=diff
==============================================================================
--- incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/UpdateAction.java (original)
+++ incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/core/UpdateAction.java Tue Jan 22 06:24:42 2008
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sling.osgi.console.web.internal;
+package org.apache.sling.osgi.console.web.internal.core;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -24,13 +24,13 @@
 import org.apache.sling.osgi.assembly.installer.InstallerService;
 import org.apache.sling.osgi.assembly.installer.VersionRange;
 import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
+import org.osgi.service.log.LogService;
+import org.osgi.util.tracker.ServiceTracker;
 
 /**
  * The <code>UpdateAction</code> TODO
- *
- * @scr.component metatype="false"
- * @scr.service
  */
 public class UpdateAction extends BundleAction {
 
@@ -38,8 +38,18 @@
 
     public static final String LABEL = "Update";
 
-    /** @scr.reference */
-    private InstallerService installerService;
+    private static final String INSTALLER_SERVICE_NAME = "org.apache.sling.osgi.assembly.installer.InstallerService";
+
+    // track the optional installer service manually
+    private ServiceTracker installerService;
+
+    public void setBundleContext(BundleContext bundleContext) {
+        super.setBundleContext(bundleContext);
+
+        installerService = new ServiceTracker(bundleContext,
+            INSTALLER_SERVICE_NAME, null);
+        installerService.open();
+    }
 
     public String getName() {
         return NAME;
@@ -51,7 +61,7 @@
 
     /*
      * (non-Javadoc)
-     *
+     * 
      * @see org.apache.sling.manager.web.internal.internal.Action#performAction(javax.servlet.http.HttpServletRequest)
      */
     public boolean performAction(HttpServletRequest request,
@@ -64,7 +74,7 @@
                 try {
                     this.updateFromRepo(bundle);
                 } catch (Throwable t) {
-                    this.log(bundle, "Uncaught Problem", t);
+                    getLog().log(LogService.LOG_ERROR, "Uncaught Problem", t);
                 }
 
             }
@@ -75,6 +85,11 @@
 
     private void updateFromRepo(final Bundle bundle) {
 
+        final InstallerService is = (InstallerService) installerService.getService();
+        if (is == null) {
+            return;
+        }
+        
         final String name = bundle.getSymbolicName();
         final String version = (String) bundle.getHeaders().get(
             Constants.BUNDLE_VERSION);
@@ -95,13 +110,15 @@
                     // don't care
                 }
 
-                Installer installer = UpdateAction.this.installerService.getInstaller();
+                Installer installer = is.getInstaller();
                 installer.addBundle(name, new VersionRange(version), -1);
                 try {
                     installer.install(false);
                 } catch (InstallerException ie) {
-                    Throwable cause = (ie.getCause() != null) ? ie.getCause() : ie;
-                    UpdateAction.this.log(bundle, "Cannot update", cause);
+                    Throwable cause = (ie.getCause() != null)
+                            ? ie.getCause()
+                            : ie;
+                    getLog().log(LogService.LOG_ERROR, "Cannot update", cause);
                 } finally {
                     installer.dispose();
                 }
@@ -112,11 +129,4 @@
         t.start();
     }
 
-    protected void bindInstallerService(InstallerService installerService) {
-        this.installerService = installerService;
-    }
-
-    protected void unbindInstallerService(InstallerService installerService) {
-        this.installerService = null;
-    }
 }

Copied: incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/misc/AssemblyListRender.java (from r613401, incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/AssemblyListRender.java)
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/misc/AssemblyListRender.java?p2=incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/misc/AssemblyListRender.java&p1=incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/AssemblyListRender.java&r1=613401&r2=614204&rev=614204&view=diff
==============================================================================
--- incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/AssemblyListRender.java (original)
+++ incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/misc/AssemblyListRender.java Tue Jan 22 06:24:42 2008
@@ -14,36 +14,23 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sling.osgi.console.web.internal;
+package org.apache.sling.osgi.console.web.internal.misc;
 
 import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.sling.osgi.console.web.internal.core.BundleListRender;
 import org.osgi.framework.Bundle;
 
-/**
- * The <code>BundleListRender</code> TODO
- *
- * @scr.component metatype="false"
- * @scr.service
- */
 public class AssemblyListRender extends BundleListRender {
 
     public static final String NAME = "assemblyList";
     public static final String LABEL = "Assemblies";
 
-    /*
-     * (non-Javadoc)
-     * @see org.apache.sling.manager.web.internal.Render#getName()
-     */
     public String getName() {
         return NAME;
     }
 
-    /*
-     * (non-Javadoc)
-     * @see org.apache.sling.manager.web.internal.Render#getLabel()
-     */
     public String getLabel() {
         return LABEL;
     }

Copied: incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/misc/ConfigurationRender.java (from r613401, incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/ConfigurationRender.java)
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/misc/ConfigurationRender.java?p2=incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/misc/ConfigurationRender.java&p1=incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/ConfigurationRender.java&r1=613401&r2=614204&rev=614204&view=diff
==============================================================================
--- incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/ConfigurationRender.java (original)
+++ incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/misc/ConfigurationRender.java Tue Jan 22 06:24:42 2008
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sling.osgi.console.web.internal;
+package org.apache.sling.osgi.console.web.internal.misc;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -24,6 +24,7 @@
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Date;
 import java.util.Dictionary;
 import java.util.Enumeration;
@@ -40,7 +41,9 @@
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.commons.io.IOUtils;
+import org.apache.sling.osgi.console.web.ConfigurationPrinter;
 import org.apache.sling.osgi.console.web.Render;
+import org.apache.sling.osgi.console.web.internal.BaseManagementPlugin;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
@@ -52,45 +55,28 @@
 import org.osgi.service.prefs.BackingStoreException;
 import org.osgi.service.prefs.Preferences;
 import org.osgi.service.prefs.PreferencesService;
+import org.osgi.util.tracker.ServiceTracker;
 
-/**
- * The <code>VMStatRender</code> TODO
- *
- * @scr.component metatype="false"
- * @scr.service
- */
-public class ConfigurationRender implements Render {
+public class ConfigurationRender extends BaseManagementPlugin implements Render {
 
     public static final String NAME = "config";
 
     public static final String LABEL = "Configuration Status";
 
-    private BundleContext bundleContext;
+    private ServiceTracker cfgPrinterTracker;
+
+    private int cfgPrinterTrackerCount;
+
+    private SortedMap<String, ConfigurationPrinter> configurationPrinters = new TreeMap<String, ConfigurationPrinter>();
 
-    /*
-     * (non-Javadoc)
-     *
-     * @see org.apache.sling.manager.web.internal.Render#getName()
-     */
     public String getName() {
         return NAME;
     }
 
-    /*
-     * (non-Javadoc)
-     *
-     * @see org.apache.sling.manager.web.internal.Render#getLabel()
-     */
     public String getLabel() {
         return LABEL;
     }
 
-    /*
-     * (non-Javadoc)
-     *
-     * @see org.apache.sling.manager.web.internal.Render#render(javax.servlet.http.HttpServletRequest,
-     *      javax.servlet.http.HttpServletResponse)
-     */
     public void render(HttpServletRequest request, HttpServletResponse response)
             throws IOException {
 
@@ -119,20 +105,47 @@
         this.printPreferences(pw);
         this.printConfigurations(pw);
 
+        for (ConfigurationPrinter cp : getConfigurationPrinters()) {
+            printConfigurationPrinter(pw, cp);
+        }
+
         pw.println("</pre>");
         pw.println("</td>");
         pw.println("</tr>");
         pw.println("</table>");
     }
 
+    private Collection<ConfigurationPrinter> getConfigurationPrinters() {
+        if (cfgPrinterTracker == null) {
+            cfgPrinterTracker = new ServiceTracker(getBundleContext(),
+                ConfigurationPrinter.SERVICE, null);
+            cfgPrinterTracker.open();
+            cfgPrinterTrackerCount = -1;
+        }
+
+        if (cfgPrinterTrackerCount != cfgPrinterTracker.getTrackingCount()) {
+            SortedMap<String, ConfigurationPrinter> cp = new TreeMap<String, ConfigurationPrinter>();
+            Object[] services = cfgPrinterTracker.getServices();
+            if (services != null) {
+                for (Object srv : services) {
+                    ConfigurationPrinter cfgPrinter = (ConfigurationPrinter) srv;
+                    cp.put(cfgPrinter.getTitle(), cfgPrinter);
+                }
+            }
+            configurationPrinters = cp;
+            cfgPrinterTrackerCount = cfgPrinterTracker.getTrackingCount();
+        }
+
+        return configurationPrinters.values();
+    }
+
     private void printSystemProperties(PrintWriter pw) {
         pw.println("*** System properties:");
 
         Properties props = System.getProperties();
-        SortedSet keys = new TreeSet(props.keySet());
-        for (Iterator ki = keys.iterator(); ki.hasNext();) {
-            String key = (String) ki.next();
-            this.infoLine(pw, null, key, props.get(key));
+        SortedSet<Object> keys = new TreeSet<Object>(props.keySet());
+        for (Object key : keys) {
+            this.infoLine(pw, null, (String) key, props.get(key));
         }
 
         pw.println();
@@ -141,7 +154,7 @@
     private void printRawFrameworkProperties(PrintWriter pw) {
         pw.println("*** Raw Framework properties:");
 
-        File file = new File(this.bundleContext.getProperty("sling.home"),
+        File file = new File(getBundleContext().getProperty("sling.home"),
             "sling.properties");
         if (file.exists()) {
             Properties props = new Properties();
@@ -155,10 +168,9 @@
                 IOUtils.closeQuietly(ins);
             }
 
-            SortedSet keys = new TreeSet(props.keySet());
-            for (Iterator ki = keys.iterator(); ki.hasNext();) {
-                String key = (String) ki.next();
-                this.infoLine(pw, null, key, props.get(key));
+            SortedSet<Object> keys = new TreeSet<Object>(props.keySet());
+            for (Object key : keys) {
+                this.infoLine(pw, null, (String) key, props.get(key));
             }
 
         } else {
@@ -171,7 +183,7 @@
     private void printAssemblies(PrintWriter pw) {
         pw.println("*** Assemblies:");
 
-        Bundle[] bundles = this.bundleContext.getBundles();
+        Bundle[] bundles = getBundleContext().getBundles();
         SortedSet<String> keys = new TreeSet<String>();
         for (int i = 0; i < bundles.length; i++) {
             if (bundles[i].getHeaders().get("Assembly-Bundles") != null) {
@@ -179,8 +191,12 @@
             }
         }
 
-        for (Iterator<String> ki = keys.iterator(); ki.hasNext();) {
-            this.infoLine(pw, null, null, ki.next());
+        if (keys.isEmpty()) {
+            pw.println("  No Assemblies installed");
+        } else {
+            for (Iterator<String> ki = keys.iterator(); ki.hasNext();) {
+                this.infoLine(pw, null, null, ki.next());
+            }
         }
 
         pw.println();
@@ -191,7 +207,7 @@
         // biz.junginger.freemem.FreeMem (1.3.0) "FreeMem Eclipse Memory
         // Monitor" [Resolved]
 
-        Bundle[] bundles = this.bundleContext.getBundles();
+        Bundle[] bundles = getBundleContext().getBundles();
         SortedSet<String> keys = new TreeSet<String>();
         for (int i = 0; i < bundles.length; i++) {
             keys.add(this.getBundleString(bundles[i], true));
@@ -210,7 +226,7 @@
         // get the list of services sorted by service ID (ascending)
         SortedMap<Object, ServiceReference> srMap = new TreeMap<Object, ServiceReference>();
         try {
-            ServiceReference[] srs = this.bundleContext.getAllServiceReferences(
+            ServiceReference[] srs = getBundleContext().getAllServiceReferences(
                 null, null);
             for (int i = 0; i < srs.length; i++) {
                 srMap.put(srs[i].getProperty(Constants.SERVICE_ID), srs[i]);
@@ -226,7 +242,8 @@
             this.infoLine(pw, null,
                 String.valueOf(sr.getProperty(Constants.SERVICE_ID)),
                 sr.getProperty(Constants.OBJECTCLASS));
-            this.infoLine(pw, "  ", "Bundle", this.getBundleString(sr.getBundle(), false));
+            this.infoLine(pw, "  ", "Bundle", this.getBundleString(
+                sr.getBundle(), false));
 
             Bundle[] users = sr.getUsingBundles();
             if (users != null && users.length > 0) {
@@ -253,14 +270,16 @@
     private void printPreferences(PrintWriter pw) {
         pw.println("*** System Preferences:");
 
-        ServiceReference sr = this.bundleContext.getServiceReference(PreferencesService.class.getName());
+        ServiceReference sr = getBundleContext().getServiceReference(
+            PreferencesService.class.getName());
         if (sr == null) {
             pw.println("  Preferences Service not registered");
             pw.println();
             return;
         }
 
-        PreferencesService ps = (PreferencesService) this.bundleContext.getService(sr);
+        PreferencesService ps = (PreferencesService) getBundleContext().getService(
+            sr);
         try {
             this.printPreferences(pw, ps.getSystemPreferences());
 
@@ -272,7 +291,7 @@
         } catch (BackingStoreException bse) {
             // todo or not :-)
         } finally {
-            this.bundleContext.ungetService(sr);
+            getBundleContext().ungetService(sr);
         }
     }
 
@@ -286,8 +305,8 @@
 
         String[] keys = prefs.keys();
         for (int i = 0; i < keys.length; i++) {
-            this.infoLine(pw, null, prefs.absolutePath() + "/" + keys[i], prefs.get(
-                keys[i], null));
+            this.infoLine(pw, null, prefs.absolutePath() + "/" + keys[i],
+                prefs.get(keys[i], null));
         }
 
         pw.println();
@@ -296,31 +315,43 @@
     private void printConfigurations(PrintWriter pw) {
         pw.println("*** Configurations:");
 
-        ServiceReference sr = this.bundleContext.getServiceReference(ConfigurationAdmin.class.getName());
+        ServiceReference sr = getBundleContext().getServiceReference(
+            ConfigurationAdmin.class.getName());
         if (sr == null) {
             pw.println("  Configuration Admin Service not registered");
-            pw.println();
-            return;
-        }
-
-        ConfigurationAdmin ca = (ConfigurationAdmin) this.bundleContext.getService(sr);
-        try {
-            Configuration[] configs = ca.listConfigurations(null);
-            if (configs != null) {
-                SortedMap<Object, Configuration> sm = new TreeMap<Object, Configuration>();
-                for (int i = 0; i < configs.length; i++) {
-                    sm.put(configs[i].getPid(), configs[i]);
-                }
+        } else {
 
-                for (Iterator<Configuration> mi = sm.values().iterator(); mi.hasNext();) {
-                    this.printConfiguration(pw, mi.next());
+            ConfigurationAdmin ca = (ConfigurationAdmin) getBundleContext().getService(
+                sr);
+            try {
+                Configuration[] configs = ca.listConfigurations(null);
+                if (configs != null && configs.length > 0) {
+                    SortedMap<Object, Configuration> sm = new TreeMap<Object, Configuration>();
+                    for (int i = 0; i < configs.length; i++) {
+                        sm.put(configs[i].getPid(), configs[i]);
+                    }
+
+                    for (Iterator<Configuration> mi = sm.values().iterator(); mi.hasNext();) {
+                        this.printConfiguration(pw, mi.next());
+                    }
+                } else {
+                    pw.println("  No Configurations available");
                 }
+            } catch (Exception e) {
+                // todo or not :-)
+            } finally {
+                getBundleContext().ungetService(sr);
             }
-        } catch (Exception e) {
-            // todo or not :-)
-        } finally {
-            this.bundleContext.ungetService(sr);
         }
+
+        pw.println();
+    }
+
+    private void printConfigurationPrinter(PrintWriter pw,
+            ConfigurationPrinter cp) {
+        pw.println("*** " + cp.getTitle() + ":");
+        cp.printConfiguration(pw);
+        pw.println();
     }
 
     private void printConfiguration(PrintWriter pw, Configuration config) {
@@ -442,13 +473,4 @@
         return buf.toString();
     }
 
-    //--------- SCR Integration -----------------------------------------------
-
-    protected void activate(ComponentContext context) {
-        this.bundleContext = context.getBundleContext();
-    }
-
-    protected void deactivate(ComponentContext context) {
-        this.bundleContext = null;
-    }
 }

Added: incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/obr/AbstractObrPlugin.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/obr/AbstractObrPlugin.java?rev=614204&view=auto
==============================================================================
--- incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/obr/AbstractObrPlugin.java (added)
+++ incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/obr/AbstractObrPlugin.java Tue Jan 22 06:24:42 2008
@@ -0,0 +1,57 @@
+/*
+ * 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.osgi.console.web.internal.obr;
+
+import org.apache.sling.osgi.assembly.installer.BundleRepositoryAdmin;
+import org.apache.sling.osgi.assembly.installer.InstallerService;
+import org.apache.sling.osgi.console.web.internal.BaseManagementPlugin;
+import org.osgi.framework.BundleContext;
+import org.osgi.util.tracker.ServiceTracker;
+
+public class AbstractObrPlugin extends BaseManagementPlugin {
+
+    // track the optional installer service manually
+    private ServiceTracker installerService;
+
+    public void setBundleContext(BundleContext bundleContext) {
+        super.setBundleContext(bundleContext);
+
+    }
+
+    protected InstallerService getInstallerService() {
+        if (installerService == null) {
+            try {
+                installerService = new ServiceTracker(getBundleContext(),
+                    InstallerService.class.getName(), null);
+                installerService.open();
+            } catch (Throwable t) {
+                // missing InstallerService class ??
+                return null;
+            }
+
+        }
+
+        return (InstallerService) installerService.getService();
+    }
+
+    protected BundleRepositoryAdmin getBundleRepositoryAdmin() {
+        InstallerService is = getInstallerService();
+        return (is != null) ? is.getBundleRepositoryAdmin() : null;
+    }
+}

Copied: incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/obr/BundleRepositoryRender.java (from r613401, incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/BundleRepositoryRender.java)
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/obr/BundleRepositoryRender.java?p2=incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/obr/BundleRepositoryRender.java&p1=incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/BundleRepositoryRender.java&r1=613401&r2=614204&rev=614204&view=diff
==============================================================================
--- incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/BundleRepositoryRender.java (original)
+++ incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/obr/BundleRepositoryRender.java Tue Jan 22 06:24:42 2008
@@ -14,11 +14,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sling.osgi.console.web.internal;
+package org.apache.sling.osgi.console.web.internal.obr;
 
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Comparator;
 import java.util.Date;
 import java.util.HashMap;
@@ -34,23 +35,18 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.sling.osgi.assembly.installer.BundleRepositoryAdmin;
 import org.apache.sling.osgi.assembly.installer.InstallerService;
 import org.apache.sling.osgi.assembly.installer.Repository;
 import org.apache.sling.osgi.assembly.installer.Resource;
 import org.apache.sling.osgi.console.web.Render;
+import org.apache.sling.osgi.console.web.internal.Util;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
 import org.osgi.framework.Version;
-import org.osgi.service.component.ComponentContext;
 
-/**
- * The <code>BundleRepositoryRender</code> TODO
- *
- * @scr.component metatype="false"
- * @scr.service
- */
-public class BundleRepositoryRender implements Render {
+public class BundleRepositoryRender extends AbstractObrPlugin implements Render {
 
     public static final String NAME = "bundlerepo";
 
@@ -62,26 +58,28 @@
 
     private static final String REPOSITORY_PROPERTY = "obr.repository.url";
 
-    private BundleContext bundleContext;
     private String[] repoURLs;
 
-    /** @scr.reference */
-    private InstallerService installerService;
+    public void setBundleContext(BundleContext bundleContext) {
+        super.setBundleContext(bundleContext);
+
+        String urlStr = bundleContext.getProperty(REPOSITORY_PROPERTY);
+        List<String> urlList = new ArrayList<String>();
+
+        if (urlStr != null) {
+            StringTokenizer st = new StringTokenizer(urlStr);
+            while (st.hasMoreTokens()) {
+                urlList.add(st.nextToken());
+            }
+        }
+
+        this.repoURLs = urlList.toArray(new String[urlList.size()]);
+    }
 
-    /*
-     * (non-Javadoc)
-     *
-     * @see org.apache.sling.manager.web.internal.Render#getName()
-     */
     public String getName() {
         return NAME;
     }
 
-    /*
-     * (non-Javadoc)
-     *
-     * @see org.apache.sling.manager.web.internal.Render#getLabel()
-     */
     public String getLabel() {
         return LABEL;
     }
@@ -92,8 +90,15 @@
         PrintWriter pw = response.getWriter();
         this.header(pw);
 
+        Iterator<?> repos;
+        BundleRepositoryAdmin repoAdmin = getBundleRepositoryAdmin();
+        if (repoAdmin != null) {
+            repos = repoAdmin.getRepositories();
+        } else {
+            repos = Collections.emptyList().iterator();
+        }
+
         Set<String> activeURLs = new HashSet<String>();
-        Iterator<?> repos = installerService.getBundleRepositoryAdmin().getRepositories();
         if (!repos.hasNext()) {
             pw.println("<tr class='content'>");
             pw.println("<td class='content' colspan='4'>No Active Repositories</td>");
@@ -124,7 +129,7 @@
         }
 
         // list any repositories configured but not active
-        for (int i=0; i < this.repoURLs.length; i++) {
+        for (int i = 0; i < this.repoURLs.length; i++) {
             if (!activeURLs.contains(this.repoURLs[i])) {
                 pw.println("<tr class='content'>");
                 pw.println("<td class='content'>-</td>");
@@ -170,9 +175,8 @@
 
         if (doForm) {
             pw.println("<form method='post'>");
-            pw.println("<input type='hidden' name='"
-                + Util.PARAM_ACTION + "' value='" + InstallFromRepoAction.NAME
-                + "'>");
+            pw.println("<input type='hidden' name='" + Util.PARAM_ACTION
+                + "' value='" + InstallFromRepoAction.NAME + "'>");
         }
 
         pw.println("<table class='content' cellpadding='0' cellspacing='0' width='100%'>");
@@ -187,22 +191,30 @@
     }
 
     private void listResources(PrintWriter pw) {
+        InstallerService is = getInstallerService();
+        if (is == null) {
+            return;
+        }
+
         Map<String, Version> bundles = this.getBundles();
 
-        Iterator<?> resources = installerService.getBundleRepositoryAdmin().getResources();
-        SortedSet<Resource> resSet = new TreeSet<Resource>(new Comparator<Resource>() {
-            public int compare(Resource o1, Resource o2) {
-                if (o1 == o2 || o1.equals(o2)) {
-                    return 0;
-                }
+        Iterator<?> resources = is.getBundleRepositoryAdmin().getResources();
+        SortedSet<Resource> resSet = new TreeSet<Resource>(
+            new Comparator<Resource>() {
+                public int compare(Resource o1, Resource o2) {
+                    if (o1 == o2 || o1.equals(o2)) {
+                        return 0;
+                    }
+
+                    if (o1.getPresentationName().equals(
+                        o2.getPresentationName())) {
+                        return o1.getVersion().compareTo(o2.getVersion());
+                    }
 
-                if (o1.getPresentationName().equals(o2.getPresentationName())) {
-                    return o1.getVersion().compareTo(o2.getVersion());
+                    return o1.getPresentationName().compareTo(
+                        o2.getPresentationName());
                 }
-
-                return o1.getPresentationName().compareTo(o2.getPresentationName());
-            }
-        });
+            });
 
         while (resources.hasNext()) {
             Resource res = (Resource) resources.next();
@@ -223,18 +235,22 @@
 
     private void printResource(PrintWriter pw, Resource res) {
         pw.println("<tr class='content'>");
-        pw.println("<td class='content' valign='top' align='center'><input class='checkradio' type='checkbox' name='bundle' value='" + res.getSymbolicName() + "," + res.getVersion() + "'></td>");
+        pw.println("<td class='content' valign='top' align='center'><input class='checkradio' type='checkbox' name='bundle' value='"
+            + res.getSymbolicName() + "," + res.getVersion() + "'></td>");
 
         // check whether the resource is an assembly (category name)
         String style = "";
         String[] cat = res.getCategories();
-        for (int i=0; cat != null && i < cat.length; i++) {
+        for (int i = 0; cat != null && i < cat.length; i++) {
             if ("assembly".equals(cat[i])) {
                 style = "style='font-weight:bold'";
             }
         }
-        pw.println("<td class='content' " + style + ">" + res.getPresentationName() + " (" + res.getSymbolicName() + ")</td>");
-        pw.println("<td class='content' " + style + " valign='top'>" + res.getVersion() + "</td>");
+        pw.println("<td class='content' " + style + ">"
+            + res.getPresentationName() + " (" + res.getSymbolicName()
+            + ")</td>");
+        pw.println("<td class='content' " + style + " valign='top'>"
+            + res.getVersion() + "</td>");
 
         pw.println("</tr>");
     }
@@ -259,9 +275,10 @@
     private Map<String, Version> getBundles() {
         Map<String, Version> bundles = new HashMap<String, Version>();
 
-        Bundle[] installed = this.bundleContext.getBundles();
-        for (int i=0; i < installed.length; i++) {
-            String ver = (String) installed[i].getHeaders().get(Constants.BUNDLE_VERSION);
+        Bundle[] installed = getBundleContext().getBundles();
+        for (int i = 0; i < installed.length; i++) {
+            String ver = (String) installed[i].getHeaders().get(
+                Constants.BUNDLE_VERSION);
             Version bundleVersion = Version.parseVersion(ver);
 
             // assume one bundle instance per symbolic name !!
@@ -274,26 +291,4 @@
         return bundles;
     }
 
-    //--------- SCR Integration -----------------------------------------------
-
-    protected void activate(ComponentContext context) {
-        this.bundleContext = context.getBundleContext();
-
-        String urlStr = this.bundleContext.getProperty(REPOSITORY_PROPERTY);
-        List<String> urlList = new ArrayList<String>();
-
-        if (urlStr != null) {
-            StringTokenizer st = new StringTokenizer(urlStr);
-            while (st.hasMoreTokens()) {
-                urlList.add(st.nextToken());
-            }
-        }
-
-        this.repoURLs = urlList.toArray(new String[urlList.size()]);
-    }
-
-    protected void deactivate(ComponentContext context) {
-        this.bundleContext = null;
-        this.repoURLs = null;
-    }
 }

Copied: incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/obr/InstallFromRepoAction.java (from r613401, incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/InstallFromRepoAction.java)
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/obr/InstallFromRepoAction.java?p2=incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/obr/InstallFromRepoAction.java&p1=incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/InstallFromRepoAction.java&r1=613401&r2=614204&rev=614204&view=diff
==============================================================================
--- incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/InstallFromRepoAction.java (original)
+++ incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/obr/InstallFromRepoAction.java Tue Jan 22 06:24:42 2008
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sling.osgi.console.web.internal;
+package org.apache.sling.osgi.console.web.internal.obr;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -26,22 +26,10 @@
 import org.apache.sling.osgi.console.web.Action;
 import org.osgi.service.log.LogService;
 
-/**
- * The <code>InstallFromRepoAction</code> TODO
- *
- * @scr.component metatype="false"
- * @scr.service
- */
-public class InstallFromRepoAction implements Action {
+public class InstallFromRepoAction extends AbstractObrPlugin implements Action {
 
     public static final String NAME = "installFromOBR";
 
-    /** @scr.reference */
-    private LogService log;
-
-    /** @scr.reference */
-    private InstallerService installerService;
-
     public String getName() {
         return NAME;
     }
@@ -50,64 +38,58 @@
         return NAME;
     }
 
-   /* (non-Javadoc)
-     * @see org.apache.sling.manager.web.internal.Action#performAction(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.sling.manager.web.internal.Action#performAction(javax.servlet.http.HttpServletRequest,
+     *      javax.servlet.http.HttpServletResponse)
      */
     public boolean performAction(HttpServletRequest request,
-            HttpServletResponse response)  {
+            HttpServletResponse response) {
 
         // check whether we have to do something
         String[] bundles = request.getParameterValues("bundle");
         if (bundles == null || bundles.length == 0) {
-            this.log.log(LogService.LOG_INFO, "No resources to deploy");
+            getLog().log(LogService.LOG_INFO, "No resources to deploy");
             return true;
         }
 
-        Installer installer = this.installerService.getInstaller();
-
-        // prepare the deployment
-        for (int i=0; i < bundles.length; i++) {
-            String bundle = bundles[i];
-            int comma = bundle.indexOf(',');
-            String name = (comma > 0) ? bundle.substring(0, comma) : bundle;
-            String version = (comma < bundle.length()-1) ? bundle.substring(comma+1) : null;
-
-            if (name.length() > 0) {
-                // no name, ignore this one
-                VersionRange versionRange = new VersionRange(version);
-                installer.addBundle(name, versionRange, -1);
+        InstallerService installerService = getInstallerService();
+        if (installerService != null) {
+            Installer installer = installerService.getInstaller();
+
+            // prepare the deployment
+            for (int i = 0; i < bundles.length; i++) {
+                String bundle = bundles[i];
+                int comma = bundle.indexOf(',');
+                String name = (comma > 0) ? bundle.substring(0, comma) : bundle;
+                String version = (comma < bundle.length() - 1)
+                        ? bundle.substring(comma + 1)
+                        : null;
+
+                if (name.length() > 0) {
+                    // no name, ignore this one
+                    VersionRange versionRange = new VersionRange(version);
+                    installer.addBundle(name, versionRange, -1);
+                }
             }
-        }
 
-        // check whether the "deploystart" button was clicked
-        boolean start = request.getParameter("deploystart") != null;
+            // check whether the "deploystart" button was clicked
+            boolean start = request.getParameter("deploystart") != null;
 
-        try {
-            installer.install(start);
-        } catch (InstallerException ie) {
-            Throwable cause = (ie.getCause() != null) ? ie.getCause() : ie;
-            this.log.log(LogService.LOG_ERROR, "Cannot install bundles", cause);
-        } finally {
-            installer.dispose();
+            try {
+                installer.install(start);
+            } catch (InstallerException ie) {
+                Throwable cause = (ie.getCause() != null) ? ie.getCause() : ie;
+                getLog().log(LogService.LOG_ERROR, "Cannot install bundles",
+                    cause);
+            } finally {
+                installer.dispose();
+            }
         }
 
         // redirect to bundle list
         return true;
     }
 
-    protected void bindLog(LogService logService) {
-        this.log = logService;
-    }
-
-    protected void unbindLog(LogService logService) {
-        this.log = null;
-    }
-
-    protected void bindInstallerService(InstallerService installerService) {
-        this.installerService = installerService;
-    }
-
-    protected void unbindInstallerService(InstallerService installerService) {
-        this.installerService = null;
-    }
 }

Copied: incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/obr/RefreshRepoAction.java (from r613401, incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/RefreshRepoAction.java)
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/obr/RefreshRepoAction.java?p2=incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/obr/RefreshRepoAction.java&p1=incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/RefreshRepoAction.java&r1=613401&r2=614204&rev=614204&view=diff
==============================================================================
--- incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/RefreshRepoAction.java (original)
+++ incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/obr/RefreshRepoAction.java Tue Jan 22 06:24:42 2008
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sling.osgi.console.web.internal;
+package org.apache.sling.osgi.console.web.internal.obr;
 
 import java.net.URL;
 import java.util.Iterator;
@@ -23,23 +23,14 @@
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.sling.osgi.assembly.installer.BundleRepositoryAdmin;
-import org.apache.sling.osgi.assembly.installer.InstallerService;
 import org.apache.sling.osgi.assembly.installer.Repository;
 import org.apache.sling.osgi.console.web.Action;
 
-/**
- * The <code>InstallFromRepoAction</code> TODO
- *
- * @scr.component metatype="false"
- * @scr.reference name="installer" interface="org.apache.sling.osgi.assembly.installer.InstallerService"
- * @scr.service
- */
-public class RefreshRepoAction implements Action {
+public class RefreshRepoAction extends AbstractObrPlugin implements Action {
 
     public static final String NAME = "refreshOBR";
-    public static final String PARAM_REPO = "repository";
 
-    private BundleRepositoryAdmin repoAdmin;
+    public static final String PARAM_REPO = "repository";
 
     public String getName() {
         return NAME;
@@ -49,42 +40,44 @@
         return NAME;
     }
 
-    /* (non-Javadoc)
-     * @see org.apache.sling.manager.web.internal.Action#performAction(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
-     */
     public boolean performAction(HttpServletRequest request,
-            HttpServletResponse response)  {
+            HttpServletResponse response) {
 
-        String repositoryURL = request.getParameter("repository");
-        Iterator<Repository> repos = this.repoAdmin.getRepositories();
-        Repository repo = this.getRepository(repos, repositoryURL);
-
-        URL repoURL = null;
-        if (repo != null) {
-            repoURL = repo.getURL();
-        } else {
-            try {
-                repoURL = new URL(repositoryURL);
-            } catch (Throwable t) {
-                // don't care, just ignore
+        BundleRepositoryAdmin repoAdmin = getBundleRepositoryAdmin();
+        if (repoAdmin != null) {
+            String repositoryURL = request.getParameter("repository");
+            Iterator<Repository> repos = repoAdmin.getRepositories();
+            Repository repo = this.getRepository(repos, repositoryURL);
+
+            URL repoURL = null;
+            if (repo != null) {
+                repoURL = repo.getURL();
+            } else {
+                try {
+                    repoURL = new URL(repositoryURL);
+                } catch (Throwable t) {
+                    // don't care, just ignore
+                }
             }
-        }
 
-        // log.log(LogService.LOG_DEBUG, "Refreshing " + repo.getURL());
-        if (repoURL != null) {
-            try {
-                this.repoAdmin.addRepository(repoURL);
-            } catch (Exception e) {
-                // TODO: log.log(LogService.LOG_ERROR, "Cannot refresh Repository " + repo.getURL());
+            // log.log(LogService.LOG_DEBUG, "Refreshing " + repo.getURL());
+            if (repoURL != null) {
+                try {
+                    repoAdmin.addRepository(repoURL);
+                } catch (Exception e) {
+                    // TODO: log.log(LogService.LOG_ERROR, "Cannot refresh
+                    // Repository " + repo.getURL());
+                }
             }
         }
 
         return true;
     }
 
-    //---------- internal -----------------------------------------------------
+    // ---------- internal -----------------------------------------------------
 
-    private Repository getRepository(Iterator<Repository> repos, String repositoryUrl) {
+    private Repository getRepository(Iterator<Repository> repos,
+            String repositoryUrl) {
         if (repositoryUrl == null || repositoryUrl.length() == 0) {
             return null;
         }
@@ -99,11 +92,4 @@
         return null;
     }
 
-    protected void bindInstaller(InstallerService installerService) {
-        this.repoAdmin = installerService.getBundleRepositoryAdmin();
-    }
-
-    protected void unbindInstaller(InstallerService installerService) {
-        this.repoAdmin = null;
-    }
 }

Added: incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/servlet/ConfigurationListener.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/servlet/ConfigurationListener.java?rev=614204&view=auto
==============================================================================
--- incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/servlet/ConfigurationListener.java (added)
+++ incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/servlet/ConfigurationListener.java Tue Jan 22 06:24:42 2008
@@ -0,0 +1,53 @@
+/*
+ * 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.osgi.console.web.internal.servlet;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.ManagedService;
+
+class ConfigurationListener implements ManagedService {
+
+    private final SlingManager slingManager;
+
+    static ServiceRegistration create(SlingManager slingManager) {
+        ConfigurationListener cl = new ConfigurationListener(slingManager);
+
+        Dictionary<String, String> props = new Hashtable<String, String>();
+        props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
+        props.put(Constants.SERVICE_DESCRIPTION,
+            "Sling Management Console Configuration Receiver");
+        props.put(Constants.SERVICE_PID, slingManager.getClass().getName());
+
+        return slingManager.getBundleContext().registerService(
+            ManagedService.class.getName(), cl, props);
+    }
+
+    private ConfigurationListener(SlingManager slingManager) {
+        this.slingManager = slingManager;
+    }
+
+    @SuppressWarnings("unchecked")
+    public void updated(Dictionary config) {
+        slingManager.updateConfiguration(config);
+    }
+}
\ No newline at end of file

Added: incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/servlet/Logger.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/servlet/Logger.java?rev=614204&view=auto
==============================================================================
--- incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/servlet/Logger.java (added)
+++ incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/servlet/Logger.java Tue Jan 22 06:24:42 2008
@@ -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.osgi.console.web.internal.servlet;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.service.log.LogService;
+import org.osgi.util.tracker.ServiceTracker;
+
+public class Logger {
+
+    private ServiceTracker logTracker;
+
+    Logger(BundleContext bundleContext) {
+        logTracker = new ServiceTracker(bundleContext,
+            LogService.class.getName(), null);
+        logTracker.open();
+    }
+
+    void dispose() {
+        if (logTracker != null) {
+            logTracker.close();
+        }
+    }
+
+    public void log(int logLevel, String message) {
+        log(logLevel, message, null);
+    }
+
+    public void log(int logLevel, String message, Throwable t) {
+        Object log = logTracker.getService();
+        if (log != null) {
+            ((LogService) log).log(logLevel, message, t);
+        } else {
+            String level;
+            switch (logLevel) {
+                case LogService.LOG_DEBUG:
+                    level = "*DEBUG*";
+                    break;
+                case LogService.LOG_INFO:
+                    level = "*INFO *";
+                    break;
+                case LogService.LOG_WARNING:
+                    level = "*WARN *";
+                    break;
+                case LogService.LOG_ERROR:
+                    level = "*ERROR*";
+                    break;
+                default:
+                    level = "*" + logLevel + "*";
+                    break;
+            }
+
+            if (message == null && t != null) {
+                message = t.getMessage();
+            }
+
+            System.out.println(level + " " + message);
+            if (t != null) {
+                t.printStackTrace(System.out);
+            }
+        }
+    }
+}

Added: incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/servlet/SlingHttpContext.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/servlet/SlingHttpContext.java?rev=614204&view=auto
==============================================================================
--- incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/servlet/SlingHttpContext.java (added)
+++ incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/servlet/SlingHttpContext.java Tue Jan 22 06:24:42 2008
@@ -0,0 +1,227 @@
+/*
+ * 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.osgi.console.web.internal.servlet;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URL;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.osgi.service.http.HttpContext;
+import org.osgi.service.http.HttpService;
+
+final class SlingHttpContext implements HttpContext {
+
+    private static final String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate";
+
+    private static final String HEADER_AUTHORIZATION = "Authorization";
+
+    private static final String AUTHENTICATION_SCHEME_BASIC = "Basic";
+
+    /**
+     * The encoding table which causes BaseFlex encoding/deconding to work like
+     * Base64 encoding/deconding.
+     */
+    private static final String base64Table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+    /**
+     * The pad character used in Base64 encoding/deconding.
+     */
+    private static final char base64Pad = '=';
+
+    String realm;
+
+    String userId;
+    String user;
+
+    private final HttpContext base;
+
+    SlingHttpContext(HttpService httpService, String realm, String userId, String password) {
+        this.base = httpService.createDefaultHttpContext();
+        this.realm = realm;
+        this.userId = userId;
+        this.user = encode(userId, password);
+    }
+
+    public String getMimeType(String name) {
+        return this.base.getMimeType(name);
+    }
+
+    public URL getResource(String name) {
+        URL url = this.base.getResource(name);
+        if (url == null && name.endsWith("/")) {
+            return this.base.getResource(name.substring(0, name.length() - 1));
+        }
+        return url;
+    }
+
+    /**
+     * Checks the <code>Authorization</code> header of the request for Basic
+     * authentication user name and password. If contained, the credentials are
+     * compared to the user name and password set for the Sling Console.
+     * <p>
+     * If no user name is set, the <code>Authorization</code> header is
+     * ignored and the client is assumed to be authenticated.
+     *
+     * @param request The HTTP request used to get the
+     *            <code>Authorization</code> header.
+     * @param response The HTTP response used to send the authentication request
+     *            if authentication is required but not satisfied.
+     * @return <code>true</code> if authentication is required and not
+     *         satisfied by the request.
+     */
+    public boolean handleSecurity(HttpServletRequest request,
+            HttpServletResponse response) {
+
+        // don't care for authentication if no user name is configured
+        if (this.user == null) {
+            return true;
+        }
+
+        // Return immediately if the header is missing
+        String authHeader = request.getHeader(HEADER_AUTHORIZATION);
+        if (authHeader != null && authHeader.length() > 0) {
+
+            // Get the authType (Basic, Digest) and authInfo (user/password)
+            // from
+            // the header
+            authHeader = authHeader.trim();
+            int blank = authHeader.indexOf(' ');
+            if (blank > 0) {
+                String authType = authHeader.substring(0, blank);
+                String authInfo = authHeader.substring(blank).trim();
+
+                // Check whether authorization type matches
+                if (authType.equalsIgnoreCase(AUTHENTICATION_SCHEME_BASIC)
+                    && this.user.equals(authInfo)) {
+
+                    // as per the spec, set attributes
+                    request.setAttribute(HttpContext.AUTHENTICATION_TYPE, "");
+                    request.setAttribute(HttpContext.REMOTE_USER, this.userId);
+
+                    // succeed
+                    return true;
+                }
+            }
+        }
+
+        // request authentication
+        response.setHeader(HEADER_WWW_AUTHENTICATE, AUTHENTICATION_SCHEME_BASIC
+            + " realm=\"" + this.realm + "\"");
+        try {
+            response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+        } catch (IOException ioe) {
+            // failed sending the error, fall back to setting the status
+            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+        }
+
+        // inform HttpService that authentication failed
+        return false;
+    }
+
+
+    /**
+     * Base64 encodes the user name and password for comparison to the value of
+     * a Basic encoded HTTP header authentication.
+     *
+     * @param user The name of the user in the username/password pair
+     * @param password The password in the username/password pair
+     * @return The Base64 encoded username/password pair or <code>null</code>
+     *         if <code>user</code> is <code>null</code> or empty.
+     */
+    public static String encode(String user, String password) {
+
+        /* check arguments */
+        if (user == null || user.length() == 0) return null;
+
+        String srcString = user + ":";
+        if (password != null && password.length() > 0) {
+            srcString += password;
+        }
+
+        // need bytes
+        byte[] src;
+        try {
+            src = srcString.getBytes("ISO-8859-1");
+        } catch (UnsupportedEncodingException uee) {
+            // we do not expect this, the API presribes ISO-8859-1 to be present
+            // anyway, fallback to platform default
+            src = srcString.getBytes();
+        }
+
+        int srcsize = src.length;
+        int tbllen = base64Table.length();
+
+        StringBuffer result = new StringBuffer(srcsize);
+
+        /* encode */
+        int tblpos = 0;
+        int bitpos = 0;
+        int bitsread = -1;
+        int inpos = 0;
+        int pos = 0;
+
+        while (inpos <= srcsize) {
+
+            if (bitsread < 0) {
+                if (inpos < srcsize) {
+                    pos = src[inpos++];
+                } else {
+                    // inpos++;
+                    // pos = 0;
+                    break;
+                }
+                bitsread = 7;
+            }
+
+            tblpos = 0;
+            bitpos = tbllen / 2;
+            while (bitpos > 0) {
+                if (bitsread < 0) {
+                    pos = (inpos < srcsize) ? src[inpos] : '\0';
+                    inpos++;
+                    bitsread = 7;
+                }
+
+                /* test if bit at pos <bitpos> in <pos> is set.. */
+                if (((1 << bitsread) & pos) != 0) tblpos += bitpos;
+
+                bitpos /= 2;
+                bitsread--;
+            }
+
+            // got one
+            result.append(base64Table.charAt(tblpos));
+        }
+
+        /* add the padding bytes */
+        while (bitsread != -1) {
+            bitpos = tbllen / 2;
+            while (bitpos > 0) {
+                if (bitsread < 0) bitsread = 7;
+                bitpos /= 2;
+                bitsread--;
+            }
+
+            result.append(base64Pad);
+        }
+
+        return result.toString();
+    }
+}
\ No newline at end of file

Added: incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/servlet/SlingManager.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/servlet/SlingManager.java?rev=614204&view=auto
==============================================================================
--- incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/servlet/SlingManager.java (added)
+++ incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/servlet/SlingManager.java Tue Jan 22 06:24:42 2008
@@ -0,0 +1,605 @@
+/*
+ * 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.osgi.console.web.internal.servlet;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import javax.servlet.GenericServlet;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.FileUploadException;
+import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+import org.apache.commons.fileupload.servlet.ServletRequestContext;
+import org.apache.sling.osgi.console.web.Action;
+import org.apache.sling.osgi.console.web.Render;
+import org.apache.sling.osgi.console.web.internal.BaseManagementPlugin;
+import org.apache.sling.osgi.console.web.internal.Util;
+import org.apache.sling.osgi.console.web.internal.compendium.AjaxConfigManagerAction;
+import org.apache.sling.osgi.console.web.internal.compendium.ComponentRenderAction;
+import org.apache.sling.osgi.console.web.internal.compendium.ConfigManager;
+import org.apache.sling.osgi.console.web.internal.core.AjaxBundleDetailsAction;
+import org.apache.sling.osgi.console.web.internal.core.BundleListRender;
+import org.apache.sling.osgi.console.web.internal.core.InstallAction;
+import org.apache.sling.osgi.console.web.internal.core.RefreshPackagesAction;
+import org.apache.sling.osgi.console.web.internal.core.SetStartLevelAction;
+import org.apache.sling.osgi.console.web.internal.core.StartAction;
+import org.apache.sling.osgi.console.web.internal.core.StopAction;
+import org.apache.sling.osgi.console.web.internal.core.UninstallAction;
+import org.apache.sling.osgi.console.web.internal.core.UpdateAction;
+import org.apache.sling.osgi.console.web.internal.misc.AssemblyListRender;
+import org.apache.sling.osgi.console.web.internal.misc.ConfigurationRender;
+import org.apache.sling.osgi.console.web.internal.obr.BundleRepositoryRender;
+import org.apache.sling.osgi.console.web.internal.obr.InstallFromRepoAction;
+import org.apache.sling.osgi.console.web.internal.obr.RefreshRepoAction;
+import org.apache.sling.osgi.console.web.internal.system.GCAction;
+import org.apache.sling.osgi.console.web.internal.system.ShutdownAction;
+import org.apache.sling.osgi.console.web.internal.system.ShutdownRender;
+import org.apache.sling.osgi.console.web.internal.system.VMStatRender;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.http.HttpContext;
+import org.osgi.service.http.HttpService;
+import org.osgi.service.log.LogService;
+import org.osgi.util.tracker.ServiceTracker;
+
+/**
+ * The <code>Sling Manager</code> TODO
+ * 
+ * @scr.component ds="no" label="%manager.name"
+ *                description="%manager.description"
+ */
+public class SlingManager extends GenericServlet {
+
+    /** Pseudo class version ID to keep the IDE quite. */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * The name and value of a parameter which will prevent redirection to a
+     * render after the action has been executed (value is "_noredir_"). This
+     * may be used by programmatic action submissions.
+     */
+    public static final String PARAM_NO_REDIRECT_AFTER_ACTION = "_noredir_";
+
+    /**
+     * @scr.property value="/sling"
+     */
+    private static final String PROP_MANAGER_ROOT = "manager.root";
+
+    /**
+     * @scr.property value="list"
+     */
+    private static final String PROP_DEFAULT_RENDER = "default.render";
+
+    /**
+     * @scr.property value="Sling Management Console"
+     */
+    private static final String PROP_REALM = "realm";
+
+    /**
+     * @scr.property value="admin"
+     */
+    private static final String PROP_USER_NAME = "username";
+
+    /**
+     * @scr.property value="admin"
+     */
+    private static final String PROP_PASSWORD = "password";
+
+    private static final Class<?>[] PLUGIN_CLASSES = {
+        AjaxConfigManagerAction.class, ComponentRenderAction.class,
+        ConfigManager.class, AjaxBundleDetailsAction.class,
+        BundleListRender.class, InstallAction.class,
+        RefreshPackagesAction.class, SetStartLevelAction.class,
+        StartAction.class, StopAction.class, UninstallAction.class,
+        UpdateAction.class, AssemblyListRender.class,
+        ConfigurationRender.class, BundleRepositoryRender.class,
+        InstallFromRepoAction.class, RefreshRepoAction.class, GCAction.class,
+        ShutdownAction.class, ShutdownRender.class, VMStatRender.class };
+
+    private BundleContext bundleContext;
+
+    private Logger log;
+
+    private ServiceTracker httpServiceTracker;
+
+    private HttpService httpService;
+
+    private ServiceTracker operationsTracker;
+
+    private ServiceTracker rendersTracker;
+
+    private ServiceRegistration configurationListener;
+
+    private Map<String, Action> operations = new HashMap<String, Action>();
+
+    private SortedMap<String, Render> renders = new TreeMap<String, Render>();
+
+    private Render defaultRender;
+
+    private String defaultRenderName;
+
+    private String webManagerRoot;
+
+    private Dictionary<String, Object> configuration;
+
+    public SlingManager(BundleContext bundleContext) {
+
+        this.bundleContext = bundleContext;
+        this.log = new Logger(bundleContext);
+
+        updateConfiguration(null);
+        
+        try {
+            this.configurationListener = ConfigurationListener.create(this);
+        } catch (Throwable t) {
+            // might be caused by CM not available
+        }
+
+        // track renders and operations
+        operationsTracker = new OperationServiceTracker(this);
+        operationsTracker.open();
+        rendersTracker = new RenderServiceTracker(this);
+        rendersTracker.open();
+        httpServiceTracker = new HttpServiceTracker(this);
+        httpServiceTracker.open();
+
+        for (Class<?> pluginClass : PLUGIN_CLASSES) {
+            try {
+                Object plugin = pluginClass.newInstance();
+                if (plugin instanceof BaseManagementPlugin) {
+                    ((BaseManagementPlugin) plugin).setBundleContext(bundleContext);
+                    ((BaseManagementPlugin) plugin).setLogger(log);
+                }
+                if (plugin instanceof Action) {
+                    bindOperation((Action) plugin);
+                }
+                if (plugin instanceof Render) {
+                    bindRender((Render) plugin);
+                }
+            } catch (Throwable t) {
+                // todo: log
+            }
+        }
+    }
+
+    public void dispose() {
+
+        if (configurationListener != null) {
+            configurationListener.unregister();
+            configurationListener = null;
+        }
+
+        if (operationsTracker != null) {
+            operationsTracker.close();
+            operationsTracker = null;
+        }
+
+        if (rendersTracker != null) {
+            rendersTracker.close();
+            rendersTracker = null;
+        }
+
+        if (httpServiceTracker != null) {
+            httpServiceTracker.close();
+            httpServiceTracker = null;
+        }
+
+        // simply remove all operations, we should not be used anymore
+        this.defaultRender = null;
+        this.operations.clear();
+        this.renders.clear();
+
+        if (log != null) {
+            log.dispose();
+        }
+
+        this.bundleContext = null;
+    }
+
+    public void service(ServletRequest req, ServletResponse res)
+            throws ServletException, IOException {
+
+        HttpServletRequest request = (HttpServletRequest) req;
+        HttpServletResponse response = (HttpServletResponse) res;
+
+        // handle the request action, terminate if done
+        if (this.handleAction(request, response)) {
+            return;
+        }
+
+        // check whether we are not at .../{webManagerRoot}
+        if (request.getRequestURI().endsWith(this.webManagerRoot)) {
+            response.sendRedirect(request.getRequestURI() + "/"
+                + this.defaultRender.getName());
+            return;
+        }
+
+        // otherwise we render the response
+        Render render = this.getRender(request);
+        if (render == null) {
+            response.sendError(HttpServletResponse.SC_NOT_FOUND);
+            return;
+        }
+
+        String current = render.getName();
+        boolean disabled = false; // should take action==shutdown into
+        // account:
+        // Boolean.valueOf(request.getParameter("disabled")).booleanValue();
+
+        PrintWriter pw = Util.startHtml(response, render.getLabel());
+        Util.navigation(pw, this.renders.values(), current, disabled);
+
+        render.render(request, response);
+
+        Util.endHhtml(pw);
+    }
+
+    protected boolean handleAction(HttpServletRequest req,
+            HttpServletResponse resp) throws IOException {
+        // check action
+        String actionName = this.getParameter(req, Util.PARAM_ACTION);
+        if (actionName != null) {
+            Action action = this.operations.get(actionName);
+            if (action != null) {
+                boolean redirect = true;
+                try {
+                    redirect = action.performAction(req, resp);
+                } catch (IOException ioe) {
+                    this.log(ioe.getMessage(), ioe);
+                } catch (ServletException se) {
+                    this.log(se.getMessage(), se.getRootCause());
+                }
+
+                // maybe overwrite redirect
+                if (PARAM_NO_REDIRECT_AFTER_ACTION.equals(getParameter(req,
+                    PARAM_NO_REDIRECT_AFTER_ACTION))) {
+                    resp.setStatus(HttpServletResponse.SC_OK);
+                    resp.setContentType("text/html");
+                    resp.getWriter().println("Ok");
+                    return true;
+                }
+
+                if (redirect) {
+                    String uri = req.getRequestURI();
+                    // Object pars =
+                    // req.getAttribute(Action.ATTR_REDIRECT_PARAMETERS);
+                    // if (pars instanceof String) {
+                    // uri += "?" + pars;
+                    // }
+                    resp.sendRedirect(uri);
+                }
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    protected Render getRender(HttpServletRequest request) {
+
+        String page = request.getRequestURI();
+
+        // remove trailing slashes
+        while (page.endsWith("/")) {
+            page = page.substring(0, page.length() - 1);
+        }
+
+        // take last part of the name
+        int lastSlash = page.lastIndexOf('/');
+        if (lastSlash >= 0) {
+            page = page.substring(lastSlash + 1);
+        }
+
+        Render render = this.renders.get(page);
+        return (render == null) ? this.defaultRender : render;
+    }
+
+    private String getParameter(HttpServletRequest request, String name) {
+        // just get the parameter if not a multipart/form-data POST
+        if (!ServletFileUpload.isMultipartContent(new ServletRequestContext(
+            request))) {
+            return request.getParameter(name);
+        }
+
+        // check, whether we alread have the parameters
+        @SuppressWarnings("unchecked")
+        Map<String, FileItem[]> params = (Map<String, FileItem[]>) request.getAttribute(Util.ATTR_FILEUPLOAD);
+        if (params == null) {
+            // parameters not read yet, read now
+            // Create a factory for disk-based file items
+            DiskFileItemFactory factory = new DiskFileItemFactory();
+            factory.setSizeThreshold(256000);
+
+            // Create a new file upload handler
+            ServletFileUpload upload = new ServletFileUpload(factory);
+            upload.setSizeMax(-1);
+
+            // Parse the request
+            params = new HashMap<String, FileItem[]>();
+            try {
+                @SuppressWarnings("unchecked")
+                List<FileItem> items = upload.parseRequest(request);
+                for (FileItem fi : items) {
+                    FileItem[] current = params.get(fi.getFieldName());
+                    if (current == null) {
+                        current = new FileItem[] { fi };
+                    } else {
+                        FileItem[] newCurrent = new FileItem[current.length + 1];
+                        System.arraycopy(current, 0, newCurrent, 0,
+                            current.length);
+                        newCurrent[current.length] = fi;
+                        current = newCurrent;
+                    }
+                    params.put(fi.getFieldName(), current);
+                }
+            } catch (FileUploadException fue) {
+                // TODO: log
+            }
+            request.setAttribute(Util.ATTR_FILEUPLOAD, params);
+        }
+
+        FileItem[] param = params.get(name);
+        if (param != null) {
+            for (int i = 0; i < param.length; i++) {
+                if (param[i].isFormField()) {
+                    return param[i].getString();
+                }
+            }
+        }
+
+        // no valid string parameter, fail
+        return null;
+    }
+
+    BundleContext getBundleContext() {
+        return bundleContext;
+    }
+
+    private static class HttpServiceTracker extends ServiceTracker {
+
+        private final SlingManager slingManager;
+
+        HttpServiceTracker(SlingManager slingManager) {
+            super(slingManager.getBundleContext(), HttpService.class.getName(),
+                null);
+            this.slingManager = slingManager;
+        }
+
+        @Override
+        public Object addingService(ServiceReference reference) {
+            Object operation = super.addingService(reference);
+            if (operation instanceof HttpService) {
+                slingManager.bindHttpService((HttpService) operation);
+            }
+            return operation;
+        }
+
+        @Override
+        public void removedService(ServiceReference reference, Object service) {
+            if (service instanceof HttpService) {
+                slingManager.unbindHttpService((HttpService) service);
+            }
+
+            super.removedService(reference, service);
+        }
+    }
+
+    private static class OperationServiceTracker extends ServiceTracker {
+
+        private final SlingManager slingManager;
+
+        OperationServiceTracker(SlingManager slingManager) {
+            super(slingManager.getBundleContext(), Action.SERVICE, null);
+            this.slingManager = slingManager;
+        }
+
+        @Override
+        public Object addingService(ServiceReference reference) {
+            Object operation = super.addingService(reference);
+            if (operation instanceof Action) {
+                slingManager.bindOperation((Action) operation);
+            }
+            return operation;
+        }
+
+        @Override
+        public void removedService(ServiceReference reference, Object service) {
+            if (service instanceof Action) {
+                slingManager.bindOperation((Action) service);
+            }
+
+            super.removedService(reference, service);
+        }
+    }
+
+    private static class RenderServiceTracker extends ServiceTracker {
+
+        private final SlingManager slingManager;
+
+        RenderServiceTracker(SlingManager slingManager) {
+            super(slingManager.getBundleContext(), Render.SERVICE, null);
+            this.slingManager = slingManager;
+        }
+
+        @Override
+        public Object addingService(ServiceReference reference) {
+            Object operation = super.addingService(reference);
+            if (operation instanceof Render) {
+                slingManager.bindRender((Render) operation);
+            }
+            return operation;
+        }
+
+        @Override
+        public void removedService(ServiceReference reference, Object service) {
+            if (service instanceof Render) {
+                slingManager.bindRender((Render) service);
+            }
+
+            super.removedService(reference, service);
+        }
+    }
+
+    protected synchronized void bindHttpService(HttpService httpService) {
+        Dictionary<String, Object> config = getConfiguration();
+
+        // get authentication details
+        String realm = this.getProperty(config, PROP_REALM,
+            "Sling Management Console");
+        String userId = this.getProperty(config, PROP_USER_NAME, null);
+        String password = this.getProperty(config, PROP_PASSWORD, null);
+
+        // register the servlet and resources
+        try {
+            HttpContext httpContext = new SlingHttpContext(httpService, realm,
+                userId, password);
+
+            Dictionary<String, String> servletConfig = toStringConfig(config);
+
+            // rest of sling
+            httpService.registerServlet(this.webManagerRoot, this,
+                servletConfig, httpContext);
+            httpService.registerResources(this.webManagerRoot + "/res", "/res",
+                httpContext);
+
+        } catch (Exception e) {
+            log.log(LogService.LOG_ERROR, "Problem setting up", e);
+        }
+
+        this.httpService = httpService;
+    }
+
+    protected synchronized void unbindHttpService(HttpService httpService) {
+        httpService.unregister(this.webManagerRoot + "/res");
+        httpService.unregister(this.webManagerRoot);
+
+        if (this.httpService == httpService) {
+            this.httpService = null;
+        }
+    }
+
+    protected void bindOperation(Action operation) {
+        this.operations.put(operation.getName(), operation);
+    }
+
+    protected void unbindOperation(Action operation) {
+        this.operations.remove(operation.getName());
+    }
+
+    protected void bindRender(Render render) {
+        this.renders.put(render.getName(), render);
+
+        if (this.defaultRender == null) {
+            this.defaultRender = render;
+        } else if (render.getName().equals(this.defaultRenderName)) {
+            this.defaultRender = render;
+        }
+    }
+
+    protected void unbindRender(Render render) {
+        this.renders.remove(render.getName());
+
+        if (this.defaultRender == render) {
+            if (this.renders.isEmpty()) {
+                this.defaultRender = null;
+            } else {
+                this.defaultRender = this.renders.values().iterator().next();
+            }
+        }
+    }
+
+    private Dictionary<String, Object> getConfiguration() {
+        return configuration;
+    }
+
+    void updateConfiguration(Dictionary<String, Object> config) {
+        if (config == null) {
+            config = new Hashtable<String, Object>();
+        }
+        
+        configuration = config;
+
+        defaultRenderName = (String) config.get(PROP_DEFAULT_RENDER);
+        if (defaultRenderName != null && renders.get(defaultRenderName) != null) {
+            defaultRender = renders.get(defaultRenderName);
+        }
+
+        // get the web manager root path
+        webManagerRoot = this.getProperty(config, PROP_MANAGER_ROOT, "/sling");
+        if (!webManagerRoot.startsWith("/")) {
+            webManagerRoot = "/" + webManagerRoot;
+        }
+
+        // might update http service registration
+        HttpService httpService = this.httpService;
+        if (httpService != null) {
+            synchronized (this) {
+                unbindHttpService(httpService);
+                bindHttpService(httpService);
+            }
+        }
+    }
+
+    /**
+     * Returns the named property from the configuration. If the property does
+     * not exist, the default value <code>def</code> is returned.
+     * 
+     * @param config The properties from which to returned the named one
+     * @param name The name of the property to return
+     * @param def The default value if the named property does not exist
+     * @return The value of the named property as a string or <code>def</code>
+     *         if the property does not exist
+     */
+    private String getProperty(Dictionary<String, Object> config, String name,
+            String def) {
+        Object value = config.get(name);
+        if (value instanceof String) {
+            return (String) value;
+        }
+
+        if (value == null) {
+            return def;
+        }
+
+        return String.valueOf(value);
+    }
+
+    private Dictionary<String, String> toStringConfig(Dictionary<?, ?> config) {
+        Dictionary<String, String> stringConfig = new Hashtable<String, String>();
+        for (Enumeration<?> ke = config.keys(); ke.hasMoreElements();) {
+            Object key = ke.nextElement();
+            stringConfig.put(key.toString(), String.valueOf(config.get(key)));
+        }
+        return stringConfig;
+    }
+}