You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by ga...@apache.org on 2010/01/17 18:51:56 UTC

svn commit: r900168 - in /geronimo/server/trunk/plugins/wab: ./ geronimo-web-extender/ geronimo-web-extender/src/ geronimo-web-extender/src/main/ geronimo-web-extender/src/main/java/ geronimo-web-extender/src/main/java/org/ geronimo-web-extender/src/ma...

Author: gawor
Date: Sun Jan 17 17:51:55 2010
New Revision: 900168

URL: http://svn.apache.org/viewvc?rev=900168&view=rev
Log:
GERONIMO-5030, GERONIMO-5029: Initial plugin for rfc 66. Contains web container extender that doesn't do any actual work besides tracking web application bundles (WABs) and firing events. The extender code is based on Rick's code in sandbox. The plugin also installs Apache Aries webbundle url handler for converting WARs into WABs

Added:
    geronimo/server/trunk/plugins/wab/
    geronimo/server/trunk/plugins/wab/geronimo-web-extender/
    geronimo/server/trunk/plugins/wab/geronimo-web-extender/pom.xml   (with props)
    geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/
    geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/
    geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/
    geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/
    geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/
    geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/
    geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/
    geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/
    geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/WebApplication.java   (with props)
    geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/WebContainerConstants.java   (with props)
    geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/WebContainerEventDispatcher.java   (with props)
    geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/WebContainerExtender.java   (with props)
    geronimo/server/trunk/plugins/wab/pom.xml   (with props)
    geronimo/server/trunk/plugins/wab/web-extender/
    geronimo/server/trunk/plugins/wab/web-extender/pom.xml   (with props)
    geronimo/server/trunk/plugins/wab/web-extender/src/
    geronimo/server/trunk/plugins/wab/web-extender/src/main/
    geronimo/server/trunk/plugins/wab/web-extender/src/main/history/
    geronimo/server/trunk/plugins/wab/web-extender/src/main/history/dependencies.xml   (with props)
    geronimo/server/trunk/plugins/wab/web-extender/src/main/plan/
    geronimo/server/trunk/plugins/wab/web-extender/src/main/plan/plan.xml   (with props)

Added: geronimo/server/trunk/plugins/wab/geronimo-web-extender/pom.xml
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/plugins/wab/geronimo-web-extender/pom.xml?rev=900168&view=auto
==============================================================================
--- geronimo/server/trunk/plugins/wab/geronimo-web-extender/pom.xml (added)
+++ geronimo/server/trunk/plugins/wab/geronimo-web-extender/pom.xml Sun Jan 17 17:51:55 2010
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+    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.
+-->
+
+<!-- $Rev$ $Date$ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.geronimo.plugins</groupId>
+        <artifactId>wab</artifactId>
+        <version>3.0-SNAPSHOT</version>
+    </parent>
+
+    <groupId>org.apache.geronimo.modules</groupId>
+    <artifactId>geronimo-web-extender</artifactId>
+    <packaging>bundle</packaging>
+    <name>Geronimo Plugins, WAB :: Web Extender</name>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.osgi.core</artifactId> 
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.osgi.compendium</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.ops4j.pax.logging</groupId>
+            <artifactId>pax-logging-api</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Import-Package>
+                            org.osgi.service.event;resolution:=optional,
+                            *
+                        </Import-Package>
+                        <Bundle-Activator>org.apache.geronimo.osgi.web.WebContainerExtender</Bundle-Activator>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
+

Propchange: geronimo/server/trunk/plugins/wab/geronimo-web-extender/pom.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/server/trunk/plugins/wab/geronimo-web-extender/pom.xml
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/server/trunk/plugins/wab/geronimo-web-extender/pom.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Added: geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/WebApplication.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/WebApplication.java?rev=900168&view=auto
==============================================================================
--- geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/WebApplication.java (added)
+++ geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/WebApplication.java Sun Jan 17 17:51:55 2010
@@ -0,0 +1,181 @@
+/*
+ * 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.geronimo.osgi.web;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.osgi.framework.Bundle;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * An instance of a WAB deployed to an available Web Container
+ * instance.
+ * 
+ * @version $Rev$, $Date$
+ */
+public class WebApplication implements Runnable {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(WebApplication.class);
+
+    private final WebContainerExtender extender;
+    // the bundle where the web application resides
+    private final Bundle bundle;
+    // the deployed context path from the bundle headers
+    private final String contextPath;
+    
+    private final AtomicBoolean scheduled = new AtomicBoolean();
+    private final AtomicBoolean running = new AtomicBoolean();
+    
+    private boolean destroyed;
+
+    /**
+     * Construct a WebApplicationImp object to represent a
+     * WAB-resident application.
+     *
+     * @param bundle    The bundle containing the WAB.
+     * @param contextPath
+     *                  The context path from the WAB headers.
+     */
+    public WebApplication(WebContainerExtender extender, Bundle bundle, String contextPath) {
+        this.extender = extender;
+        this.bundle = bundle;
+        this.contextPath = contextPath;
+    }
+
+    public String getContextPath() {
+        return contextPath;        
+    }
+    
+    /**
+     * Provide access to the bundle where the application resides.
+     *
+     * @return The Bundle instance for the WAB.
+     */
+    public Bundle getBundle() {
+        return bundle;
+    }
+
+    /**
+     * Schedule this handler for deployment processing.
+     */
+    public void schedule() {
+        // only one scheduled startup at a time.
+        if (scheduled.compareAndSet(false, true)) {
+            extender.getExecutorService().submit(this);
+        }
+    }
+
+    /**
+     * Run the application deployment process in a separate thread.
+     */
+    public void run() {
+        scheduled.set(false);
+        synchronized (scheduled) {
+            synchronized (running) {
+                running.set(true);
+                try {
+                    doRun();
+                } finally {
+                    running.set(false);
+                    running.notifyAll();
+                }
+            }
+        }
+    }
+
+    private void deploying() {
+        LOGGER.debug("Deploying bundle {}", getBundle().getSymbolicName());
+        extender.getEventDispatcher().deploying(bundle, contextPath);
+    }
+
+    private void deployed() {
+        LOGGER.debug("Deployed bundle {}", getBundle().getSymbolicName());
+        extender.getEventDispatcher().deployed(bundle, contextPath);
+    }
+
+    private void undeploying() {
+        LOGGER.debug("Undeploying bundle {}", bundle.getSymbolicName());
+        extender.getEventDispatcher().undeploying(bundle, contextPath);
+    }
+
+    private void undeployed() {
+        LOGGER.debug("Undeployed bundle {}", bundle.getSymbolicName());
+        extender.getEventDispatcher().undeployed(bundle, contextPath);
+    }
+
+    private void failed(Throwable cause) {
+        extender.getEventDispatcher().failed(bundle, contextPath, cause);
+    }
+    
+    /**
+     * This method must be called inside a synchronized block to ensure this method is not run concurrently
+     */
+    private void doRun() {
+        if (destroyed) {
+            return;
+        }
+        try {
+            // send out a broadcast alert that we're going to do this
+            deploying();
+
+            // TODO: do actual deployment
+            System.out.println("Deploying " + contextPath + " " + bundle);
+            
+            // send out the deployed event
+            deployed();
+        } catch (Throwable exception) {
+            LOGGER.error("Unable to start web application for bundle " + getBundle().getSymbolicName(), exception);
+            // broadcast a failure event
+            failed(exception);
+            // unregister the application and possibly let other WABs with the same ContextPath to deploy
+            extender.unregisterWebApplication(this);
+        }
+    }
+
+    /**
+     * Undeploy a web application.
+     */
+    public void undeploy() {
+        destroyed = true;
+        
+        synchronized (running) {
+            while (running.get()) {
+                try {
+                    running.wait();
+                } catch (InterruptedException e) {
+                    // Ignore
+                }
+            }
+        }
+        
+        // send the undeploying event
+        undeploying();
+        
+        // TODO: do actual undeployment
+        System.out.println("Undeploying " + contextPath + " " + bundle);
+
+        // finished with the undeploy operation
+        undeployed();
+        
+        // unregister the application and possibly let other WABs with the same ContextPath to deploy
+        extender.unregisterWebApplication(this);        
+    }
+
+}

Propchange: geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/WebApplication.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/WebApplication.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/WebApplication.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/WebContainerConstants.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/WebContainerConstants.java?rev=900168&view=auto
==============================================================================
--- geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/WebContainerConstants.java (added)
+++ geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/WebContainerConstants.java Sun Jan 17 17:51:55 2010
@@ -0,0 +1,60 @@
+/**
+ * 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.geronimo.osgi.web;
+
+public interface WebContainerConstants {
+
+    public static final String TOPIC_DEPLOYING = "org/osgi/service/web/DEPLOYING";
+    public static final String TOPIC_DEPLOYED = "org/osgi/service/web/DEPLOYED";
+    public static final String TOPIC_UNDEPLOYING = "org/osgi/service/web/UNDEPLOYING";
+    public static final String TOPIC_UNDEPLOYED = "org/osgi/service/web/UNDEPLOYED";
+    public static final String TOPIC_FAILED = "org/osgi/service/web/FAILED";    
+    
+    /**
+     * The Blueprint extender bundle that is generating this event. This
+     * property is of type <code>Bundle</code>.
+     */
+    public static final String EXTENDER_BUNDLE = "extender.bundle";
+
+    /**
+     * The bundle id of the Blueprint extender bundle that is generating this
+     * event. This property is of type <code>Long</code>.
+     */
+    public static final String EXTENDER_BUNDLE_ID = "extender.bundle.id";
+
+    /**
+     * The bundle symbolic of the Blueprint extender bundle that is generating
+     * this event. This property is of type <code>String</code>.
+     */
+    public static final String EXTENDER_BUNDLE_SYMBOLICNAME = "extender.bundle.symbolicName";
+
+    /**
+     * The bundle version of the Blueprint extender bundle that is generating
+     * this event. This property is of type <code>Version</code>.
+     */
+    public static final String EXTENDER_BUNDLE_VERSION = "extender.bundle.version";
+
+    
+    public static final String CONTEXT_PATH = "context.path";
+    
+    public static final String COLLISION = "collision";
+    
+    public static final String COLLISION_BUNDLES = "collision.bundles";
+}
+

Propchange: geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/WebContainerConstants.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/WebContainerConstants.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/WebContainerConstants.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/WebContainerEventDispatcher.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/WebContainerEventDispatcher.java?rev=900168&view=auto
==============================================================================
--- geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/WebContainerEventDispatcher.java (added)
+++ geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/WebContainerEventDispatcher.java Sun Jan 17 17:51:55 2010
@@ -0,0 +1,208 @@
+/**
+ * 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.geronimo.osgi.web;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.List;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Version;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventAdmin;
+import org.osgi.service.event.EventConstants;
+import org.osgi.util.tracker.ServiceTracker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Support for dispatching Web container lifecycle events to
+ * the EventAdmin service, if it's available.
+ * 
+ * @version $Rev$, $Date$
+ */
+public class WebContainerEventDispatcher {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(WebContainerEventDispatcher.class);
+
+    // our service tracker for the EventAdmin service
+    private ServiceTracker tracker;
+    // the extender bundle we're working on behalf of
+    private Bundle extenderBundle;
+
+    public WebContainerEventDispatcher(BundleContext bundleContext) {
+        this.extenderBundle = bundleContext.getBundle();
+
+        if (isEventAdminPresent()) {
+            // this will track the availability of the EventAdmin service when we need to dispatch
+            tracker = new ServiceTracker(bundleContext, EventAdmin.class.getName(), null);
+            tracker.open();
+        }
+    }
+    
+    private boolean isEventAdminPresent() {
+        try {
+            getClass().getClassLoader().loadClass("org.osgi.service.event.EventAdmin");
+            return true;
+        } catch (Throwable t) {
+            // Ignore, if the EventAdmin package is not available, just don't use it
+            LOGGER.debug("EventAdmin package is not available, just don't use it");
+            return false;
+        }
+    }
+
+    /**
+     * Dispatch a deploying event
+     *
+     * @param bundle The bundle we're deploying.
+     * @param contextPath
+     *               The context path information from the bundle.
+     */
+    public void deploying(Bundle bundle, String contextPath) {
+        dispatch(WebContainerConstants.TOPIC_DEPLOYING, bundle, contextPath);
+    }
+
+    /**
+     * Dispatch a deployed event
+     *
+     * @param bundle The bundle we're deploying.
+     * @param contextPath
+     *               The context path information from the bundle.
+     */
+    public void deployed(Bundle bundle, String contextPath) {
+        dispatch(WebContainerConstants.TOPIC_DEPLOYED, bundle, contextPath);
+    }
+
+    /**
+     * Dispatch an undeploying event
+     *
+     * @param bundle The bundle we're undeploying.
+     * @param contextPath
+     *               The context path information from the bundle.
+     */
+    public void undeploying(Bundle bundle, String contextPath) {
+        dispatch(WebContainerConstants.TOPIC_UNDEPLOYING, bundle, contextPath);
+    }
+
+    /**
+     * Dispatch an undeployed event
+     *
+     * @param bundle The bundle we're undeploying.
+     * @param contextPath
+     *               The context path information from the bundle.
+     */
+    public void undeployed(Bundle bundle, String contextPath) {
+        dispatch(WebContainerConstants.TOPIC_UNDEPLOYED, bundle, contextPath);
+    }
+
+    /**
+     * Dispatch a FAILED event
+     *
+     * @param bundle The bundle we're attempting to deploy
+     * @param contextPath
+     *               The context path information from the bundle.
+     */
+    public void failed(Bundle bundle, String contextPath, Throwable cause) {
+        EventAdmin eventAdmin = getEventAdmin();
+        if (eventAdmin == null) {
+            return;
+        }
+        Dictionary<String, Object> props = createDefaultProperties(bundle, contextPath);
+        if (cause != null) {
+            props.put(EventConstants.EXCEPTION, cause);
+        }
+        eventAdmin.postEvent(new Event(WebContainerConstants.TOPIC_FAILED, props));
+    }
+    
+    /**
+     * Dispatch a FAILED event indicating a contextPath collision
+     *
+     * @param bundle The bundle we're attempting to deploy
+     * @param contextPath
+     *               The context path information from the bundle.
+     */
+    public void collision(Bundle bundle, String contextPath, List<Long> bundleId) {
+        EventAdmin eventAdmin = getEventAdmin();
+        if (eventAdmin == null) {
+            return;
+        }
+        Dictionary<String, Object> props = createDefaultProperties(bundle, contextPath);
+        /*
+         * XXX: The specification doesn't exactly say what type of COLLISION and COLLISION_BUNDLES are
+         */
+        props.put(WebContainerConstants.COLLISION, Boolean.TRUE);
+        props.put(WebContainerConstants.COLLISION_BUNDLES, bundleId);
+        eventAdmin.postEvent(new Event(WebContainerConstants.TOPIC_FAILED, props));
+    }
+    
+    /**
+     * Dispatch an event to the appropriate listeners.
+     *
+     * @param topic  The event topic.
+     * @param bundle The bundle hosting the web application.
+     * @param contextPath
+     *               The contextPath information from the bundle.
+     */
+    private void dispatch(String topic, Bundle bundle, String contextPath) {
+        EventAdmin eventAdmin = getEventAdmin();
+        if (eventAdmin == null) {
+            return;
+        }
+        Dictionary<String, Object> props = createDefaultProperties(bundle, contextPath);
+        eventAdmin.postEvent(new Event(topic, props));
+    }
+
+    private Dictionary<String, Object> createDefaultProperties(Bundle bundle, String contextPath) {
+        Dictionary<String, Object> props = new Hashtable<String, Object>();
+        
+        props.put(EventConstants.BUNDLE_SYMBOLICNAME, bundle.getSymbolicName());
+        props.put(EventConstants.BUNDLE_ID, bundle.getBundleId());
+        props.put(EventConstants.BUNDLE, bundle);
+        props.put(EventConstants.BUNDLE_VERSION, getBundleVersion(bundle));
+        props.put(EventConstants.TIMESTAMP, System.currentTimeMillis());
+        
+        props.put(WebContainerConstants.CONTEXT_PATH, contextPath);
+               
+        props.put(WebContainerConstants.EXTENDER_BUNDLE, extenderBundle);
+        props.put(WebContainerConstants.EXTENDER_BUNDLE_ID, extenderBundle.getBundleId());
+        props.put(WebContainerConstants.EXTENDER_BUNDLE_SYMBOLICNAME, extenderBundle.getSymbolicName());
+        props.put(WebContainerConstants.EXTENDER_BUNDLE_VERSION, getBundleVersion(extenderBundle));
+        
+        return props;
+    }
+    
+    private EventAdmin getEventAdmin() {
+        return (tracker != null) ? (EventAdmin) tracker.getService() : null;
+    }
+    
+    public void destroy() {
+        if (tracker != null) {
+            tracker.close();
+        }
+    }
+
+    private Version getBundleVersion(Bundle bundle) {
+        Dictionary headers = bundle.getHeaders();
+        String version = (String) headers.get(Constants.BUNDLE_VERSION);
+        return (version != null) ? Version.parseVersion(version) : Version.emptyVersion;
+    }
+}
+

Propchange: geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/WebContainerEventDispatcher.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/WebContainerEventDispatcher.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/WebContainerEventDispatcher.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/WebContainerExtender.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/WebContainerExtender.java?rev=900168&view=auto
==============================================================================
--- geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/WebContainerExtender.java (added)
+++ geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/WebContainerExtender.java Sun Jan 17 17:51:55 2010
@@ -0,0 +1,181 @@
+/**
+ * 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.geronimo.osgi.web;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.Constants;
+import org.osgi.util.tracker.BundleTracker;
+import org.osgi.util.tracker.BundleTrackerCustomizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * An extender bundle to manage deployment of Web
+ * Application Bundles (WABs) to the RFC 66 web container.
+ * 
+ * @version $Rev$, $Date$
+ */
+public class WebContainerExtender implements BundleActivator {
+    // the header that identifies a bundle as being a WAB
+    public final static String WEB_CONTEXT_PATH_HEADER = "Web-ContextPath";
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(WebContainerExtender.class);
+
+    private Map<String, WebApplication> contextPathMap;
+    private WebContainerEventDispatcher eventDispatcher;
+    private BundleTracker bt;
+    private ExecutorService executor;
+
+    /**
+     * Activate the bundle and initialize the extender instance.
+     *
+     * @param context The BundleContext for our bundle.
+     */
+    public void start(BundleContext context) {
+        LOGGER.debug("Starting web container extender...");
+
+        executor = Executors.newFixedThreadPool(3);
+        contextPathMap = new HashMap<String, WebApplication>();  
+        eventDispatcher = new WebContainerEventDispatcher(context);
+        bt = new BundleTracker(context, Bundle.STARTING | Bundle.ACTIVE, new WebBundleTrackerCustomizer());
+        bt.open();
+        
+        LOGGER.debug("Web container extender started");
+    }
+
+    public ExecutorService getExecutorService() {
+        return executor;
+    }
+    
+    /**
+     * Get the event dispatcher instance associated with this
+     * application.
+     *
+     * @return The configured event dispatcher information.
+     */
+    public WebContainerEventDispatcher getEventDispatcher() {
+        return eventDispatcher;
+    }   
+    
+    private class WebBundleTrackerCustomizer implements BundleTrackerCustomizer {
+
+        public Object addingBundle(Bundle bundle, BundleEvent event) {
+            if (bundle.getState() == Bundle.ACTIVE) {
+                return deploy(bundle);
+            } else if (bundle.getState() == Bundle.STARTING) {
+                String activationPolicyHeader = (String) bundle.getHeaders().get(Constants.BUNDLE_ACTIVATIONPOLICY);
+                if (activationPolicyHeader != null && activationPolicyHeader.startsWith(Constants.ACTIVATION_LAZY)) {
+                    return deploy(bundle);
+                }
+            }
+            return null;
+        }
+
+        public void modifiedBundle(Bundle bundle, BundleEvent event, Object arg) {
+        }
+
+        public void removedBundle(Bundle bundle, BundleEvent event, Object arg) {
+            undeploy((WebApplication) arg);
+        }
+        
+    }
+
+    /**
+     * Shutdown the extender bundle at termination time.
+     *
+     * @param context Our BundleContext.
+     */
+    public void stop(BundleContext context) {
+        LOGGER.debug("Stopping web container extender...");
+        
+        if (bt != null) {
+            bt.close();
+        }
+        eventDispatcher.destroy();
+        executor.shutdown();
+        
+        LOGGER.debug("Web container extender stopped");
+    }
+
+    /**
+     * Destroy a web application deployment, either as a result
+     * of the host bundle getting started, the extended getting stopped,
+     * or the hosting Web Container service going away.
+     *
+     * @param wab    The deployed application.
+     */
+    private void undeploy(WebApplication wab) {
+        // remove from our global list before destroying
+        wab.undeploy();
+    }
+
+    /**
+     * Check a started bundle to detect if this bundle
+     * should be handled by this extender instance.
+     *
+     * @param bundle The source bundle.
+     */
+    private WebApplication deploy(Bundle bundle) {
+        LOGGER.debug("Scanning bundle {} for WAB application", bundle.getSymbolicName());
+        String contextPath = (String) bundle.getHeaders().get(WEB_CONTEXT_PATH_HEADER);
+        // a WAB MUST have the Web-ContextPath header or it must be ignored by the extender.
+        if (contextPath == null) {
+            LOGGER.debug("No web container application found in bundle {}", bundle.getSymbolicName());
+            return null;
+        }
+        LOGGER.debug("Found web container application in bundle {} with context path: {}", bundle.getSymbolicName(), contextPath);
+        WebApplication webApp = new WebApplication(this, bundle, contextPath);
+        WebApplication deployedApp = registerWebApplication(webApp);
+        if (deployedApp == null) {
+            webApp.schedule();
+            return webApp;
+        } else {
+            List<Long> bundleIds = new ArrayList<Long>();
+            bundleIds.add(deployedApp.getBundle().getBundleId());
+            eventDispatcher.collision(bundle, contextPath, bundleIds);
+            LOGGER.warn("WAB {} cannot be deployed. WAB {} is already deployed with {} Context-Path.", 
+                        new Object[] {bundle, deployedApp.getBundle(), contextPath});
+            return null;
+        }
+    }
+    
+    private synchronized WebApplication registerWebApplication(WebApplication webApp) {
+        WebApplication app = contextPathMap.get(webApp.getContextPath());
+        if (app == null) {
+            contextPathMap.put(webApp.getContextPath(), webApp);
+            return null;
+        } else {
+            return app;
+        }
+    }
+ 
+    protected synchronized void unregisterWebApplication(WebApplication webApp) {
+        contextPathMap.remove(webApp.getContextPath());
+    }
+}

Propchange: geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/WebContainerExtender.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/WebContainerExtender.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/server/trunk/plugins/wab/geronimo-web-extender/src/main/java/org/apache/geronimo/osgi/web/WebContainerExtender.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: geronimo/server/trunk/plugins/wab/pom.xml
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/plugins/wab/pom.xml?rev=900168&view=auto
==============================================================================
--- geronimo/server/trunk/plugins/wab/pom.xml (added)
+++ geronimo/server/trunk/plugins/wab/pom.xml Sun Jan 17 17:51:55 2010
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+
+<!-- $Rev$ $Date$ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.geronimo.plugins</groupId>
+        <artifactId>plugins</artifactId>
+        <version>3.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>wab</artifactId>
+    <name>Geronimo Plugins, WAB</name>
+    <packaging>pom</packaging>
+
+    <description>
+    </description>
+
+    <modules>
+        <module>geronimo-web-extender</module>
+        <module>web-extender</module>
+    </modules>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.apache.aries.web</groupId>
+                <artifactId>org.apache.aries.web.urlhandler</artifactId>
+                <version>1.0.0-incubating-SNAPSHOT</version>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+</project>

Propchange: geronimo/server/trunk/plugins/wab/pom.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/server/trunk/plugins/wab/pom.xml
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/server/trunk/plugins/wab/pom.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Added: geronimo/server/trunk/plugins/wab/web-extender/pom.xml
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/plugins/wab/web-extender/pom.xml?rev=900168&view=auto
==============================================================================
--- geronimo/server/trunk/plugins/wab/web-extender/pom.xml (added)
+++ geronimo/server/trunk/plugins/wab/web-extender/pom.xml Sun Jan 17 17:51:55 2010
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+    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.
+-->
+
+<!-- $Rev$ $Date$ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.geronimo.plugins</groupId>
+        <artifactId>wab</artifactId>
+        <version>3.0-SNAPSHOT</version>
+    </parent>
+
+    <groupId>org.apache.geronimo.configs</groupId>
+    <artifactId>web-extender</artifactId>
+    <name>Geronimo Plugins, WAB :: Web Extender Plugin</name>
+    <packaging>car</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.aries.web</groupId>
+            <artifactId>org.apache.aries.web.urlhandler</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.geronimo.modules</groupId>
+            <artifactId>geronimo-web-extender</artifactId>
+            <version>${version}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.geronimo.buildsupport</groupId>
+                <artifactId>car-maven-plugin</artifactId>
+                <configuration>
+                    <category>Geronimo Core</category>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

Propchange: geronimo/server/trunk/plugins/wab/web-extender/pom.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/server/trunk/plugins/wab/web-extender/pom.xml
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/server/trunk/plugins/wab/web-extender/pom.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Added: geronimo/server/trunk/plugins/wab/web-extender/src/main/history/dependencies.xml
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/plugins/wab/web-extender/src/main/history/dependencies.xml?rev=900168&view=auto
==============================================================================
--- geronimo/server/trunk/plugins/wab/web-extender/src/main/history/dependencies.xml (added)
+++ geronimo/server/trunk/plugins/wab/web-extender/src/main/history/dependencies.xml Sun Jan 17 17:51:55 2010
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<plugin-artifact xmlns:ns2="http://geronimo.apache.org/xml/ns/attributes-1.2" xmlns="http://geronimo.apache.org/xml/ns/plugins-1.3">
+    <module-id>
+        <groupId>org.apache.geronimo.configs</groupId>
+        <artifactId>web-extender</artifactId>
+        <version>3.0-SNAPSHOT</version>
+        <type>car</type>
+    </module-id>
+    <dependency>
+        <groupId>asm</groupId>
+        <artifactId>asm-all</artifactId>
+        <type>jar</type>
+    </dependency>
+    <dependency>
+        <groupId>org.apache.aries.web</groupId>
+        <artifactId>org.apache.aries.web.urlhandler</artifactId>
+        <type>jar</type>
+    </dependency>
+    <dependency>
+        <groupId>org.apache.geronimo.modules</groupId>
+        <artifactId>geronimo-web-extender</artifactId>
+        <type>jar</type>
+    </dependency>
+    <dependency>
+        <groupId>org.ops4j.pax.logging</groupId>
+        <artifactId>pax-logging-api</artifactId>
+        <type>jar</type>
+    </dependency>
+</plugin-artifact>

Propchange: geronimo/server/trunk/plugins/wab/web-extender/src/main/history/dependencies.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/server/trunk/plugins/wab/web-extender/src/main/history/dependencies.xml
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/server/trunk/plugins/wab/web-extender/src/main/history/dependencies.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Added: geronimo/server/trunk/plugins/wab/web-extender/src/main/plan/plan.xml
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/plugins/wab/web-extender/src/main/plan/plan.xml?rev=900168&view=auto
==============================================================================
--- geronimo/server/trunk/plugins/wab/web-extender/src/main/plan/plan.xml (added)
+++ geronimo/server/trunk/plugins/wab/web-extender/src/main/plan/plan.xml Sun Jan 17 17:51:55 2010
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+
+<module xmlns="http://geronimo.apache.org/xml/ns/deployment-${geronimoSchemaVersion}">
+
+
+</module>

Propchange: geronimo/server/trunk/plugins/wab/web-extender/src/main/plan/plan.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/server/trunk/plugins/wab/web-extender/src/main/plan/plan.xml
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/server/trunk/plugins/wab/web-extender/src/main/plan/plan.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml