You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by gd...@apache.org on 2006/09/15 17:02:16 UTC

svn commit: r446624 [2/4] - in /geronimo/server/trunk: ./ assemblies/geronimo-jetty-j2ee/ configs/jetty-clustering-builder-wadi/ configs/jetty-clustering-builder-wadi/src/ configs/jetty-clustering-builder-wadi/src/plan/ configs/jetty-clustering-wadi/ c...

Added: geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/BasicReplicationManagerFactoryGBean.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/BasicReplicationManagerFactoryGBean.java?view=auto&rev=446624
==============================================================================
--- geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/BasicReplicationManagerFactoryGBean.java (added)
+++ geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/BasicReplicationManagerFactoryGBean.java Fri Sep 15 08:02:12 2006
@@ -0,0 +1,50 @@
+package org.apache.geronimo.clustering.wadi;
+
+import org.apache.geronimo.gbean.GBeanInfo;
+import org.apache.geronimo.gbean.GBeanInfoBuilder;
+import org.apache.geronimo.gbean.GBeanLifecycle;
+import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
+import org.codehaus.wadi.group.Dispatcher;
+import org.codehaus.wadi.replication.manager.ReplicationManager;
+import org.codehaus.wadi.replication.manager.ReplicationManagerFactory;
+import org.codehaus.wadi.replication.manager.basic.BasicReplicationManagerFactory;
+import org.codehaus.wadi.replication.storage.ReplicaStorageFactory;
+import org.codehaus.wadi.replication.strategy.BackingStrategyFactory;
+
+public class BasicReplicationManagerFactoryGBean implements ReplicationManagerFactory, GBeanLifecycle {
+    private ReplicationManagerFactory factory;
+    
+    public ReplicationManager factory(Dispatcher dispatcher, ReplicaStorageFactory replicaStoragefactory,
+            BackingStrategyFactory backingStrategyFactory) {
+        return factory.factory(dispatcher, replicaStoragefactory, backingStrategyFactory);
+    }
+    
+    public void doFail() {
+        factory = null;
+    }
+
+    public void doStart() throws Exception {
+        factory = new BasicReplicationManagerFactory();
+    }
+
+    public void doStop() throws Exception {
+        factory = null;
+    }
+    
+    public static final GBeanInfo GBEAN_INFO;
+    
+    static {
+        GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(BasicReplicationManagerFactoryGBean.class, 
+                NameFactory.GERONIMO_SERVICE);
+
+        infoBuilder.addInterface(ReplicationManagerFactory.class);
+        
+        infoBuilder.setConstructor(new String[0]);
+        
+        GBEAN_INFO = infoBuilder.getBeanInfo();
+    }
+    
+    public static GBeanInfo getGBeanInfo() {
+        return GBEAN_INFO;
+    }
+}

Added: geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/BasicWADISessionManager.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/BasicWADISessionManager.java?view=auto&rev=446624
==============================================================================
--- geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/BasicWADISessionManager.java (added)
+++ geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/BasicWADISessionManager.java Fri Sep 15 08:02:12 2006
@@ -0,0 +1,387 @@
+/**
+ *
+ * Copyright 2006 The Apache Software Foundation
+ *
+ *  Licensed 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.clustering.wadi;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import javax.servlet.ServletContext;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.geronimo.clustering.Node;
+import org.apache.geronimo.clustering.Session;
+import org.apache.geronimo.clustering.SessionAlreadyExistException;
+import org.apache.geronimo.clustering.SessionListener;
+import org.apache.geronimo.clustering.SessionManager;
+import org.apache.geronimo.gbean.GBeanInfo;
+import org.apache.geronimo.gbean.GBeanInfoBuilder;
+import org.apache.geronimo.gbean.GBeanLifecycle;
+import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
+import org.codehaus.wadi.Collapser;
+import org.codehaus.wadi.Contextualiser;
+import org.codehaus.wadi.Emoter;
+import org.codehaus.wadi.Evicter;
+import org.codehaus.wadi.Immoter;
+import org.codehaus.wadi.Invocation;
+import org.codehaus.wadi.InvocationException;
+import org.codehaus.wadi.Manager;
+import org.codehaus.wadi.ManagerConfig;
+import org.codehaus.wadi.Motable;
+import org.codehaus.wadi.PoolableInvocationWrapperPool;
+import org.codehaus.wadi.SessionPool;
+import org.codehaus.wadi.Streamer;
+import org.codehaus.wadi.ValuePool;
+import org.codehaus.wadi.group.Dispatcher;
+import org.codehaus.wadi.impl.AbsoluteEvicter;
+import org.codehaus.wadi.impl.ClusterContextualiser;
+import org.codehaus.wadi.impl.ClusteredManager;
+import org.codehaus.wadi.impl.DummyContextualiser;
+import org.codehaus.wadi.impl.DummyReplicaterFactory;
+import org.codehaus.wadi.impl.HashingCollapser;
+import org.codehaus.wadi.impl.HybridRelocater;
+import org.codehaus.wadi.impl.MemoryContextualiser;
+import org.codehaus.wadi.impl.SerialContextualiser;
+import org.codehaus.wadi.impl.SerialContextualiserFrontingMemory;
+import org.codehaus.wadi.impl.SimpleSessionPool;
+import org.codehaus.wadi.impl.SimpleStreamer;
+import org.codehaus.wadi.impl.SimpleValuePool;
+import org.codehaus.wadi.impl.StatelessContextualiser;
+import org.codehaus.wadi.replication.manager.ReplicationManagerFactory;
+import org.codehaus.wadi.replication.storage.ReplicaStorageFactory;
+import org.codehaus.wadi.replication.strategy.BackingStrategyFactory;
+import org.codehaus.wadi.web.AttributesFactory;
+import org.codehaus.wadi.web.WebSession;
+import org.codehaus.wadi.web.WebSessionPool;
+import org.codehaus.wadi.web.WebSessionWrapperFactory;
+import org.codehaus.wadi.web.impl.AtomicallyReplicableSessionFactory;
+import org.codehaus.wadi.web.impl.DistributableAttributesFactory;
+import org.codehaus.wadi.web.impl.DistributableValueFactory;
+import org.codehaus.wadi.web.impl.DummyRouter;
+import org.codehaus.wadi.web.impl.DummyStatefulHttpServletRequestWrapperPool;
+import org.codehaus.wadi.web.impl.StandardSessionWrapperFactory;
+import org.codehaus.wadi.web.impl.WebSessionToSessionPoolAdapter;
+
+import EDU.oswego.cs.dl.util.concurrent.Sync;
+
+/**
+ * 
+ * @version $Rev$ $Date$
+ */
+public class BasicWADISessionManager implements GBeanLifecycle, SessionManager, WADISessionManager {
+    private static final Log log = LogFactory.getLog(BasicWADISessionManager.class);
+    
+    private final int sweepInterval;
+    private final int numPartitions;
+    private final ReplicationManagerFactory replicationManagerFactory;
+    private final ReplicaStorageFactory replicaStorageFactory;
+    private final BackingStrategyFactory backingStrategyFactory;
+    private final DispatcherHolder dispatcherHolder;
+    private final Set listeners;
+    
+    private ClusteredManager manager;
+
+    public BasicWADISessionManager(int sweepInterval,
+            int numPartitions,
+            ReplicationManagerFactory replicationManagerFactory,
+            ReplicaStorageFactory replicaStorageFactory,
+            BackingStrategyFactory backingStrategyFactory,
+            DispatcherHolder dispatcherHolder) {
+        this.sweepInterval = sweepInterval;
+        this.numPartitions = numPartitions;
+        this.dispatcherHolder = dispatcherHolder;
+        this.replicationManagerFactory = replicationManagerFactory;
+        this.replicaStorageFactory = replicaStorageFactory;
+        this.backingStrategyFactory = backingStrategyFactory;
+        
+        listeners = new HashSet();
+    }
+
+    public void doStart() throws Exception {
+        Dispatcher dispatcher = dispatcherHolder.getDispatcher();
+        
+        boolean strictOrdering = true;
+        Streamer streamer = new SimpleStreamer();
+        Collapser collapser = new HashingCollapser(1024, 10000);
+        Map mmap = Collections.synchronizedMap(new HashMap());
+
+        // end of contextualiser stack
+        Contextualiser contextualiser = new DummyContextualiser();
+        
+        // replica aware contextualiser
+//        ReplicationManager replicationManager = replicationManagerFactory.factory(dispatcher,
+//                replicaStorageFactory,
+//                backingStrategyFactory);
+//        DistributableManagerRehydrater sessionRehydrater = new DistributableManagerRehydrater();
+//        ReplicationManager sessionRepManager = new SessionReplicationManager(replicationManager, sessionRehydrater);
+//        contextualiser = new ReplicaAwareContextualiser(contextualiser, sessionRepManager);
+
+        // cluster aware contextualiser
+        contextualiser = new ClusterContextualiser(contextualiser, collapser, new HybridRelocater(5000, 5000, true));
+
+        contextualiser = new StatelessContextualiser(contextualiser, Pattern.compile("GET|POST", 2), true, 
+                Pattern.compile(".*\\.(JPG|JPEG|GIF|PNG|ICO|HTML|HTM)", 2), false);
+
+        // serialize invocations bound to the same session id
+        contextualiser = new SerialContextualiser(contextualiser, collapser, mmap);
+
+        // in-memory contextualiser 
+        WebSessionPool sessionPool = new SimpleSessionPool(new AtomicallyReplicableSessionFactory());
+        Evicter mevicter = new AbsoluteEvicter(sweepInterval, strictOrdering, 10);
+        SessionPool contextPool = new WebSessionToSessionPoolAdapter(sessionPool);
+        PoolableInvocationWrapperPool requestPool = new DummyStatefulHttpServletRequestWrapperPool();
+        contextualiser = new MotionTracker(contextualiser, mevicter, mmap, streamer, contextPool, requestPool);
+
+        contextualiser = new SerialContextualiserFrontingMemory(contextualiser, new HashingCollapser(1024, 10000));
+        
+        // Manager
+        AttributesFactory attributesFactory = new DistributableAttributesFactory();
+        ValuePool valuePool = new SimpleValuePool(new DistributableValueFactory());
+        WebSessionWrapperFactory wrapperFactory = new StandardSessionWrapperFactory();
+        manager = new ClusteredManager(sessionPool, 
+                        attributesFactory,
+                        valuePool, 
+                        wrapperFactory, 
+                        null, 
+                        contextualiser, 
+                        mmap,
+                        new DummyRouter(), 
+                        true, 
+                        streamer, 
+                        true,
+                        new DummyReplicaterFactory(),
+//                        new ReplicaterAdapterFactory(replicationManager), 
+                        null, 
+                        null,
+                        dispatcher, 
+                        numPartitions, 
+                        collapser);
+//        sessionRehydrater.setManager(manager);
+
+        manager.init(new ManagerConfig() {
+            public void callback(Manager manager) {
+            }
+
+            public ServletContext getServletContext() {
+                return null;
+            }
+        });
+        
+        manager.start();
+    }
+
+    public void doStop() throws Exception {
+        manager.stop();
+    }
+
+    public void doFail() {
+        try {
+            manager.stop();
+        } catch (Exception e) {
+            log.error(e);
+        }
+    }
+
+    public Session createSession(String sessionId) throws SessionAlreadyExistException {
+        WebSession session;
+        try {
+            session = manager.createWithName(sessionId);
+        } catch (org.codehaus.wadi.SessionAlreadyExistException e) {
+            throw new SessionAlreadyExistException(sessionId);
+        }
+        return new WADISessionAdaptor(session);
+    }
+
+    public ClusteredManager getManager() {
+        return manager;
+    }
+    
+    public Node getNode() {
+        return dispatcherHolder.getNode();
+    }
+    
+    public void registerListener(SessionListener listener) {
+        synchronized (listeners) {
+            listeners.add(listener);
+        }
+    }
+
+    public void unregisterListener(SessionListener listener) {
+        synchronized (listeners) {
+            listeners.remove(listener);
+        }
+    }
+
+    private void notifyInboundSessionMigration(WebSession webSession) {
+        synchronized (listeners) {
+            for (Iterator iter = listeners.iterator(); iter.hasNext();) {
+                SessionListener listener = (SessionListener) iter.next();
+                listener.notifyInboundSessionMigration(new WADISessionAdaptor(webSession));
+            }
+        }
+    }
+
+    private WebSession notifyOutboundSessionMigration(WebSession webSession) {
+        synchronized (listeners) {
+            for (Iterator iter = listeners.iterator(); iter.hasNext();) {
+                SessionListener listener = (SessionListener) iter.next();
+                listener.notifyOutboundSessionMigration(new WADISessionAdaptor(webSession));
+            }
+        }
+        return webSession;
+    }
+
+    private class MotionTracker extends MemoryContextualiser {
+        private final Immoter immoter;
+        private final Emoter emoter;
+        
+        public MotionTracker(Contextualiser next, Evicter evicter, Map map, Streamer streamer, SessionPool pool,
+                PoolableInvocationWrapperPool requestPool) {
+            super(next, evicter, map, streamer, pool, requestPool);
+            
+            Immoter immoterDelegate = super.getImmoter();
+            immoter = new InboundSessionTracker(immoterDelegate);
+
+            Emoter emoterDelegate = super.getEmoter();
+            emoter = new OutboundSessionTracker(emoterDelegate);
+        }
+
+        public Immoter getPromoter(Immoter immoter) {
+            Immoter delegate = super.getPromoter(immoter);
+            if (null == immoter) {
+                return new InboundSessionTracker(delegate);
+            } else {
+                return delegate;
+            }
+        }
+
+        public Immoter getImmoter() {
+            return immoter;
+        }
+        
+        public Emoter getEmoter() {
+            return emoter;
+        }
+    }
+
+    private class OutboundSessionTracker implements Emoter {
+        private final Emoter delegate;
+
+        public OutboundSessionTracker(Emoter delegate) {
+            this.delegate = delegate;
+        }
+
+        public void commit(String arg0, Motable arg1) {
+            notifyOutboundSessionMigration((WebSession) arg1);
+            delegate.commit(arg0, arg1);
+        }
+
+        public String getInfo() {
+            return delegate.getInfo();
+        }
+
+        public boolean prepare(String arg0, Motable arg1, Motable arg2) {
+            return delegate.prepare(arg0, arg1, arg2);
+        }
+
+        public void rollback(String arg0, Motable arg1) {
+            delegate.rollback(arg0, arg1);
+        }
+    }
+    
+    private class InboundSessionTracker implements Immoter {
+        private final Immoter delegate;
+
+        public InboundSessionTracker(Immoter delegate) {
+            this.delegate = delegate;
+        }
+
+        public void commit(String arg0, Motable arg1) {
+            notifyInboundSessionMigration((WebSession) arg1);
+            delegate.commit(arg0, arg1);
+        }
+
+        public boolean contextualise(Invocation arg0, String arg1, Motable arg2, Sync arg3) throws InvocationException {
+            return delegate.contextualise(arg0, arg1, arg2, arg3);
+        }
+
+        public String getInfo() {
+            return delegate.getInfo();
+        }
+
+        public Motable nextMotable(String arg0, Motable arg1) {
+            return delegate.nextMotable(arg0, arg1);
+        }
+
+        public boolean prepare(String arg0, Motable arg1, Motable arg2) {
+            return delegate.prepare(arg0, arg1, arg2);
+        }
+
+        public void rollback(String arg0, Motable arg1) {
+            delegate.rollback(arg0, arg1);
+        }
+    }
+    
+    
+    public static final GBeanInfo GBEAN_INFO;
+    
+    public static final String GBEAN_ATTR_SWEEP_INTERVAL = "sweepInterval";
+    public static final String GBEAN_ATTR_NUM_PARTITIONS = "numPartitions";
+
+    public static final String GBEAN_REF_REPLICATION_MANAGER_FACTORY = "ReplicationManagerFactory";
+    public static final String GBEAN_REF_REPLICA_STORAGE_FACTORY = "ReplicaStorageFactory";
+    public static final String GBEAN_REF_BACKING_STRATEGY_FACTORY = "BackingStrategyFactory";
+    public static final String GBEAN_REF_DISPATCHER_HOLDER = "DispatcherHolder";
+
+    static {
+        GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic("WADI Session Manager", 
+                BasicWADISessionManager.class, 
+                NameFactory.GERONIMO_SERVICE);
+        
+        infoBuilder.addAttribute(GBEAN_ATTR_SWEEP_INTERVAL, int.class, true);
+        infoBuilder.addAttribute(GBEAN_ATTR_NUM_PARTITIONS, int.class, true);
+
+        infoBuilder.addReference(GBEAN_REF_REPLICATION_MANAGER_FACTORY, ReplicationManagerFactory.class,
+                NameFactory.GERONIMO_SERVICE);
+        infoBuilder.addReference(GBEAN_REF_REPLICA_STORAGE_FACTORY, ReplicaStorageFactory.class,
+                NameFactory.GERONIMO_SERVICE);
+        infoBuilder.addReference(GBEAN_REF_BACKING_STRATEGY_FACTORY, BackingStrategyFactory.class,
+                NameFactory.GERONIMO_SERVICE);
+        infoBuilder.addReference(GBEAN_REF_DISPATCHER_HOLDER, DispatcherHolder.class, NameFactory.GERONIMO_SERVICE);
+        
+        infoBuilder.addInterface(SessionManager.class);
+        infoBuilder.addInterface(WADISessionManager.class);
+        
+        infoBuilder.setConstructor(new String[]{GBEAN_ATTR_SWEEP_INTERVAL,
+                GBEAN_ATTR_NUM_PARTITIONS,
+                GBEAN_REF_REPLICATION_MANAGER_FACTORY,
+                GBEAN_REF_REPLICA_STORAGE_FACTORY,
+                GBEAN_REF_BACKING_STRATEGY_FACTORY,
+                GBEAN_REF_DISPATCHER_HOLDER});
+
+        GBEAN_INFO = infoBuilder.getBeanInfo();
+    }
+    
+    public static GBeanInfo getGBeanInfo() {
+        return GBEAN_INFO;
+    }
+}

Added: geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/DispatcherHolder.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/DispatcherHolder.java?view=auto&rev=446624
==============================================================================
--- geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/DispatcherHolder.java (added)
+++ geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/DispatcherHolder.java Fri Sep 15 08:02:12 2006
@@ -0,0 +1,30 @@
+/**
+ *
+ * Copyright 2006 The Apache Software Foundation
+ *
+ *  Licensed 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.clustering.wadi;
+
+import org.apache.geronimo.clustering.Node;
+import org.codehaus.wadi.group.Dispatcher;
+
+/**
+ * 
+ * @version $Rev$ $Date$
+ */
+public interface DispatcherHolder {
+    Dispatcher getDispatcher();
+
+    Node getNode();
+}

Added: geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/RoundRobinBackingStrategyFactoryGBean.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/RoundRobinBackingStrategyFactoryGBean.java?view=auto&rev=446624
==============================================================================
--- geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/RoundRobinBackingStrategyFactoryGBean.java (added)
+++ geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/RoundRobinBackingStrategyFactoryGBean.java Fri Sep 15 08:02:12 2006
@@ -0,0 +1,77 @@
+/**
+ *
+ * Copyright 2006 The Apache Software Foundation
+ *
+ *  Licensed 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.clustering.wadi;
+
+import org.apache.geronimo.gbean.GBeanInfo;
+import org.apache.geronimo.gbean.GBeanInfoBuilder;
+import org.apache.geronimo.gbean.GBeanLifecycle;
+import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
+import org.codehaus.wadi.replication.strategy.BackingStrategy;
+import org.codehaus.wadi.replication.strategy.BackingStrategyFactory;
+import org.codehaus.wadi.replication.strategy.RoundRobinBackingStrategyFactory;
+
+/**
+ * 
+ * @version $Rev$ $Date$
+ */
+public class RoundRobinBackingStrategyFactoryGBean implements BackingStrategyFactory, GBeanLifecycle {
+    private final int nbReplica;
+    
+    private BackingStrategyFactory strategyFactory;
+    
+    public RoundRobinBackingStrategyFactoryGBean(int nbReplica) {
+        this.nbReplica = nbReplica;
+    }
+
+    public BackingStrategy factory() {
+        return strategyFactory.factory();
+    }
+
+    public void doFail() {
+        strategyFactory = null;
+    }
+
+    public void doStart() throws Exception {
+        strategyFactory = new RoundRobinBackingStrategyFactory(nbReplica);
+    }
+
+    public void doStop() throws Exception {
+        strategyFactory = null;
+    }
+
+    
+    public static final GBeanInfo GBEAN_INFO;
+    
+    public static final String GBEAN_ATTR_NB_REPLICA = "nbReplica";
+    
+    static {
+        GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(RoundRobinBackingStrategyFactoryGBean.class, 
+                NameFactory.GERONIMO_SERVICE);
+        
+        infoBuilder.addAttribute(GBEAN_ATTR_NB_REPLICA, int.class, true);
+        
+        infoBuilder.addInterface(BackingStrategyFactory.class);
+
+        infoBuilder.setConstructor(new String[] {GBEAN_ATTR_NB_REPLICA});
+        
+        GBEAN_INFO = infoBuilder.getBeanInfo();
+    }
+    
+    public static GBeanInfo getGBeanInfo() {
+        return GBEAN_INFO;
+    }
+}

Added: geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/TribesDispatcherHolder.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/TribesDispatcherHolder.java?view=auto&rev=446624
==============================================================================
--- geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/TribesDispatcherHolder.java (added)
+++ geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/TribesDispatcherHolder.java Fri Sep 15 08:02:12 2006
@@ -0,0 +1,104 @@
+/**
+ *
+ * Copyright 2006 The Apache Software Foundation
+ *
+ *  Licensed 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.clustering.wadi;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.geronimo.clustering.Node;
+import org.apache.geronimo.gbean.GBeanInfo;
+import org.apache.geronimo.gbean.GBeanInfoBuilder;
+import org.apache.geronimo.gbean.GBeanLifecycle;
+import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
+import org.codehaus.wadi.group.Dispatcher;
+import org.codehaus.wadi.group.MessageExchangeException;
+import org.codehaus.wadi.tribes.TribesDispatcher;
+
+/**
+ *
+ * @version $Rev$ $Date$
+ */
+public class TribesDispatcherHolder implements GBeanLifecycle, DispatcherHolder {
+    private static final Log log = LogFactory.getLog(TribesDispatcherHolder.class); 
+    
+    private final String clusterName;
+    private final long inactiveTime;
+    private final Node node;
+
+    private TribesDispatcher dispatcher;
+
+    public TribesDispatcherHolder(String clusterName, long inactiveTime, Node node) {
+        this.clusterName = clusterName;
+        this.inactiveTime = inactiveTime;
+        this.node = node;
+    }
+
+    public void doStart() throws Exception {
+        dispatcher = new TribesDispatcher(clusterName, node.getName(), inactiveTime, null);
+        dispatcher.start();
+    }
+
+    public void doStop() throws Exception {
+        dispatcher.stop();
+    }
+
+    public void doFail() {
+        try {
+            dispatcher.stop();
+        } catch (MessageExchangeException e) {
+            log.error(e);
+        }
+    }
+    
+    public Dispatcher getDispatcher() {
+        return dispatcher;
+    }
+
+    public Node getNode() {
+        return node;
+    }
+    
+    
+    public static final GBeanInfo GBEAN_INFO;
+    
+    public static final String GBEAN_ATTR_CLUSTER_NAME = "clusterName";
+    public static final String GBEAN_ATTR_CLUSTER_URI = "clusterUri";
+    public static final String GBEAN_ATTR_INACTIVE_TIME = "inactiveTime";
+
+    public static final String GBEAN_REF_NODE = "Node";
+
+    static {
+        GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(TribesDispatcherHolder.class, 
+                NameFactory.GERONIMO_SERVICE);
+        
+        infoBuilder.addAttribute(GBEAN_ATTR_CLUSTER_NAME, String.class, true);
+        infoBuilder.addAttribute(GBEAN_ATTR_INACTIVE_TIME, long.class, true);
+        
+        infoBuilder.addReference(GBEAN_REF_NODE, Node.class, NameFactory.GERONIMO_SERVICE);
+
+        infoBuilder.addInterface(DispatcherHolder.class);
+        
+        infoBuilder.setConstructor(new String[] { GBEAN_ATTR_CLUSTER_NAME, 
+                GBEAN_ATTR_INACTIVE_TIME, 
+                GBEAN_REF_NODE });
+        
+        GBEAN_INFO = infoBuilder.getBeanInfo();
+    }
+
+    public static GBeanInfo getGBeanInfo() {
+        return GBEAN_INFO;
+    }
+}

Added: geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/WADIClusteredHandleInterceptor.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/WADIClusteredHandleInterceptor.java?view=auto&rev=446624
==============================================================================
--- geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/WADIClusteredHandleInterceptor.java (added)
+++ geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/WADIClusteredHandleInterceptor.java Fri Sep 15 08:02:12 2006
@@ -0,0 +1,129 @@
+/**
+ *
+ * Copyright 2006 The Apache Software Foundation
+ *
+ *  Licensed 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.clustering.wadi;
+
+import java.io.IOException;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+import org.apache.geronimo.clustering.ClusteredInvocation;
+import org.apache.geronimo.clustering.ClusteredInvocationException;
+import org.apache.geronimo.gbean.GBeanInfo;
+import org.apache.geronimo.gbean.GBeanInfoBuilder;
+import org.apache.geronimo.gbean.GBeanLifecycle;
+import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
+import org.apache.geronimo.jetty.HandleInterceptor;
+import org.apache.geronimo.jetty.cluster.AbstractClusteredHandleInterceptor;
+import org.codehaus.wadi.InvocationException;
+import org.codehaus.wadi.impl.ClusteredManager;
+import org.codehaus.wadi.web.impl.WebInvocation;
+import org.mortbay.http.HttpRequest;
+import org.mortbay.http.HttpResponse;
+import org.mortbay.jetty.servlet.ServletHttpRequest;
+import org.mortbay.jetty.servlet.ServletHttpResponse;
+
+
+/**
+ * 
+ * @version $Rev$ $Date$
+ */
+public class WADIClusteredHandleInterceptor extends AbstractClusteredHandleInterceptor implements GBeanLifecycle {
+    private final WADISessionManager sessionManager;
+    
+    private ClusteredManager wadiManager;
+
+    public WADIClusteredHandleInterceptor(WADISessionManager sessionManager) {
+        this.sessionManager = sessionManager;
+    }
+    
+    public void doStart() throws Exception {
+        wadiManager = sessionManager.getManager();
+    }
+    
+    public void doStop() throws Exception {
+        wadiManager = null;
+    }
+    
+    public void doFail() {
+        wadiManager = null;
+    }
+    
+    protected ClusteredInvocation newClusteredInvocation(String pathInContext, String pathParams, HttpRequest request,
+            HttpResponse response, HandleInterceptor end) {
+        return new WADIWebClusteredInvocation(pathInContext, pathParams, request, response, end);
+    }
+    
+    protected class WADIWebClusteredInvocation extends WebClusteredInvocation {
+        
+        public WADIWebClusteredInvocation(String pathInContext, String pathParams, HttpRequest request,
+                HttpResponse response, HandleInterceptor end) {
+            super(pathInContext, pathParams, request, response, end);
+        }
+
+        public void invoke() throws ClusteredInvocationException {
+            ServletHttpRequest servletHttpRequest = (ServletHttpRequest) request.getWrapper();
+            ServletHttpResponse servletHttpResponse = (ServletHttpResponse) response.getWrapper();
+
+            WebInvocation invocation = WebInvocation.getThreadLocalInstance();
+            FilterChain chainAdapter = new FilterChain() {
+                public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
+                    try {
+                        invokeLocally();
+                    } catch (ClusteredInvocationException e) {
+                        throw (IOException) new IOException().initCause(e);
+                    }
+                }
+            };
+            invocation.init(servletHttpRequest, servletHttpResponse, chainAdapter);
+            try {
+                wadiManager.contextualise(invocation);
+            } catch (InvocationException e) {
+                Throwable throwable = e.getCause();
+                if (throwable instanceof IOException) {
+                    throw new ClusteredInvocationException(throwable);
+                } else if (throwable instanceof ServletException) {
+                    throw new ClusteredInvocationException(throwable);
+                } else {
+                    throw new ClusteredInvocationException(e);
+                }
+            }
+        }
+    }
+    
+    public static final GBeanInfo GBEAN_INFO;
+
+    public static final String GBEAN_REF_WADI_SESSION_MANAGER = "WADISessionManager";
+
+    static {
+        GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic("WADI Clustered Handle Interceptor",
+                WADIClusteredHandleInterceptor.class, NameFactory.GERONIMO_SERVICE);
+        
+        infoBuilder.addReference(GBEAN_REF_WADI_SESSION_MANAGER, WADISessionManager.class, 
+                NameFactory.GERONIMO_SERVICE);
+        
+        infoBuilder.setConstructor(new String[]{GBEAN_REF_WADI_SESSION_MANAGER});
+
+        GBEAN_INFO = infoBuilder.getBeanInfo();
+    }
+    
+    public static GBeanInfo getGBeanInfo() {
+        return GBEAN_INFO;
+    }
+}

Added: geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/WADISessionAdaptor.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/WADISessionAdaptor.java?view=auto&rev=446624
==============================================================================
--- geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/WADISessionAdaptor.java (added)
+++ geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/WADISessionAdaptor.java Fri Sep 15 08:02:12 2006
@@ -0,0 +1,128 @@
+/**
+ *
+ * Copyright 2006 The Apache Software Foundation
+ *
+ *  Licensed 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.clustering.wadi;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.geronimo.clustering.Session;
+import org.codehaus.wadi.web.WebSession;
+
+/**
+ *
+ * @version $Rev$ $Date$
+ */
+public class WADISessionAdaptor implements Session {
+    private final WebSession session;
+    private final Map state;
+    
+    public WADISessionAdaptor(WebSession session) {
+        this.session = session;
+        
+        state = new StateMap();
+    }
+
+    public String getSessionId() {
+        return session.getId();
+    }
+
+    public void release() {
+        try {
+            session.destroy();
+        } catch (Exception e) {
+            throw new IllegalStateException("Cannot release session " + session);
+        }
+    }
+
+    public Object addState(String key, Object value) {
+        return session.setAttribute(key, value);
+    }
+
+    public Object getState(String key) {
+        return session.getAttribute(key);
+     }
+
+    public Object removeState(String key) {
+        return session.removeAttribute(key);
+    }
+
+    public Map getState() {
+        return state;
+    }
+    
+    private class StateMap implements Map {
+
+        public Object put(Object key, Object value) {
+            String wadiKey = ensureTypeAndCast(key);
+            return addState(wadiKey, value);
+        }
+
+        public Object remove(Object key) {
+            String wadiKey = ensureTypeAndCast(key);
+            return removeState(wadiKey);
+        }
+
+        public void clear() {
+            throw new UnsupportedOperationException();
+        }
+
+        public boolean containsKey(Object key) {
+            throw new UnsupportedOperationException();
+        }
+
+        public boolean containsValue(Object value) {
+            throw new UnsupportedOperationException();
+        }
+
+        public Set entrySet() {
+            throw new UnsupportedOperationException();
+        }
+
+        public Object get(Object key) {
+            String wadiKey = ensureTypeAndCast(key);
+            return getState(wadiKey);
+        }
+
+        public boolean isEmpty() {
+            throw new UnsupportedOperationException();
+        }
+
+        public Set keySet() {
+            return session.getAttributeNameSet();
+        }
+
+        public void putAll(Map t) {
+            throw new UnsupportedOperationException();
+        }
+
+        public int size() {
+            return session.getAttributeNameSet().size();
+        }
+
+        public Collection values() {
+            throw new UnsupportedOperationException();
+        }
+
+        private String ensureTypeAndCast(Object key) {
+            if (!(key instanceof String)) {
+                throw new ClassCastException(String.class + " is expected.");
+            }
+            return (String) key;
+        }
+    }
+}

Added: geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/WADISessionManager.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/WADISessionManager.java?view=auto&rev=446624
==============================================================================
--- geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/WADISessionManager.java (added)
+++ geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/WADISessionManager.java Fri Sep 15 08:02:12 2006
@@ -0,0 +1,27 @@
+/**
+ *
+ * Copyright 2006 The Apache Software Foundation
+ *
+ *  Licensed 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.clustering.wadi;
+
+import org.codehaus.wadi.impl.ClusteredManager;
+
+/**
+ * 
+ * @version $Rev$ $Date$
+ */
+public interface WADISessionManager {
+    ClusteredManager getManager();
+}
\ No newline at end of file

Added: geronimo/server/trunk/modules/geronimo-clustering/pom.xml
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-clustering/pom.xml?view=auto&rev=446624
==============================================================================
--- geronimo/server/trunk/modules/geronimo-clustering/pom.xml (added)
+++ geronimo/server/trunk/modules/geronimo-clustering/pom.xml Fri Sep 15 08:02:12 2006
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+    Copyright 2006 The Apache Software Foundation
+
+    Licensed 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.modules</groupId>
+        <artifactId>modules</artifactId>
+        <version>1.2-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>geronimo-clustering</artifactId>
+    <name>Geronimo Clustering</name>
+    
+    <!--
+    
+    HACK: Need to explicitly configure SCM for this module since its artifactId
+          does not match the directory it lives in.
+    
+    FIXME: Rename module directory or artifactId.
+    
+    -->
+    <scm>
+        <connection>scm:svn:https://svn.apache.org/repos/asf/geronimo/trunk/modules/clustering</connection>
+        <developerConnection>scm:svn:https://${maven.username}@svn.apache.org/repos/asf/geronimo/trunk/modules/clustering</developerConnection>
+        <url>http://svn.apache.org/repos/asf/geronimo/trunk/modules/clustering</url>
+    </scm>
+    
+    <dependencies>
+        <dependency>
+            <groupId>${pom.groupId}</groupId>
+            <artifactId>geronimo-system</artifactId>
+            <version>${pom.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>${pom.groupId}</groupId>
+            <artifactId>geronimo-j2ee</artifactId>
+            <version>${pom.version}</version>
+        </dependency>
+    </dependencies>
+    
+</project>
+

Added: geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/BasicNode.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/BasicNode.java?view=auto&rev=446624
==============================================================================
--- geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/BasicNode.java (added)
+++ geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/BasicNode.java Fri Sep 15 08:02:12 2006
@@ -0,0 +1,57 @@
+/**
+ *
+ * Copyright 2006 The Apache Software Foundation
+ *
+ *  Licensed 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.clustering;
+
+import org.apache.geronimo.gbean.GBeanInfo;
+import org.apache.geronimo.gbean.GBeanInfoBuilder;
+import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
+
+/**
+ *
+ * @version $Rev$ $Date$
+ */
+public class BasicNode implements Node {
+    private final String name;
+    
+    public BasicNode(String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+    
+    public static final GBeanInfo GBEAN_INFO;
+    
+    public static final String GBEAN_ATTR_NODE_NAME = "nodeName";
+    
+    static {
+        GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(BasicNode.class, NameFactory.GERONIMO_SERVICE);
+        
+        infoBuilder.addAttribute(GBEAN_ATTR_NODE_NAME, String.class, true);
+        
+        infoBuilder.addInterface(Node.class);
+        
+        infoBuilder.setConstructor(new String[] {GBEAN_ATTR_NODE_NAME});
+        
+        GBEAN_INFO = infoBuilder.getBeanInfo();
+    }
+
+    public static GBeanInfo getGBeanInfo() {
+        return GBEAN_INFO;
+    }
+}

Added: geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/ClusteredInvocation.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/ClusteredInvocation.java?view=auto&rev=446624
==============================================================================
--- geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/ClusteredInvocation.java (added)
+++ geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/ClusteredInvocation.java Fri Sep 15 08:02:12 2006
@@ -0,0 +1,56 @@
+/**
+ *
+ * Copyright 2006 The Apache Software Foundation
+ *
+ *  Licensed 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.clustering;
+
+
+/**
+ * Represents a clustered invocation.
+ * <p>
+ * A clustered invocation is intended to be a thin wrapper around an actual invocation enhancing this latter with
+ * an association to a local SessionManager. For instance, an HTTPRequest is an actual invocation.
+ * <p> 
+ * A clustered invocation is interposed between a client and the Session he wants to access to provide cluster wide
+ * access serialization to the requested Session. A clustered invocation is associated to a local SessionManager, even
+ * if no contract captures such a relationship. When a clustered invocation is executed one of the two following 
+ * scenarios happen:
+ * <ul>
+ * <li>the clustered invocation is executed locally. A local execution implies that the local SessionManager associated
+ * to the clustered invocation is owning the Session (may be after a migration); or</li>
+ * <li>the clustered invocation is executed remotely on the Node where the Session is being owned.</li>
+ * </ul>
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ClusteredInvocation {
+    
+    /**
+     * Invokes the clustered invocation.
+     * 
+     * @throws ClusteredInvocationException Thrown when the invocation cannot be successfully executed. This may
+     * be either due to the fact that the actual invocation has failed or the requestedSessionId is unknown by
+     * the associated local SessionManager and its remote peers.
+     */
+    void invoke() throws ClusteredInvocationException;
+    
+    /**
+     * Gets the sessionId of the Session bound to the invocation represented by this instance.
+     *  
+     * @return sessionId of the targeted Session.
+     */
+    String getRequestedSessionId();
+    
+}

Added: geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/ClusteredInvocationException.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/ClusteredInvocationException.java?view=auto&rev=446624
==============================================================================
--- geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/ClusteredInvocationException.java (added)
+++ geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/ClusteredInvocationException.java Fri Sep 15 08:02:12 2006
@@ -0,0 +1,40 @@
+/**
+ *
+ * Copyright 2006 The Apache Software Foundation
+ *
+ *  Licensed 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.clustering;
+
+/**
+ *
+ * @version $Rev$ $Date$
+ */
+public class ClusteredInvocationException extends Exception {
+
+    public ClusteredInvocationException() {
+        super();
+    }
+
+    public ClusteredInvocationException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public ClusteredInvocationException(String message) {
+        super(message);
+    }
+
+    public ClusteredInvocationException(Throwable cause) {
+        super(cause);
+    }
+}

Added: geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/Node.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/Node.java?view=auto&rev=446624
==============================================================================
--- geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/Node.java (added)
+++ geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/Node.java Fri Sep 15 08:02:12 2006
@@ -0,0 +1,33 @@
+/**
+ *
+ * Copyright 2006 The Apache Software Foundation
+ *
+ *  Licensed 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.clustering;
+
+/**
+ * Represents a node.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface Node {
+    
+    /**
+     * Gets the node name.
+     * 
+     * @return Node name
+     */
+    String getName();
+
+}

Added: geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/Session.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/Session.java?view=auto&rev=446624
==============================================================================
--- geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/Session.java (added)
+++ geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/Session.java Fri Sep 15 08:02:12 2006
@@ -0,0 +1,78 @@
+/**
+ *
+ * Copyright 2006 The Apache Software Foundation
+ *
+ *  Licensed 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.clustering;
+
+import java.util.Map;
+
+/**
+ * Represents a clustered session.
+ * <p>
+ * A Session is created by a SessionManager and is uniquely identified by its sessionId. More accurately, this 
+ * sessionId is unique within the set of SessionManagers from which this Session has been sourced. If two Sessions 
+ * have the same sessionId, then a client can be sure that they have been created from two distinct set of 
+ * SessionManagers.
+ * <p>
+ * A Session provides Map like contracts to manipulate state information. State information must be Serializable as
+ * it may be marshalled automatically by the underpinning local SessionManager. At any given point of time, a Session
+ * is uniquely "instantiated" once cluster wide. Also, cluster wide accesses to a given Session are 
+ * ensured to be serialized by the set of SessionManagers from which the Session has been sourced. The interposition
+ * of a ClusteredInvocation between a client and the Session this client would like to access enforces unique
+ * instantiation and access serialization cluster wide for a given Session.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface Session {
+    
+    /**
+     * Gets the sessionId.
+     * 
+     * @return sessionId.
+     */
+    String getSessionId();
+
+    /**
+     * Map like contract to manipulate state information.
+     */
+    Object addState(String key, Object value);
+
+    /**
+     * Map like contract to manipulate state information.
+     */
+    Object getState(String key);
+
+    /**
+     * Map like contract to manipulate state information.
+     */
+    Object removeState(String key);
+    
+    /**
+     * Map like contract to manipulate state information.
+     * <p>
+     * The returned Map is mutable and is backed by the session.
+     */
+    Map getState();
+    
+    /**
+     * Releases the session.
+     * <p>
+     * When a Session is released, it is released from the underlying set of SessionManagers. In other words, its
+     * sessionId is unknown and its state is permanently lost. After the release of a Session, the behavior of
+     * the other methods is undefined.
+     */
+    void release();
+    
+}

Added: geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/SessionAlreadyExistException.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/SessionAlreadyExistException.java?view=auto&rev=446624
==============================================================================
--- geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/SessionAlreadyExistException.java (added)
+++ geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/SessionAlreadyExistException.java Fri Sep 15 08:02:12 2006
@@ -0,0 +1,40 @@
+/**
+ *
+ * Copyright 2006 The Apache Software Foundation
+ *
+ *  Licensed 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.clustering;
+
+/**
+ *
+ * @version $Rev$ $Date$
+ */
+public class SessionAlreadyExistException extends Exception {
+
+    public SessionAlreadyExistException() {
+        super();
+    }
+
+    public SessionAlreadyExistException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public SessionAlreadyExistException(String message) {
+        super(message);
+    }
+
+    public SessionAlreadyExistException(Throwable cause) {
+        super(cause);
+    }
+}

Added: geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/SessionListener.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/SessionListener.java?view=auto&rev=446624
==============================================================================
--- geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/SessionListener.java (added)
+++ geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/SessionListener.java Fri Sep 15 08:02:12 2006
@@ -0,0 +1,51 @@
+/**
+ *
+ * Copyright 2006 The Apache Software Foundation
+ *
+ *  Licensed 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.clustering;
+
+/**
+ * Callback listener for inbound and outbound Session migration.
+ * <p>
+ * A Session is preemptively moved between its associated set of SessionManagers. For instance, when a 
+ * ClusteredInvocation for a given Session is invoked on a Node where the local SessionManager, RequestingSM, does not 
+ * own the targeted Session, the SessionManager owning the Session, OwningSM, the Session may be moved from OwningSM
+ * to RequestingSM. OwningSM, prior to relinquish the Session, executes notifyOutboundSessionMigration and provides
+ * the Session under migration. RequestingRM, after having acquired the Session ownership, executes 
+ * notifyInboundSessionMigration and provides the Session under migration.
+ * <p>
+ * The typical usage of these migration callbacks are to allow a wrapping SessionManager, e.g. an HTTPSession manager,
+ * to perform bookkeeping operations.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface SessionListener {
+    
+    /**
+     * Calls when the ownership of the provided Session is acquired by the SessionManager to which this listener
+     * is attached.
+     * 
+     * @param session New Session now owned by the attached SessionManager.
+     */
+    void notifyInboundSessionMigration(Session session);
+    
+    /**
+     * Calls when the ownership of the provided Session is relinquished to another SessionManager.
+     * 
+     * @param session Session now owned by another SessionManager.
+     */
+    void notifyOutboundSessionMigration(Session session);
+    
+}

Added: geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/SessionManager.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/SessionManager.java?view=auto&rev=446624
==============================================================================
--- geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/SessionManager.java (added)
+++ geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/SessionManager.java Fri Sep 15 08:02:12 2006
@@ -0,0 +1,61 @@
+/**
+ *
+ * Copyright 2006 The Apache Software Foundation
+ *
+ *  Licensed 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.clustering;
+
+/**
+ * Represents a local SessionManager.
+ * <p>
+ * A local SessionManager works collaboratively with remote SessionManagers to manage Session instances. A local 
+ * SessionMananger along with its associated remote SessionManagers are a single space where Session instances live.
+ * In this space, each Session is ensured to have a unique sessionId. This contract is enforced during creation of
+ * a Session instance by a local SessionManager. A Session in this space is preemptively migrated from one local 
+ * SessionManager to another. The interposition of a ClusteredInvocation between a Client and the Session he wants to
+ * access ensures that at any point in time a Session is uniquely instantiated once cluster wide. Clients can
+ * receive migration callbacks via the registration of SessionListener.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface SessionManager {
+    
+    /**
+     * Creates a Session having the specified sessionId.
+     * 
+     * @param sessionId Unique identifier of the Session instance.
+     * @return Session instance.
+     * @throws SessionAlreadyExistException Thrown when the provided sessiondId already exists in the Session space
+     * of this local SessionManager and its associated remote SessionManagers.
+     */
+    Session createSession(String sessionId) throws SessionAlreadyExistException;
+    
+    /**
+     * Registers a migration listener. 
+     */
+    void registerListener(SessionListener listener);    
+
+    /**
+     * Unregisters a migration listener.
+     */
+    void unregisterListener(SessionListener listener);    
+
+    /**
+     * Gets the Node hosting this local SessionManager.
+     * 
+     * @return Hosting Node.
+     */
+    Node getNode();
+
+}

Modified: geronimo/server/trunk/modules/geronimo-deployment/src/main/java/org/apache/geronimo/deployment/NamespaceDrivenBuilder.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-deployment/src/main/java/org/apache/geronimo/deployment/NamespaceDrivenBuilder.java?view=diff&rev=446624&r1=446623&r2=446624
==============================================================================
--- geronimo/server/trunk/modules/geronimo-deployment/src/main/java/org/apache/geronimo/deployment/NamespaceDrivenBuilder.java (original)
+++ geronimo/server/trunk/modules/geronimo-deployment/src/main/java/org/apache/geronimo/deployment/NamespaceDrivenBuilder.java Fri Sep 15 08:02:12 2006
@@ -22,11 +22,15 @@
 import org.apache.xmlbeans.XmlObject;
 import org.apache.geronimo.common.DeploymentException;
 import org.apache.geronimo.gbean.AbstractName;
+import org.apache.geronimo.kernel.repository.Environment;
 
 /**
  * @version $Rev$ $Date$
  */
 public interface NamespaceDrivenBuilder {
+
+    void buildEnvironment(XmlObject container, Environment environment) throws DeploymentException;
+ 
     void build(XmlObject container, DeploymentContext applicationContext, DeploymentContext moduleContext) throws DeploymentException;
 
     String getNamespace();

Modified: geronimo/server/trunk/modules/geronimo-deployment/src/main/java/org/apache/geronimo/deployment/NamespaceDrivenBuilderCollection.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-deployment/src/main/java/org/apache/geronimo/deployment/NamespaceDrivenBuilderCollection.java?view=diff&rev=446624&r1=446623&r2=446624
==============================================================================
--- geronimo/server/trunk/modules/geronimo-deployment/src/main/java/org/apache/geronimo/deployment/NamespaceDrivenBuilderCollection.java (original)
+++ geronimo/server/trunk/modules/geronimo-deployment/src/main/java/org/apache/geronimo/deployment/NamespaceDrivenBuilderCollection.java Fri Sep 15 08:02:12 2006
@@ -22,11 +22,13 @@
 import java.util.Iterator;
 import java.util.Collection;
 import java.util.List;
+import java.util.Collections;
 
 import org.apache.geronimo.gbean.ReferenceCollection;
 import org.apache.geronimo.gbean.ReferenceCollectionListener;
 import org.apache.geronimo.gbean.ReferenceCollectionEvent;
 import org.apache.geronimo.common.DeploymentException;
+import org.apache.geronimo.kernel.repository.Environment;
 import org.apache.xmlbeans.XmlObject;
 
 /**
@@ -38,7 +40,7 @@
     private final Set namespaces = new HashSet();
 
     public NamespaceDrivenBuilderCollection(Collection builders) {
-        this.builders = builders;
+        this.builders = builders == null? Collections.EMPTY_SET: builders;
         if (builders instanceof ReferenceCollection) {
             ((ReferenceCollection)builders).addReferenceCollectionListener(new ReferenceCollectionListener() {
 
@@ -53,7 +55,7 @@
                 }
             });
         }
-        for (Iterator iterator = builders.iterator(); iterator.hasNext();) {
+        for (Iterator iterator = this.builders.iterator(); iterator.hasNext();) {
             Object builder = iterator.next();
             addBuilder(builder);
         }
@@ -64,7 +66,14 @@
         if (namespaces.contains(namespace)) {
             throw new IllegalArgumentException("Duplicate namespace in builder set: " + namespace);
         }
-        namespaces.add(namespace);
+        namespaces.add(namespace);                                                                   
+    }
+
+    public void buildEnvironment(XmlObject container, Environment environment) throws DeploymentException {
+        for (Iterator iterator = builders.iterator(); iterator.hasNext();) {
+            NamespaceDrivenBuilder builder = (NamespaceDrivenBuilder) iterator.next();
+            builder.buildEnvironment(container, environment);
+        }
     }
 
     public void build(XmlObject container, DeploymentContext applicationContext, DeploymentContext moduleContext) throws DeploymentException {

Modified: geronimo/server/trunk/modules/geronimo-j2ee-builder/src/main/schema/geronimo-application-1.2.xsd
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-j2ee-builder/src/main/schema/geronimo-application-1.2.xsd?view=diff&rev=446624&r1=446623&r2=446624
==============================================================================
--- geronimo/server/trunk/modules/geronimo-j2ee-builder/src/main/schema/geronimo-application-1.2.xsd (original)
+++ geronimo/server/trunk/modules/geronimo-j2ee-builder/src/main/schema/geronimo-application-1.2.xsd Fri Sep 15 08:02:12 2006
@@ -84,6 +84,13 @@
         </xs:sequence>
     </xs:complexType>
 
+    <xs:element name="clustering" type="geronimo:abstract-clusteringType"/>
+    
+    <xs:complexType name="abstract-clusteringType" abstract="true">
+        <xs:sequence>
+        </xs:sequence>
+    </xs:complexType>
+
     <xs:complexType name="ext-moduleType">
         <xs:annotation>
             <xs:documentation>