You are viewing a plain text version of this content. The canonical link for it is here.
Posted to wadi-commits@incubator.apache.org by bd...@apache.org on 2005/12/14 23:36:16 UTC

svn commit: r356933 [21/35] - in /incubator/wadi/trunk: ./ etc/ modules/ modules/assembly/ modules/assembly/src/ modules/assembly/src/bin/ modules/assembly/src/conf/ modules/assembly/src/main/ modules/assembly/src/main/assembly/ modules/core/ modules/c...

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/test/TestReplication.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/test/TestReplication.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/test/TestReplication.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/test/TestReplication.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,212 @@
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.codehaus.wadi.test;
+
+import java.io.File;
+import java.net.InetSocketAddress;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.sql.DataSource;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.axiondb.jdbc.AxionDataSource;
+import org.codehaus.wadi.AttributesFactory;
+import org.codehaus.wadi.Collapser;
+import org.codehaus.wadi.ContextPool;
+import org.codehaus.wadi.Contextualiser;
+import org.codehaus.wadi.Evicter;
+import org.codehaus.wadi.InvocationProxy;
+import org.codehaus.wadi.PoolableInvocationWrapperPool;
+import org.codehaus.wadi.ProxiedLocation;
+import org.codehaus.wadi.ReplicaterFactory;
+import org.codehaus.wadi.SessionIdFactory;
+import org.codehaus.wadi.SessionPool;
+import org.codehaus.wadi.SessionWrapperFactory;
+import org.codehaus.wadi.Streamer;
+import org.codehaus.wadi.ValuePool;
+import org.codehaus.wadi.gridstate.Dispatcher;
+import org.codehaus.wadi.gridstate.PartitionManager;
+import org.codehaus.wadi.gridstate.activecluster.ActiveClusterDispatcher;
+import org.codehaus.wadi.gridstate.impl.DummyPartitionManager;
+import org.codehaus.wadi.http.HTTPProxiedLocation;
+import org.codehaus.wadi.impl.AbstractExclusiveContextualiser;
+import org.codehaus.wadi.impl.AbstractReplicableSession;
+import org.codehaus.wadi.impl.AlwaysEvicter;
+import org.codehaus.wadi.impl.AtomicallyReplicableSessionFactory;
+import org.codehaus.wadi.impl.ClusterContextualiser;
+import org.codehaus.wadi.impl.ClusteredManager;
+import org.codehaus.wadi.impl.DatabaseStore;
+import org.codehaus.wadi.impl.DistributableAttributesFactory;
+import org.codehaus.wadi.impl.DistributableValueFactory;
+import org.codehaus.wadi.impl.DummyContextualiser;
+import org.codehaus.wadi.impl.DummyRelocater;
+import org.codehaus.wadi.impl.DummyRouter;
+import org.codehaus.wadi.impl.DummyStatefulHttpServletRequestWrapperPool;
+import org.codehaus.wadi.impl.ExclusiveStoreContextualiser;
+import org.codehaus.wadi.impl.HashingCollapser;
+import org.codehaus.wadi.impl.MemoryContextualiser;
+import org.codehaus.wadi.impl.MemoryReplicaterFactory;
+import org.codehaus.wadi.impl.NeverEvicter;
+import org.codehaus.wadi.impl.SerialContextualiser;
+import org.codehaus.wadi.impl.SessionToContextPoolAdapter;
+import org.codehaus.wadi.impl.SharedStoreContextualiser;
+import org.codehaus.wadi.impl.SimpleSessionPool;
+import org.codehaus.wadi.impl.SimpleStreamer;
+import org.codehaus.wadi.impl.SimpleValuePool;
+import org.codehaus.wadi.impl.StandardHttpProxy;
+import org.codehaus.wadi.impl.StandardSessionWrapperFactory;
+import org.codehaus.wadi.impl.TomcatSessionIdFactory;
+import org.codehaus.wadi.impl.Utils;
+import org.codehaus.wadi.impl.WebInvocationContext;
+
+public class TestReplication extends TestCase {
+	
+	protected Log _log = LogFactory.getLog(getClass());
+	
+	public TestReplication(String arg0) {
+		super(arg0);
+	}
+	
+	protected void setUp() throws Exception {
+		super.setUp();
+	}
+	
+	protected void tearDown() throws Exception {
+		super.tearDown();
+	}
+	
+	public void testReplication() throws Exception {
+		
+		int sweepInterval=1000*60*60*24; // 1 eviction/day
+		boolean strictOrdering=true;
+		Streamer streamer=new SimpleStreamer();
+		Collapser collapser=new HashingCollapser(100, 1000);
+		
+		// Terminator
+		Contextualiser terminator=new DummyContextualiser();
+		Streamer sessionStreamer=new SimpleStreamer();
+		
+		// DB
+		String url="jdbc:axiondb:WADI";
+		DataSource ds=new AxionDataSource(url);
+		String storeTable="SESSIONS";
+		DatabaseStore store=new DatabaseStore(url, ds, storeTable, false, true, true);
+		boolean clean=true;
+		Contextualiser db=new SharedStoreContextualiser(terminator, collapser, clean, store);
+		
+		// Cluster
+		Contextualiser cluster=new ClusterContextualiser(db, collapser, new DummyRelocater());
+		
+		// Disc
+		Evicter devicter=new NeverEvicter(sweepInterval, strictOrdering);
+		Map dmap=new HashMap();
+		File dir=Utils.createTempDirectory("wadi", ".test", new File("/tmp"));
+		Contextualiser spool=new ExclusiveStoreContextualiser(cluster, collapser, false, devicter, dmap, sessionStreamer, dir);
+		
+		Map mmap=new HashMap();
+		
+		Contextualiser serial=new SerialContextualiser(spool, collapser, mmap);
+		
+		SessionPool sessionPool=new SimpleSessionPool(new AtomicallyReplicableSessionFactory());
+		
+		// Memory
+		Evicter mevicter=new AlwaysEvicter(sweepInterval, strictOrdering);
+		ContextPool contextPool=new SessionToContextPoolAdapter(sessionPool);
+		PoolableInvocationWrapperPool requestPool=new DummyStatefulHttpServletRequestWrapperPool();
+		AbstractExclusiveContextualiser memory=new MemoryContextualiser(serial, mevicter, mmap, streamer, contextPool, requestPool);
+		
+		// Manager
+		int numPartitions=72;
+		AttributesFactory attributesFactory=new DistributableAttributesFactory();
+		ValuePool valuePool=new SimpleValuePool(new DistributableValueFactory());
+		SessionWrapperFactory wrapperFactory=new StandardSessionWrapperFactory();
+		SessionIdFactory idFactory=new TomcatSessionIdFactory();
+		ReplicaterFactory replicaterfactory=new MemoryReplicaterFactory(numPartitions);
+		ProxiedLocation location = new HTTPProxiedLocation(new InetSocketAddress("localhost", 8080));
+		InvocationProxy proxy=new StandardHttpProxy("jsessionid");
+		//String clusterUri="peer://wadi";
+		String clusterUri="tcp://localhost:61616";
+		String clusterName="TEST";
+		String nodeName="test.1";
+		PartitionManager partitionManager=new DummyPartitionManager(numPartitions);
+		Dispatcher dispatcher=new ActiveClusterDispatcher(nodeName, clusterName, clusterUri, 5000L);
+		ClusteredManager manager=new ClusteredManager(sessionPool, attributesFactory, valuePool, wrapperFactory, idFactory, memory, memory.getMap(), new DummyRouter(), true, streamer, true, replicaterfactory, location, proxy, dispatcher, partitionManager, collapser);
+//		manager.setSessionListeners(new HttpSessionListener[]{});
+		//manager.setAttributelisteners(new HttpSessionAttributeListener[]{});
+		manager.init(new DummyManagerConfig());
+		
+		manager.start();
+		//mevicter.stop(); // we'll run it by hand...
+		//devicter.stop();
+		
+		_log.info("CREATING SESSION");
+		AbstractReplicableSession session=(AbstractReplicableSession)manager.create();
+		String foo="bar";
+		session.setAttribute("foo", foo);
+		String name=session.getId();
+		assertTrue(mmap.size()==1);
+		assertTrue(dmap.size()==0);
+		
+		_log.info("TOUCHING SESSION");
+		long lat=session.getLastAccessedTime();
+		memory.contextualise(new WebInvocationContext(null, null, new FilterChain() { public void doFilter(ServletRequest req, ServletResponse res){_log.info("running request");} }), name, null, null, false);
+		assert(lat!=session.getLastAccessedTime());
+		session=(AbstractReplicableSession)mmap.get(name);
+		assertTrue(mmap.size()==1);
+		assertTrue(dmap.size()==0);
+		
+		_log.info("DEMOTING SESSION to short-term SPOOL");
+		mevicter.evict();
+		assertTrue(mmap.size()==0);
+		assertTrue(dmap.size()==1);
+		
+//		_log.info("DEMOTING SESSION to long-term STORE");
+//		manager.stop();
+//		assertTrue(mmap.size()==0);
+//		assertTrue(dmap.size()==0);
+//		
+//		_log.info("PROMOTING SESSION to short-term SPOOL");
+//		manager.start();
+//		assertTrue(mmap.size()==0);
+//		assertTrue(dmap.size()==1);
+//		
+		_log.info("PROMOTING SESSION to Memory");
+		memory.contextualise(new WebInvocationContext(null, null, new FilterChain() { public void doFilter(ServletRequest req, ServletResponse res){_log.info("running request");} }), name, null, null, false);
+		session=(AbstractReplicableSession)mmap.get(name);
+		assertTrue(session.getAttribute("foo")!=foo);
+		assertTrue(session.getAttribute("foo").equals(foo));
+		assertTrue(mmap.size()==1);
+		assertTrue(dmap.size()==0);
+		
+		_log.info("DESTROYING SESSION");
+		manager.destroy(session);
+		assertTrue(mmap.size()==0);
+		assertTrue(dmap.size()==0);
+		
+		manager.stop();
+		
+		dir.delete();
+	}
+	
+}

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/test/TestSessionIdFactory.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/test/TestSessionIdFactory.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/test/TestSessionIdFactory.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/test/TestSessionIdFactory.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,49 @@
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.codehaus.wadi.test;
+
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.codehaus.wadi.SessionIdFactory;
+import org.codehaus.wadi.impl.TomcatSessionIdFactory;
+
+import junit.framework.TestCase;
+
+public class TestSessionIdFactory extends TestCase {
+
+    public TestSessionIdFactory(String name) {
+        super(name);
+    }
+
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+  public void testIdFactory() throws Exception {
+      SessionIdFactory factory=new TomcatSessionIdFactory();
+      Set ids=new TreeSet();
+      int numIds=100000;
+      for (int i=0; i<numIds; i++)
+          ids.add(factory.create());
+      assertTrue(ids.size()==numIds);
+  }
+}

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/test/TestSimpleCluster.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/test/TestSimpleCluster.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/test/TestSimpleCluster.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/test/TestSimpleCluster.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,76 @@
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.codehaus.wadi.test;
+
+import javax.jms.Destination;
+import javax.jms.ObjectMessage;
+import junit.framework.TestCase;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.activecluster.Cluster;
+import org.activecluster.impl.DefaultClusterFactory;
+import org.activemq.ActiveMQConnectionFactory;
+
+/**
+ * @author <a href="mailto:jules@coredevelopers.net">Jules Gosnell</a>
+ * @version $Revision: 1.3 $
+ */
+public class
+  TestSimpleCluster
+  extends TestCase
+{
+  protected Log _log=LogFactory.getLog(TestSimpleCluster.class);
+
+  public TestSimpleCluster(String name)
+  {
+    super(name);
+  }
+
+  public void
+    testSendToSelf()
+    throws Exception
+  {
+    ActiveMQConnectionFactory conFact =new ActiveMQConnectionFactory("vm://localhost");// "multicast://224.1.2.3:5123"
+    DefaultClusterFactory clusFact    =new DefaultClusterFactory(conFact);
+    Cluster node                      =clusFact.createCluster("ORG.CODEHAUS.WADI.TEST.CLUSTER");
+    Destination thisNode              =node.getLocalNode().getDestination();
+    Destination thisCluster           =node.getDestination();
+
+    if (_log.isInfoEnabled()) {
+        _log.info("Node:    " + thisNode);
+        _log.info("Cluster: " + thisCluster);
+    }
+
+
+    // attach listeners here...
+
+    node.start();
+
+      if (_log.isInfoEnabled()) _log.info("started node: " + thisNode);
+
+    ObjectMessage om=node.createObjectMessage();
+    om.setObject("payload");
+    node.send(thisNode, om);
+
+    // wait for messages here...
+
+    node.stop();
+
+    _log.info("request/response to self OK");
+  }
+}

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/test/activecluster/TestCluster.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/test/activecluster/TestCluster.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/test/activecluster/TestCluster.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/test/activecluster/TestCluster.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,329 @@
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.codehaus.wadi.test.activecluster;
+
+import java.net.InetSocketAddress;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.jms.ConnectionFactory;
+import javax.jms.JMSException;
+import javax.servlet.ServletContext;
+import javax.sql.DataSource;
+
+import junit.framework.TestCase;
+
+import org.activecluster.ClusterException;
+import org.activecluster.ClusterFactory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.axiondb.jdbc.AxionDataSource;
+import org.codehaus.wadi.AttributesFactory;
+import org.codehaus.wadi.Collapser;
+import org.codehaus.wadi.ContextPool;
+import org.codehaus.wadi.Contextualiser;
+import org.codehaus.wadi.Emoter;
+import org.codehaus.wadi.Evicter;
+import org.codehaus.wadi.Immoter;
+import org.codehaus.wadi.InvocationProxy;
+import org.codehaus.wadi.ManagerConfig;
+import org.codehaus.wadi.Motable;
+import org.codehaus.wadi.ProxiedLocation;
+import org.codehaus.wadi.Relocater;
+import org.codehaus.wadi.Router;
+import org.codehaus.wadi.SessionIdFactory;
+import org.codehaus.wadi.SessionPool;
+import org.codehaus.wadi.SessionWrapperFactory;
+import org.codehaus.wadi.Streamer;
+import org.codehaus.wadi.ValuePool;
+import org.codehaus.wadi.gridstate.Dispatcher;
+import org.codehaus.wadi.gridstate.ExtendedCluster;
+import org.codehaus.wadi.gridstate.activecluster.ActiveClusterDispatcher;
+import org.codehaus.wadi.gridstate.activecluster.CustomClusterFactory;
+import org.codehaus.wadi.gridstate.activecluster.RestartableClusterFactory;
+import org.codehaus.wadi.gridstate.impl.DummyPartitionManager;
+import org.codehaus.wadi.http.HTTPProxiedLocation;
+import org.codehaus.wadi.impl.ClusterContextualiser;
+import org.codehaus.wadi.impl.DatabaseStore;
+import org.codehaus.wadi.impl.DistributableAttributesFactory;
+import org.codehaus.wadi.impl.ClusteredManager;
+import org.codehaus.wadi.impl.DistributableSessionFactory;
+import org.codehaus.wadi.impl.DistributableValueFactory;
+import org.codehaus.wadi.impl.DummyContextualiser;
+import org.codehaus.wadi.impl.DummyEvicter;
+import org.codehaus.wadi.impl.DummyRelocater;
+import org.codehaus.wadi.impl.DummyReplicaterFactory;
+import org.codehaus.wadi.impl.DummyRouter;
+import org.codehaus.wadi.impl.DummyStatefulHttpServletRequestWrapperPool;
+import org.codehaus.wadi.impl.HashingCollapser;
+import org.codehaus.wadi.impl.MemoryContextualiser;
+import org.codehaus.wadi.impl.SessionToContextPoolAdapter;
+import org.codehaus.wadi.impl.SharedStoreContextualiser;
+import org.codehaus.wadi.impl.SimpleSessionPool;
+import org.codehaus.wadi.impl.SimpleStreamer;
+import org.codehaus.wadi.impl.SimpleValuePool;
+import org.codehaus.wadi.impl.StandardHttpProxy;
+import org.codehaus.wadi.impl.StandardManager;
+import org.codehaus.wadi.impl.StandardSessionWrapperFactory;
+import org.codehaus.wadi.impl.TomcatSessionIdFactory;
+import org.codehaus.wadi.impl.Utils;
+import org.codehaus.wadi.test.EtherEmoter;
+
+/**
+ * Test the shutdown of a Contextualiser stack as live sessions are distributed to other nodes in the cluster
+ *
+ * @author <a href="mailto:jules@coredevelopers.net">Jules Gosnell</a>
+ * @version $Revision: 1.6 $
+ */
+
+public class TestCluster extends TestCase {
+	protected Log _log = LogFactory.getLog(getClass());
+	
+	protected final Streamer _streamer=new SimpleStreamer();
+	protected final Contextualiser _dummyContextualiser=new DummyContextualiser();
+	protected final Collapser _collapser=new HashingCollapser(10, 2000);
+	protected final SessionWrapperFactory _sessionWrapperFactory=new StandardSessionWrapperFactory();
+	protected final SessionIdFactory _sessionIdFactory=new TomcatSessionIdFactory();
+	protected final boolean _accessOnLoad=true;
+	protected final Router _router=new DummyRouter();
+	
+	
+	class MyNode {
+		
+		protected final String _clusterUri=Utils.getClusterUri();
+		protected final String _clusterName;
+		protected final String _nodeName;
+		protected final Dispatcher _dispatcher;
+		protected final Relocater _relocater;
+		protected final Map _cmap=new HashMap();
+		protected final Map _mmap=new HashMap();
+		protected final Evicter _evicter=new DummyEvicter();
+		protected final MemoryContextualiser _top;
+		protected final ClusterContextualiser _middle;
+		protected final SharedStoreContextualiser _bottom;
+		protected final SessionPool _distributableSessionPool=new SimpleSessionPool(new DistributableSessionFactory());
+		protected final ContextPool _distributableContextPool=new SessionToContextPoolAdapter(_distributableSessionPool);
+		protected final AttributesFactory _distributableAttributesFactory=new DistributableAttributesFactory();
+		protected final ValuePool _distributableValuePool=new SimpleValuePool(new DistributableValueFactory());
+		protected final ClusteredManager _manager;
+		
+		public MyNode(String nodeName, ClusterFactory factory, String clusterName, DatabaseStore store) throws JMSException, ClusterException {
+			_bottom=new SharedStoreContextualiser(_dummyContextualiser, _collapser, false, store);
+			_clusterName=clusterName;
+			_nodeName=nodeName;
+			_dispatcher=new ActiveClusterDispatcher(_nodeName, _clusterName, _clusterUri, 5000L);
+			ProxiedLocation proxiedLocation= new HTTPProxiedLocation(new InetSocketAddress("localhost", 8080));
+			InvocationProxy proxy=new StandardHttpProxy("jsessionid");
+			//_relocater=new SwitchableRelocationStrategy();
+			_relocater=new DummyRelocater();
+			_middle=new ClusterContextualiser(_bottom, _collapser, _relocater);
+			_top=new MemoryContextualiser(_middle, _evicter, _mmap, _streamer, _distributableContextPool, new DummyStatefulHttpServletRequestWrapperPool());
+			_manager=new ClusteredManager(_distributableSessionPool, _distributableAttributesFactory, _distributableValuePool, _sessionWrapperFactory, _sessionIdFactory, _top, _mmap, _router, true, _streamer, _accessOnLoad, new DummyReplicaterFactory(), proxiedLocation, proxy, _dispatcher, new DummyPartitionManager(24), _collapser);
+		}
+		
+		protected boolean _running;
+		
+		public synchronized void start() throws Exception {
+			if (!_running) {
+				_manager.init(new ManagerConfig() {
+					
+					public ServletContext getServletContext() {
+						return null;
+					}
+					
+					public void callback(StandardManager manager) {
+						// do nothing - should install Listeners
+					}
+					
+				});
+				_manager.start();
+				_running=true;
+			}
+		}
+		
+		public synchronized void stop() throws Exception {
+			if (_running) {
+				_manager.stop();
+				_manager.destroy();
+				Thread.sleep(6000);
+				_running=false;
+			}
+		}
+		
+		public Map getClusterContextualiserMap() {return _cmap;}
+		public ExtendedCluster getCluster(){return (ExtendedCluster)((ActiveClusterDispatcher)_dispatcher).getCluster();}
+		public ClusterContextualiser getClusterContextualiser() {return _middle;}
+		
+		public Map getMemoryContextualiserMap() {return _mmap;}
+		public MemoryContextualiser getMemoryContextualiser(){return _top;}
+	}
+	
+	protected final ConnectionFactory _connectionFactory=Utils.getConnectionFactory();
+	protected final ClusterFactory _clusterFactory=new RestartableClusterFactory(new CustomClusterFactory(_connectionFactory));
+	protected final String _clusterName="ORG.CODEHAUS.WADI.TEST.CLUSTER";
+	protected final DataSource _ds=new AxionDataSource("jdbc:axiondb:testdb");
+	protected final String _table="WADISESSIONS";
+	protected final DatabaseStore _store=new DatabaseStore("test", _ds, _table, false, false, false);
+	
+	protected boolean _preserveDB;
+	
+	protected MyNode _node0;
+	protected MyNode _node1;
+	protected MyNode _node2;
+	
+	/**
+	 * Constructor for TestCluster.
+	 * @param name
+	 */
+	public TestCluster(String name) throws Exception {
+		super(name);
+		
+		String preserveDB=System.getProperty("preserve.db");
+		if (preserveDB!=null && preserveDB.equals("true"))
+			_preserveDB=true;
+		
+		_log.info("TEST CTOR!");
+	}
+	
+	/*
+	 * @see TestCase#setUp()
+	 */
+	protected void setUp() throws Exception {
+		super.setUp();
+		
+		if (!_preserveDB)
+			_store.init();
+		
+		(_node0=new MyNode("node0", _clusterFactory, _clusterName, _store)).start();
+		(_node1=new MyNode("node1", _clusterFactory, _clusterName, _store)).start();
+		(_node2=new MyNode("node2", _clusterFactory, _clusterName, _store)).start();
+		
+		//_node0.getCluster().waitForClusterToComplete(3, 6000);
+		//_node1.getCluster().waitForClusterToComplete(3, 6000);
+		_node2.getCluster().waitForClusterToComplete(3, 6000);
+	}
+	
+	/*
+	 * @see TestCase#tearDown()
+	 */
+	protected void tearDown() throws Exception {
+		Thread.sleep(1000);
+		
+		super.tearDown();
+		_node2.stop();
+		Thread.sleep(6000);
+		_node1.stop();
+//		Thread.sleep(6000);
+		_node0.stop();
+//		Thread.sleep(10000);
+		
+		if (!_preserveDB)
+			_store.destroy();
+	}
+	
+	public void testEvacuation() throws Exception {
+		Map m0=_node0.getMemoryContextualiserMap();
+		Map m1=_node1.getMemoryContextualiserMap();
+		Map m2=_node2.getMemoryContextualiserMap();
+		
+		// populate node0
+		Contextualiser c0=_node0.getMemoryContextualiser();
+		
+		int numContexts=3;
+		for (int i=0; i<numContexts; i++) {
+			String name="session-"+i;
+			Motable emotable=_node0._distributableSessionPool.take();
+			long time=System.currentTimeMillis();
+			emotable.init(time, time, 30*60, name);
+			Immoter immoter=c0.getDemoter(name, emotable);
+			Emoter emoter=new EtherEmoter();
+			Utils.mote(emoter, immoter, emotable, name);
+		}
+		assertTrue(m0.size()==numContexts); // all sessions are on node0
+		
+		// shutdown node0
+		// sessions should be evacuated to remaining two nodes...
+		if (_log.isInfoEnabled()) _log.info("NODES: " + _node0.getCluster().getNodes().size());
+		_node0.stop();
+		Thread.sleep(6000); // time for other nodes to notice...
+		if (_log.isInfoEnabled()) _log.info("NODES: " + _node1.getCluster().getNodes().size());
+		
+		// where are all the sessions now ?
+		// the sum of nodes 1 and 2 should total n Contexts
+		{
+			int s0=m0.size();
+			int s1=m1.size();
+			int s2=m2.size();
+			if (_log.isInfoEnabled()) _log.info("dispersal - n0:" + s0 + ", n1:" + s1 + ", n2:" + s2);
+			assertTrue(s0==0);
+			assertTrue(s1+s2==numContexts);
+			// TODO - hmmmm...
+			assertTrue(_node0.getClusterContextualiserMap().size()==numContexts); // node0 remembers where everything was sent...
+		}
+		
+		// shutdown node1
+		// sessions should all be evacuated to node2
+		if (_log.isInfoEnabled()) _log.info("NODES: " + _node1.getCluster().getNodes().size());
+		_node1.stop();
+		Thread.sleep(6000); // time for other nodes to notice...
+		if (_log.isInfoEnabled()) _log.info("NODES: " + _node2.getCluster().getNodes().size());
+		{
+			int s0=m0.size();
+			int s1=m1.size();
+			int s2=m2.size();
+			_log.info("dispersal - n0:"+s0+", n1:"+s1+", n2:"+s2);
+			assertTrue(s0==0);
+			assertTrue(s1==0);
+			assertTrue(s2==numContexts);
+			// TODO - hmmmm...
+			//assertTrue(_node0.getClusterContextualiserMap().size()==numContexts); // node0 remembers where everything was sent...
+		}
+		
+		// shutdown node2
+		if (_log.isInfoEnabled()) _log.info("NODES: " + _node2.getCluster().getNodes().size());
+		_node2.stop();
+		Thread.sleep(6000); // time for other nodes to notice...
+		_log.info("NODES: should be 0");
+		{
+			int s0=m0.size();
+			int s1=m1.size();
+			int s2=m2.size();
+			_log.info("dispersal - n0:"+s0+", n1:"+s1+", n2:"+s2);
+			assertTrue(s0==0);
+			assertTrue(s1==0);
+			assertTrue(s2==0);
+			//assertTrue(_node0.getClusterContextualiserMap().size()==numContexts); // node0 remembers where everything was sent...
+		}
+		
+		// TODO - figure out what should happen to location caches, implement and test it.
+		
+		// restart nodes - first one up should reload saved contexts...
+		
+		assertTrue(m0.size()==0);
+		_node0.start();
+		assertTrue(m0.size()==numContexts);
+		
+		assertTrue(m1.size()==0);
+		_node1.start();
+		assertTrue(m1.size()==0);
+		
+		assertTrue(m2.size()==0);
+		_node2.start();
+		assertTrue(m2.size()==0);
+		
+	}
+}

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/test/io/TestByteBufferStreams.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/test/io/TestByteBufferStreams.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/test/io/TestByteBufferStreams.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/test/io/TestByteBufferStreams.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,154 @@
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.codehaus.wadi.test.io;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+import org.codehaus.wadi.sandbox.io.impl.ByteBufferInputStream;
+
+import EDU.oswego.cs.dl.util.concurrent.LinkedQueue;
+import junit.framework.TestCase;
+
+public class TestByteBufferStreams extends TestCase {
+
+    public TestByteBufferStreams(String name) {
+        super(name);
+    }
+
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    public void testByteBufferInputStream() throws Exception {
+        
+        
+        int capacity=256; //8092; // must be divisible by 4 !
+        // create a byte array
+        byte[] bytesIn=new byte[capacity];
+        // initialise it with testable values
+        for (int i=0; i<capacity; i++)
+            bytesIn[i]=(byte)(i%256);
+        
+        // create input and output queues
+        LinkedQueue inputQueue=new LinkedQueue();
+        LinkedQueue outputQueue=new LinkedQueue();
+        // put the queues into the stream
+        ByteBufferInputStream is=new ByteBufferInputStream(inputQueue, outputQueue, 30*1000);
+
+        // try exhausting a single ByteBuffer
+        
+        // allocate a ByteBuffer
+        ByteBuffer buffer=ByteBuffer.allocateDirect(capacity);
+        // copy byte array into ByteBuffer
+        buffer.put(bytesIn);
+        // prepare it for reading
+        buffer.flip();
+        // push the ByteBuffer onto the Stream's input
+        inputQueue.put(buffer);
+
+        // read it all out and check it for validity
+        {
+            byte[] bytesOut=new byte[capacity];
+            int bytesRead=0;
+            while((bytesRead+=is.read(bytesOut))<capacity);
+            assertTrue(bytesRead==capacity);
+            assertTrue(Arrays.equals(bytesIn, bytesOut));
+        }
+        // check the state of the queues...
+        assertTrue(inputQueue.isEmpty()); // no input left
+        assertTrue(outputQueue.take()!=null); // 1 buffer in output
+        assertTrue(outputQueue.isEmpty());
+        
+        // OK - now lets see if rollover works OK...
+        
+        int rolloverCapacity=capacity/4;
+        for (int i=0; i<4; i++) {
+            buffer=ByteBuffer.allocateDirect(rolloverCapacity);
+            buffer.put(bytesIn, i*rolloverCapacity, rolloverCapacity);
+            buffer.flip();
+            inputQueue.put(buffer);
+        }
+        // read it all out and check it for validity
+        {
+            byte[] bytesOut=new byte[capacity];
+            int bytesRead=0;
+            while((bytesRead+=is.read(bytesOut))<capacity);
+            assertTrue(bytesRead==capacity);
+            assertTrue(Arrays.equals(bytesIn, bytesOut));
+        }        
+        assertTrue(inputQueue.isEmpty()); // no input left
+        assertTrue(outputQueue.take()!=null); // 4 buffers in output
+        assertTrue(outputQueue.take()!=null); // 3 buffers in output
+        assertTrue(outputQueue.take()!=null); // 2 buffers in output
+        assertTrue(outputQueue.take()!=null); // 1 buffer in output
+        assertTrue(outputQueue.isEmpty());
+        
+        // test closing a stream...
+
+        buffer=ByteBuffer.allocateDirect(rolloverCapacity);
+        buffer.put(bytesIn, 0, rolloverCapacity);
+        buffer.flip();
+        is.put(buffer);
+        is.commit();
+        
+        // read it all out and check it for validity
+        {
+            byte[] bytesOut=new byte[capacity];
+            int b=0;
+            int bytesRead=0;
+            while((b=is.read(bytesOut))!=-1)
+                bytesRead+=b;
+            assertTrue(bytesRead==rolloverCapacity);
+            for (int i=0; i<rolloverCapacity; i++)
+                assertTrue(bytesIn[i]==bytesOut[i]);
+        }        
+        
+        // check the state of the queues...
+        assertTrue(!inputQueue.isEmpty()); // just end of queue marker left
+        assertTrue(inputQueue.take()!=null);
+        assertTrue(inputQueue.isEmpty()); // no input left
+        assertTrue(outputQueue.take()!=null); // 1 buffer in output
+        assertTrue(outputQueue.isEmpty());
+        
+    }
+    
+//  public void testWrite() throws Exception {
+//  assertTrue(true);
+//  
+//  int size=1024;
+//  byte[] bytes=new byte[size];
+//  for (int i=0; i<size; i++)
+//  bytes[i]=(byte)i;
+//  File file=File.createTempFile("wadi-", ".tst");
+//  FileOutputStream fos=new FileOutputStream(file);
+//  fos.write(bytes);
+//  fos.close();
+//  
+//  _log.info("File: "+file);
+//  
+//  assertTrue(file.length()==size);
+//  FileInputStream fis= new FileInputStream(file);
+//  FileChannel fc=fis.getChannel();
+//  MappedByteBuffer mbb=fc.map(FileChannel.MapMode.READ_ONLY, 0, file.length());
+//  }
+    
+}

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/test/io/TestMotion.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/test/io/TestMotion.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/test/io/TestMotion.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/test/io/TestMotion.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,469 @@
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.codehaus.wadi.test.io;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.net.InetSocketAddress;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.jms.ConnectionFactory;
+import javax.jms.Destination;
+import javax.servlet.FilterChain;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import junit.framework.TestCase;
+
+import org.activecluster.Cluster;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.codehaus.wadi.Collapser;
+import org.codehaus.wadi.ContextPool;
+import org.codehaus.wadi.Contextualiser;
+import org.codehaus.wadi.DistributableSessionConfig;
+import org.codehaus.wadi.Emoter;
+import org.codehaus.wadi.Immoter;
+import org.codehaus.wadi.InvocationProxy;
+import org.codehaus.wadi.Location;
+import org.codehaus.wadi.Motable;
+import org.codehaus.wadi.PoolableInvocationWrapperPool;
+import org.codehaus.wadi.ProxiedLocation;
+import org.codehaus.wadi.RelocaterConfig;
+import org.codehaus.wadi.SessionPool;
+import org.codehaus.wadi.SessionRelocater;
+import org.codehaus.wadi.dindex.impl.DIndex;
+import org.codehaus.wadi.gridstate.Dispatcher;
+import org.codehaus.wadi.gridstate.ExtendedCluster;
+import org.codehaus.wadi.gridstate.activecluster.CustomClusterFactory;
+import org.codehaus.wadi.impl.DistributableSession;
+import org.codehaus.wadi.impl.DistributableSessionFactory;
+import org.codehaus.wadi.impl.DummyContextualiser;
+import org.codehaus.wadi.impl.MemoryContextualiser;
+import org.codehaus.wadi.impl.NeverEvicter;
+import org.codehaus.wadi.impl.SessionToContextPoolAdapter;
+import org.codehaus.wadi.impl.SimpleMotable;
+import org.codehaus.wadi.impl.SimpleSessionPool;
+import org.codehaus.wadi.impl.SimpleStreamer;
+import org.codehaus.wadi.impl.StreamingMigratingRelocater;
+import org.codehaus.wadi.impl.Utils;
+import org.codehaus.wadi.impl.WebInvocationContext;
+import org.codehaus.wadi.sandbox.io.PeerConfig;
+import org.codehaus.wadi.sandbox.io.Pipe;
+import org.codehaus.wadi.sandbox.io.Server;
+import org.codehaus.wadi.sandbox.io.ServerConfig;
+import org.codehaus.wadi.sandbox.io.impl.ClusterServer;
+import org.codehaus.wadi.sandbox.io.impl.Peer;
+import org.codehaus.wadi.sandbox.io.impl.ThreadFactory;
+import org.codehaus.wadi.test.DummyDistributableSessionConfig;
+import org.codehaus.wadi.test.EtherEmoter;
+import org.codehaus.wadi.test.MyDummyHttpServletRequestWrapperPool;
+
+import EDU.oswego.cs.dl.util.concurrent.BoundedBuffer;
+import EDU.oswego.cs.dl.util.concurrent.NullSync;
+import EDU.oswego.cs.dl.util.concurrent.PooledExecutor;
+import EDU.oswego.cs.dl.util.concurrent.Sync;
+import EDU.oswego.cs.dl.util.concurrent.SynchronizedBoolean;
+
+public class TestMotion extends TestCase {
+	
+	protected final Log _log=LogFactory.getLog(getClass());
+	
+	protected final ThreadFactory _threadFactory=new ThreadFactory();
+	
+	interface Location2 {/* empty */}
+	
+	public static class InetSocketAddressLocation implements Location2 {
+		
+		protected final InetSocketAddress _address;
+		
+		public InetSocketAddressLocation(InetSocketAddress address) {
+			_address=address;
+		}
+		
+		public InetSocketAddress getAddress() {return _address;}
+	}
+	
+	public static class DestinationLocation implements Location2 {
+		
+		protected final Destination _destination;
+		
+		public DestinationLocation(Destination destination) {
+			_destination=destination;
+		}
+		
+		public Destination getDestination() {return _destination;}
+	}
+	
+	
+	public static class MyServerConfig implements ServerConfig {
+		
+		protected static ConnectionFactory _cfactory=Utils.getConnectionFactory();
+		protected static CustomClusterFactory _factory=new CustomClusterFactory(_cfactory);
+		
+		protected final Log _log=LogFactory.getLog(getClass());
+		protected final String _nodeName;
+		protected final Contextualiser _contextualiser;
+		
+		protected ExtendedCluster _cluster=null;
+		
+		public MyServerConfig(String nodeName, Contextualiser contextualiser) {
+			_nodeName=nodeName;
+			_contextualiser=contextualiser;
+			try {
+				_cluster=(ExtendedCluster)_factory.createCluster("ORG.CODEHAUS.WADI.TEST.CLUSTER");
+			} catch (Exception e) {
+				_log.error("unexpected problem", e);
+			}
+		}
+		
+		public ExtendedCluster getCluster() {
+			return _cluster;
+		}
+		
+		public Contextualiser getContextualiser() {
+			return _contextualiser;
+		}
+		
+		public String getNodeName() {
+			return _nodeName;
+		}
+		
+	}
+	
+	public static class Node {
+		
+		protected final Map _clients=new HashMap();
+		protected final PooledExecutor _executor;
+		protected final Server _server;
+		
+		protected int _counter=0;
+		
+		public Node(Location2 location, ThreadFactory factory, ServerConfig config) {
+			_executor=new PooledExecutor(new BoundedBuffer(10), 100);
+			_executor.setThreadFactory(factory);
+			_executor.setMinimumPoolSize(3);
+			//_server=new NIOServer(_executor, 5*1000, ((InetSocketAddressLocation)location).getAddress(), 1*1000, 256, 4096, 4096);
+			//_server=new BIOServer(_executor, ((InetSocketAddressLocation)location).getAddress(), 32, 1*1000);
+			_server=new ClusterServer(_executor, 5000, false);
+			_server.init(config);
+		}
+		
+		public void start() throws Exception {
+			_server.start();
+		}
+		
+		public void stop() throws Exception {
+//			synchronized (_clients) {
+//			for (Iterator i=_clients.entrySet().iterator(); i.hasNext(); ) {
+//			Map.Entry e=(Map.Entry)i.next();
+//			//InetSocketAddress key=(InetSocketAddress)e.getKey();
+//			SocketClientConnection val=(SocketClientConnection)e.getValue();
+//			val.close();
+//			i.remove();
+//			}
+//			}
+			_server.stop();
+		}
+		
+		public Pipe getClient(Location2 location) throws IOException {
+//			synchronized (_clients) {
+//			Pipe client=(Pipe)_clients.get(location);
+//			if (client==null) {
+//			client=((ClusterServer)_server).makeClientPipe("foo-"+_counter++, ((DestinationLocation)location).getDestination());
+//			//client=new SocketClientConnection(((InetSocketAddressLocation)location).getAddress(), 5*1000);
+//			//_clients.put(location, client); // don't cache clients..
+//			}
+//			return client;
+//			}
+			return ((ClusterServer)_server).makeClientPipe("foo-"+_counter++, ((DestinationLocation)location).getDestination());
+		}
+	}
+	
+	protected final DistributableSessionFactory _distributableSessionFactory=new DistributableSessionFactory();
+	protected final SessionPool _distributableSessionPool=new SimpleSessionPool(_distributableSessionFactory);
+	protected final PoolableInvocationWrapperPool _requestPool=new MyDummyHttpServletRequestWrapperPool();
+	protected final ContextPool _distributableContextPool=new SessionToContextPoolAdapter(_distributableSessionPool);
+	
+	protected final Location2 _localLocation;
+	protected final Map _localMap=new HashMap();
+	protected final MemoryContextualiser _localContextualiser=new MemoryContextualiser(new DummyContextualiser(), new NeverEvicter(60, true), _localMap, new SimpleStreamer(), _distributableContextPool, _requestPool);
+	protected final ServerConfig _localConfig=new MyServerConfig("local", _localContextualiser);
+	protected final Location2 _remoteLocation;
+	protected final Map _remoteMap=new HashMap();
+	protected final MemoryContextualiser _remoteContextualiser=new MemoryContextualiser(new DummyContextualiser(), new NeverEvicter(60, true), _remoteMap, new SimpleStreamer(), _distributableContextPool, _requestPool);
+	protected final ServerConfig _remoteConfig=new MyServerConfig("remote", _remoteContextualiser);
+	
+	public TestMotion(String name) throws Exception {
+		super(name);
+		_distributableSessionPool.init(new DummyDistributableSessionConfig());
+		_localLocation=new DestinationLocation(_localConfig.getCluster().getLocalNode().getDestination());
+		_remoteLocation=new DestinationLocation(_remoteConfig.getCluster().getLocalNode().getDestination());
+		//_local=new InetSocketAddressLocation(new InetSocketAddress(InetAddress.getLocalHost(), 8888));
+		//_remote=new InetSocketAddressLocation(new InetSocketAddress(InetAddress.getLocalHost(), 8889));
+	}
+	
+	protected Node _us;
+	protected Node _them;
+	
+	protected void setUp() throws Exception {
+		super.setUp();
+		(_us=new Node(_localLocation, _threadFactory, _localConfig)).start();
+		(_them=new Node(_remoteLocation, _threadFactory, _remoteConfig)).start();
+		_localConfig.getCluster().start();
+		_remoteConfig.getCluster().start();
+	}
+	
+	protected void tearDown() throws Exception {
+		super.tearDown();
+		_them.stop();
+		_us.stop();
+		_remoteConfig.getCluster().stop();
+		_localConfig.getCluster().stop();
+		_localMap.clear();
+		_remoteMap.clear();
+	}
+	
+	public static class SingleRoundTripServerPeer extends Peer {
+		
+		protected static final Log _log=LogFactory.getLog(SingleRoundTripServerPeer.class);
+		
+		public boolean run(PeerConfig config) throws IOException {
+			if (_log.isInfoEnabled()) {
+				_log.info("server - starting");
+				_log.info("server - creating output stream");
+			}
+			
+			ObjectOutputStream oos=config.getObjectOutputStream();
+			_log.info("server - writing response");
+			oos.writeBoolean(true); // ack
+			_log.info("server - flushing response");
+			oos.flush();
+			_log.info("server - finished");
+			//config.close();
+			return true;
+		}
+	}
+	
+	public static class SingleRoundTripClientPeer extends Peer {
+		
+		protected static final Log _log=LogFactory.getLog(SingleRoundTripClientPeer.class);
+		
+		public boolean run(PeerConfig config) throws IOException {
+			if (_log.isInfoEnabled()) {
+				_log.info("client - starting");
+				_log.info("client - creating output stream");
+			}
+			
+			ObjectOutputStream oos=config.getObjectOutputStream();
+			_log.info("client - writing server");
+			oos.writeObject(new SingleRoundTripServerPeer());
+			_log.info("client - flushing server");
+			oos.flush();
+			_log.info("client - creating input stream");
+			ObjectInputStream ois=config.getObjectInputStream();
+			_log.info("client - reading response");
+			boolean result=ois.readBoolean();
+			if (_log.isInfoEnabled()) _log.info("client - finished: " + result);
+			assertTrue(result);
+			//config.close();
+			return result;
+		}
+	}
+	
+	public void testRoundTripping() throws Exception {
+		
+		_log.info("START");
+		Pipe us2them=_us.getClient(_remoteLocation);
+		try {
+			_log.info("us -> them (1st trip)");
+			us2them.run(new SingleRoundTripClientPeer());
+			_log.info("us -> them (2nd trip)");
+			us2them.run(new SingleRoundTripClientPeer());
+		} finally {
+			us2them.close();
+		}
+		_log.info("FINISH");
+		_log.info("START");
+		
+		Pipe them2us=_them.getClient(_localLocation);
+		try {
+			_log.info("them -> us (1st trip)");
+			them2us.run(new SingleRoundTripClientPeer());
+			_log.info("them -> us (2nd trip)");
+			them2us.run(new SingleRoundTripClientPeer());
+		} finally {
+			them2us.close();
+		}
+		_log.info("FINISH");
+	}
+	
+	public static class EmotionServerPeer extends Peer implements Serializable {
+		
+		protected static final Log _log=LogFactory.getLog(EmotionServerPeer.class);
+		
+		public boolean run(PeerConfig config) throws IOException, ClassNotFoundException {
+			long startTime=System.currentTimeMillis();
+			ObjectInputStream ois=config.getObjectInputStream();
+			String nodeName=(String)ois.readObject();
+			String name=(String)ois.readObject();
+			Motable emotable=(Motable)ois.readObject();
+			Contextualiser contextualiser=config.getContextualiser();
+			Immoter immoter=contextualiser.getDemoter(name, emotable);
+			Motable immotable=immoter.nextMotable(name, emotable);
+			ObjectOutputStream oos=config.getObjectOutputStream();
+			boolean ok=immoter.prepare(name, emotable, immotable);
+			if (ok) immoter.commit(name, immotable);
+			oos.writeObject(config.getNodeId());
+			oos.writeBoolean(ok);
+			oos.flush();
+			long elapsedTime=System.currentTimeMillis()-startTime;
+			if (_log.isDebugEnabled())_log.debug("motion"+(ok?"":" failed")+": "+name+" : cluster ["+nodeName+"] -> "+immoter.getInfo()+" ("+elapsedTime+" millis)");
+			return true;
+		}
+	}
+	
+	public static class EmotionClientPeer extends Peer {
+		
+		protected static final Log _log=LogFactory.getLog(EmotionClientPeer.class);
+		
+		protected final String _name;
+		protected final Emoter _emoter;
+		protected final Motable _emotable;
+		
+		public EmotionClientPeer(String name, Emoter emoter, Motable emotable) {
+			_name=name;
+			_emoter=emoter;
+			_emotable=emotable;
+		}
+		
+		public boolean run(PeerConfig config) throws Exception {
+			long startTime=System.currentTimeMillis();
+			Motable motable=new SimpleMotable();
+			motable.copy(_emotable); // how can we avoid this copy...? write straight onto the stream...
+			boolean ok=_emoter.prepare(_name, _emotable, null); // FIXME - this should not be a null
+			if (!ok) return ok;
+			ok=false;
+			ObjectOutputStream oos=null;
+			ObjectInputStream ois=null;
+			String nodeName="<unknown>";
+			try {
+				oos=config.getObjectOutputStream();
+				oos.writeObject(new EmotionServerPeer()); // could be cached...
+				oos.writeObject(config.getNodeId());
+				oos.writeObject(_name);
+				oos.writeObject(motable);
+				oos.flush();
+				// server tries to prepare and commit...
+				// returns success or failure
+				ois=config.getObjectInputStream();
+				nodeName=(String)ois.readObject();
+				ok=ois.readBoolean();
+			} catch (Exception e) {
+				_log.error("unexpected problem", e);
+			} finally {
+				if (ok) {
+					_emoter.commit(_name, _emotable);
+				} else {
+					_emoter.rollback(_name, _emotable);
+				}
+			}
+			long elapsedTime=System.currentTimeMillis()-startTime;
+			if (_log.isDebugEnabled())_log.debug("motion"+(ok?"":" failed")+": "+_name+" : "+_emoter.getInfo()+" -> cluster ["+nodeName+"] ("+elapsedTime+" millis)");
+			return ok;
+		}
+	}
+	
+	public static class DummyRelocaterConfig implements RelocaterConfig {
+		
+		public Collapser getCollapser() {return null;}
+		public Dispatcher getDispatcher() {return null;}
+		public Location getLocation() {return null;}
+		public Map getMap() {return null;}
+		public Cluster getCluster() {return null;}
+		public Contextualiser getContextualiser() {return null;}
+		public String getNodeName() {return null;}
+		public SynchronizedBoolean getShuttingDown() {return null;}
+		public InvocationProxy getInvocationProxy() {return null;}
+		public ProxiedLocation getProxiedLocation() {return null;}
+		public DIndex getDIndex() {return null;}
+		public void notifySessionRelocation(String name) {};
+		
+	}
+	
+	public void testEmotion() throws Exception {
+		
+		Emoter emoter=new EtherEmoter();
+		DistributableSessionConfig config=new DummyDistributableSessionConfig();
+		DistributableSessionFactory factory=new DistributableSessionFactory();
+		DistributableSession s0=(DistributableSession)factory.create(config);
+		long time=System.currentTimeMillis();
+		String name0="foo";
+		s0.init(time, time, 30*60, name0);
+		DistributableSession s1=(DistributableSession)factory.create(config);
+		String name1="bar";
+		s1.init(time, time, 30*60, name1);
+		
+		_log.info("START");
+		Pipe us2them=_us.getClient(_remoteLocation);
+		try {
+			_log.info("us -> them (1st trip)");
+			us2them.run(new EmotionClientPeer(s0.getName(), emoter, s0));
+			assertTrue(_localMap.size()==0);
+			assertTrue(_remoteMap.size()==1);
+			assertTrue(_remoteMap.containsKey(name0));
+			_log.info("us -> them (2nd trip)");
+			us2them.run(new EmotionClientPeer(s1.getName(), emoter, s1));
+			assertTrue(_localMap.size()==0);
+			assertTrue(_remoteMap.size()==2);
+			assertTrue(_remoteMap.containsKey(name1));
+		} finally {
+			us2them.close();
+		}
+		_log.info("FINISH");
+		
+		SessionRelocater relocater=new StreamingMigratingRelocater();
+		relocater.init(new DummyRelocaterConfig());
+		Sync motionLock=new NullSync();
+		//Map locationMap=new HashMap();
+		HttpServletRequest req=null;
+		HttpServletResponse res=null;
+		FilterChain chain=null;
+		Immoter immoter=_localContextualiser.getImmoter();
+		
+		boolean ok=false;
+		assertTrue(_localMap.size()==0);
+		assertTrue(_remoteMap.size()==2);
+		ok=relocater.relocate(new WebInvocationContext(req, res, chain), name0, immoter, motionLock);
+		assertTrue(ok);
+		assertTrue(_localMap.size()==1);
+		assertTrue(_remoteMap.size()==1);
+		assertTrue(_localMap.containsKey(name0));
+		assertTrue(!_remoteMap.containsKey(name0));
+		ok=relocater.relocate(new WebInvocationContext(req, res, chain), name1, immoter, motionLock);
+		assertTrue(ok);
+		assertTrue(_localMap.size()==2);
+		assertTrue(_remoteMap.size()==0);
+		assertTrue(_localMap.containsKey(name1));
+		assertTrue(!_remoteMap.containsKey(name1));
+	}
+	
+}

Added: incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/test/io/TestServers.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/test/io/TestServers.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/test/io/TestServers.java (added)
+++ incubator/wadi/trunk/modules/core/src/test/java/org/codehaus/wadi/test/io/TestServers.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,314 @@
+/**
+ *
+ * Copyright 2003-2005 Core Developers Network Ltd.
+ *
+ *  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.codehaus.wadi.test.io;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+
+import javax.jms.Destination;
+
+import org.activecluster.ClusterFactory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.codehaus.wadi.Contextualiser;
+import org.codehaus.wadi.gridstate.ExtendedCluster;
+import org.codehaus.wadi.gridstate.activecluster.CustomClusterFactory;
+import org.codehaus.wadi.gridstate.activecluster.RestartableClusterFactory;
+import org.codehaus.wadi.impl.Utils;
+import org.codehaus.wadi.sandbox.io.PeerConfig;
+import org.codehaus.wadi.sandbox.io.Pipe;
+import org.codehaus.wadi.sandbox.io.ServerConfig;
+import org.codehaus.wadi.sandbox.io.impl.BIOServer;
+import org.codehaus.wadi.sandbox.io.impl.ClusterServer;
+import org.codehaus.wadi.sandbox.io.impl.NIOServer;
+import org.codehaus.wadi.sandbox.io.impl.Peer;
+import org.codehaus.wadi.sandbox.io.impl.SocketClientPipe;
+import org.codehaus.wadi.sandbox.io.impl.ThreadFactory;
+
+import EDU.oswego.cs.dl.util.concurrent.BoundedBuffer;
+import EDU.oswego.cs.dl.util.concurrent.LinkedQueue;
+import EDU.oswego.cs.dl.util.concurrent.PooledExecutor;
+
+import junit.framework.TestCase;
+
+public class TestServers extends TestCase {
+
+    protected Log _log = LogFactory.getLog(getClass());
+
+    public TestServers(String name) {
+        super(name);
+    }
+
+    interface PipeFactory { Pipe create() throws IOException; }
+
+    protected InetSocketAddress _bioAddress;
+    protected BIOServer _bioServer;
+    protected PipeFactory _bioPipeFactory=new PipeFactory(){ public Pipe create() throws IOException {return new SocketClientPipe(_bioAddress, 5*1000);}};
+    protected InetSocketAddress _nioAddress;
+    protected NIOServer _nioServer;
+    protected PipeFactory _nioPipeFactory=new PipeFactory() {public Pipe create() throws IOException {return new SocketClientPipe(_nioAddress, 5*1000);}};
+    protected javax.jms.ConnectionFactory _connectionFactory=Utils.getConnectionFactory();
+    protected ClusterFactory _clusterFactory=new RestartableClusterFactory(new CustomClusterFactory(_connectionFactory));
+    protected String _clusterName="ORG.CODEHAUS.WADI.TEST.CLUSTER";
+    protected ExtendedCluster _cluster;
+    protected ClusterServer _clusterServer;
+    protected PipeFactory _clusterPipeFactory;
+
+    protected final int _count=10000;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        // an unbounded queue, serviced by 5 threads
+        PooledExecutor pool;
+        pool=new PooledExecutor(new LinkedQueue());
+        pool.setKeepAliveTime(-1); // live forever
+        pool.createThreads(5);
+
+        ThreadFactory threadFactory=new ThreadFactory();
+
+        _bioAddress=new InetSocketAddress(InetAddress.getLocalHost(), 8888);
+        PooledExecutor executor;
+        executor=new PooledExecutor(new BoundedBuffer(10), 100);
+        executor.setThreadFactory(threadFactory);
+        executor.setMinimumPoolSize(3);
+        _bioServer=new BIOServer(executor, 5*1000, _bioAddress, 1*1000, 16);
+        _bioServer.start();
+
+        _nioAddress=new InetSocketAddress(InetAddress.getLocalHost(), 8889);
+        executor=new PooledExecutor(new BoundedBuffer(10), 100);
+        executor.setThreadFactory(threadFactory);
+        executor.setMinimumPoolSize(3);
+        _nioServer=new NIOServer(executor, 5*1000, _nioAddress, 1*1000, 1024, 256, 256);
+        _nioServer.start();
+
+        _cluster=(ExtendedCluster)_clusterFactory.createCluster(_clusterName);
+        executor=new PooledExecutor(new BoundedBuffer(10), 100);
+        executor.setThreadFactory(threadFactory);
+        executor.setMinimumPoolSize(3);
+        _clusterServer=new ClusterServer(executor, 5*1000, false);
+        _clusterServer.init(new ServerConfig() {
+            public ExtendedCluster getCluster() {return _cluster;}
+            public Contextualiser getContextualiser() {return null;}
+            public String getNodeName() {return null;}
+        });
+        _clusterServer.start();
+        _cluster.start();
+
+        _clusterPipeFactory=new PipeFactory()  {
+            protected int _count=0;
+            public Pipe create() throws IOException {
+                String name="foo-"+(_count++);
+                Destination target=_cluster.getLocalNode().getDestination();
+                return _clusterServer.makeClientPipe(name, target);
+            }
+        };
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        _nioServer.stop();
+        _bioServer.stop();
+        _clusterServer.stop();
+        _cluster.stop();
+    }
+
+    public static class SingleRoundTripServerPeer extends Peer {
+
+        public boolean run(PeerConfig config) throws IOException {
+            //_log.info("server - starting");
+            //_log.info("server - creating output stream");
+            ObjectOutputStream oos=config.getObjectOutputStream();
+            //_log.info("server - writing response");
+            oos.writeBoolean(true); // ack
+            //_log.info("server - flushing response");
+            oos.flush();
+            //_log.info("server - finished");
+            return true;
+        }
+    }
+
+    public static class SingleRoundTripClientPeer extends Peer {
+
+        public boolean run(PeerConfig config) throws IOException {
+            //_log.info("client - starting");
+            //_log.info("client - creating output stream");
+            ObjectOutputStream oos=config.getObjectOutputStream();
+            //_log.info("client - writing object");
+            oos.writeObject(new SingleRoundTripServerPeer());
+            //_log.info("client - flushing object");
+            oos.flush();
+            //_log.info("client - creating input stream");
+            ObjectInputStream ois=config.getObjectInputStream();
+            //_log.info("client - reading response");
+            boolean result=ois.readBoolean();
+            //_log.info("client - finished: "+result);
+            assertTrue(result);
+            return result;
+        }
+    }
+
+    // NEED CONCURRENT TEST
+
+    public void testSingleRoundTrip() throws Exception {
+        //testSingleRoundTrip("BIO", _bioPipeFactory);
+        //testSingleRoundTrip("NIO", _nioPipeFactory);
+        testSingleRoundTrip("Cluster", _clusterPipeFactory);
+    }
+
+    public void testSingleRoundTrip(String info, PipeFactory factory) throws Exception {
+        long start=System.currentTimeMillis();
+        for (int i=0; i<_count; i++) {
+            Pipe pipe=factory.create();
+            Peer peer=new SingleRoundTripClientPeer();
+            pipe.run(peer);
+            pipe.close();
+            //_log.info("count: "+i);
+        }
+        long elapsed=System.currentTimeMillis()-start;
+        if (_log.isInfoEnabled()) _log.info(info + " rate=" + ( _count * 1000 / elapsed ) + " round-trips/second");
+    }
+
+    public void testMultipleRoundTrip() throws Exception {
+        //testMultipleRoundTrip("BIO", _bioPipeFactory);
+        //testMultipleRoundTrip("NIO", _nioPipeFactory);
+        testMultipleRoundTrip("Cluster", _clusterPipeFactory);
+    }
+
+    public void testMultipleRoundTrip(String info, PipeFactory factory) throws Exception {
+        long start=System.currentTimeMillis();
+        Pipe pipe=factory.create();
+        Peer peer=new SingleRoundTripClientPeer();
+        for (int i=0; i<_count; i++) {
+            pipe.run(peer);
+            //_log.info("count: "+i);
+        }
+        pipe.close();
+        long elapsed=System.currentTimeMillis()-start;
+        if (_log.isInfoEnabled()) _log.info(info + " rate=" + ( _count * 1000 / ( elapsed + 1 ) ) + " round-trips/second");
+    }
+
+//    public static class MixedContentServerPeer extends Peer {
+//
+//        protected static final Log _log=LogFactory.getLog(MixedContentServerPeer.class);
+//
+//        public void process(Socket socket, ObjectInputStream ois, ObjectOutputStream oos) {
+//            try {
+//                int capacity=ois.readInt();
+//                ByteBuffer buffer=ByteBuffer.allocateDirect(capacity);
+//                socket.getChannel().read(buffer);
+//                oos.writeBoolean(true); // ack
+//            } catch (IOException e) {
+//                _log.error(e);
+//            }
+//        }
+//    }
+
+//    public static class MixedContentClientPeer extends Peer {
+//
+//        protected static final Log _log=LogFactory.getLog(MixedContentClientPeer.class);
+//        protected final ByteBuffer _buffer;
+//
+//        public MixedContentClientPeer(InetSocketAddress address, ByteBuffer buffer, boolean inputThenOutput) throws IOException {
+//            super(address, inputThenOutput);
+//            _buffer=buffer;
+//        }
+//
+//        public void process(Socket socket, ObjectInputStream ois, ObjectOutputStream oos) {
+//            try {
+//                oos.writeObject(new MixedContentServerPeer());
+//                oos.writeInt(_buffer.capacity());
+//                oos.flush();
+//                SocketChannel channel=socket.getChannel();
+//
+//                // AHA ! - you can't get the Channel for a preexisting Socket :-(
+//                // back to the drawing board...
+//
+//                channel.write(_buffer);
+//                oos.flush();
+//                assertTrue(ois.readBoolean());
+//            } catch (IOException e) {
+//                _log.error(e);
+//            }
+//        }
+//    }
+
+//    public void testMixedContent() throws Exception {
+//        long start=System.currentTimeMillis();
+//        int capacity=4096;
+//        ByteBuffer buffer=ByteBuffer.allocateDirect(capacity);
+//        for (int i=0; i<1; i++) {
+//            Peer peer=new MixedContentClientPeer(_address, buffer);
+//            peer.run();
+//        }
+//        long elapsed=System.currentTimeMillis()-start;
+//        _log.info("rate="+(_count*1000/elapsed)+" round-trips/second");
+//    }
+
+//    public static class PeerMoter extends Peer implements Moter {
+//
+//        public PeerMoter(Socket socket) throws IOException {
+//            super(socket);
+//        }
+//
+//        public boolean prepare(String name, Motable emotable, Motable immotable) {
+//            // lock e
+//            return true;
+//        }
+//
+//        public void commit(String name, Motable motable) {
+//
+//        }
+//
+//        public void rollback(String name, Motable motable) {
+//
+//        }
+//
+//        public String getInfo() {
+//            return "peer";
+//        }
+//
+//    }
+//
+//    public static class PeerEmoter extends PeerMoter implements Emoter{
+//    }
+//
+//    public static class PeerImmoter extends PeerMoter implements Immoter {
+//
+//        Motable nextMotable(String id, Motable emotable);
+//
+//        boolean contextualise(HttpServletRequest hreq, HttpServletResponse hres, FilterChain chain, String id, Motable immotable, Sync motionLock) throws IOException, ServletException;
+//
+//    }
+
+//    public void testMigration() throws Exception {
+//
+//        Emoter emoter=null;
+//        Immoter immoter=null;
+//
+//        Motable emotable=new SimpleMotable();
+//        String name="foo";
+//        long time=System.currentTimeMillis();
+//        emotable.init(time, time, 30*60, name);
+//
+//        Utils.mote(emoter, immoter, emotable, name);
+//    }
+
+}

Added: incubator/wadi/trunk/modules/itest/.cvsignore
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/itest/.cvsignore?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/itest/.cvsignore (added)
+++ incubator/wadi/trunk/modules/itest/.cvsignore Wed Dec 14 15:32:56 2005
@@ -0,0 +1,5 @@
+target
+.classpath
+.wtpmodules
+.project
+.settings

Added: incubator/wadi/trunk/modules/itest/pom.xml
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/itest/pom.xml?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/itest/pom.xml (added)
+++ incubator/wadi/trunk/modules/itest/pom.xml Wed Dec 14 15:32:56 2005
@@ -0,0 +1,108 @@
+<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">
+    <parent>
+        <groupId>wadi</groupId>
+        <artifactId>wadi</artifactId>
+        <version>2.0M1</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>wadi</groupId>
+    <artifactId>wadi-itest</artifactId>
+    <packaging>jar</packaging>
+    <name>WADI :: Integration Test Module</name>
+    <url>http://wadi.codehaus.org</url>
+    <scm>
+        <connection>scm:cvs:pserver:anoncvs@cvs.wadi.codehaus.org:/home/projects/wadi/scm:wadi/modules/itest</connection>
+        <developerConnection>scm:cvs:ext:${maven.username}@cvs.wadi.codehaus.org/home/projects/wadi/scm:wadi/modules/itest</developerConnection>
+        <url>http://cvs.wadi.codehaus.org/viewrep/wadi/wadi/modules/itest</url>
+    </scm>
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>3.8.1</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.cargo</groupId>
+            <artifactId>cargo-core-api-generic</artifactId>
+            <version>0.7-SNAPSHOT</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.cargo</groupId>
+            <artifactId>cargo-core-container-tomcat</artifactId>
+            <version>0.7-SNAPSHOT</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>commons-httpclient</groupId>
+            <artifactId>commons-httpclient</artifactId>
+            <version>2.0.2</version>
+            <scope>test</scope>
+        </dependency>
+	<dependency>
+	  <groupId>wadi</groupId>
+          <artifactId>wadi-test-webapp</artifactId>
+          <version>2.0M1</version>
+	  <type>war</type>
+	</dependency>
+    </dependencies>
+    <build>
+      <plugins>
+	<plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-surefire-plugin</artifactId>
+	  <configuration>
+	    <systemProperties>
+	      <property>
+		<name>wadi.version</name>
+		<value>${version}</value>
+	      </property>
+	      <property>
+		<name>container.install.dir</name>
+		<value>${basedir}/${project.x.build.directory}/installs</value>
+	      </property>
+	      <property>
+		<name>container.config.dir</name>
+		<value>${basedir}/${project.x.build.directory}/test-containers</value>
+	      </property>
+	      <property>
+		<name>tomcat50.url</name>
+		<value>http://www.apache.org/dist/jakarta/tomcat-5/v5.0.30/bin/jakarta-tomcat-5.0.30.zip</value>
+	      </property>
+	      <property>
+		<name>tomcat50.manager.class.name</name>
+		<value>org.codehaus.wadi.tomcat50.TomcatManager</value>
+	      </property>
+	      <property>
+		<name>tomcat50.cargo.container.name</name>
+		<value>tomcat5x</value>
+	      </property>
+	      <property>
+		<name>tomcat55.url</name>
+		<value>http://www.apache.org/dist/tomcat/tomcat-5/v5.5.12/bin/apache-tomcat-5.5.12.zip</value>
+	      </property>
+	      <property>
+		<name>tomcat55.compatibility.url</name>
+		<value>http://apache.hoxt.com/tomcat/tomcat-5/v5.5.12/bin/apache-tomcat-5.5.12-compat.zip</value>
+	      </property>
+	      <property>
+		<name>tomcat55.manager.class.name</name>
+		<value>org.codehaus.wadi.tomcat55.TomcatManager</value>
+	      </property>
+	      <property>
+		<name>tomcat55.cargo.container.name</name>
+		<value>tomcat5x</value>
+	      </property>
+	    </systemProperties>
+	  </configuration>
+	</plugin>
+      </plugins>
+    </build>
+</project>

Added: incubator/wadi/trunk/modules/itest/src/test/java/org/codehaus/wadi/itest/ContainerTestDecorator.java
URL: http://svn.apache.org/viewcvs/incubator/wadi/trunk/modules/itest/src/test/java/org/codehaus/wadi/itest/ContainerTestDecorator.java?rev=356933&view=auto
==============================================================================
--- incubator/wadi/trunk/modules/itest/src/test/java/org/codehaus/wadi/itest/ContainerTestDecorator.java (added)
+++ incubator/wadi/trunk/modules/itest/src/test/java/org/codehaus/wadi/itest/ContainerTestDecorator.java Wed Dec 14 15:32:56 2005
@@ -0,0 +1,416 @@
+/**
+ *
+ * Copyright 2005 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.codehaus.wadi.itest;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import junit.extensions.TestSetup;
+import junit.framework.Test;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.codehaus.cargo.container.LocalContainer;
+import org.codehaus.cargo.container.configuration.ConfigurationType;
+import org.codehaus.cargo.container.configuration.LocalConfiguration;
+import org.codehaus.cargo.container.deployable.WAR;
+import org.codehaus.cargo.container.installer.Installer;
+import org.codehaus.cargo.container.installer.ZipURLInstaller;
+import org.codehaus.cargo.container.property.ServletPropertySet;
+import org.codehaus.cargo.container.tomcat.TomcatPropertySet;
+import org.codehaus.cargo.container.tomcat.TomcatWAR;
+import org.codehaus.cargo.generic.ContainerFactory;
+import org.codehaus.cargo.generic.DefaultContainerFactory;
+import org.codehaus.cargo.generic.configuration.DefaultConfigurationFactory;
+import org.codehaus.wadi.itest.tomcat.ExtendedTomcatPropertySet;
+
+public class ContainerTestDecorator extends TestSetup {
+  protected Log _log = LogFactory.getLog(getClass());
+  // node names
+  private static final String WHITE = "white";
+  private static final String BROWN = "brown";
+  private static final String PURPLE = "purple";
+  private static final String ORANGE = "orange";
+  private static final String PINK = "pink";
+  private static final String YELLOW = "yellow";
+  private static final String BLUE = "blue";
+  private static final String GREEN = "green";
+  private static final String RED = "red";
+  // property names to configure nodes
+  private static final String NODE_NAME_PROP_NAME = "node.name";
+  private static final String STOP_PORT_PROP_NAME = "STOP.PORT";
+  private static final String JNDI_PORT_PROP_NAME = "jndi.port";
+  private static final String AJP_PORT_PROP_NAME = "ajp.port";
+  private static final String HTTP_PORT_PROP_NAME = "http.port";
+  // cargo property names
+  private static final String TOMCAT55_KEY_NAME = "tomcat55";
+  private static final String TOMCAT50_KEY_NAME = "tomcat50";
+  private static final String CARGO_CONTAINER_NAME_PROP_NAME = "cargoContainerName";
+  private static final String MANAGER_CLASS_NAME_PROP_NAME = "managerClassName";
+  private static final String CONTAINER_URL_PROP_NAME = "url";
+  private static final String INSTALL_DIR_PROP_NAME = "installDir";
+  private static final String CONFIG_BASE_PROP_NAME = "configBase";
+  // the config dir base is the path that the various containers will be
+  // copied to
+  private static final String CONTAINER_CONFIG_DIR_BASE = "target/test-containers/";
+  private static final String WADI_VERSION = System.getProperty("wadi.version");
+  // the systemProps are initialized in a static block at the end of this
+  // class
+  private static Map systemProps = null;
+  // the systemProps are initialized in a static block at the end of this
+  // class
+  //private static Map installProps = null;
+  private LocalContainer containers[] = null;
+
+  public ContainerTestDecorator(Test decorated) {
+    super(decorated);
+  }
+
+  public String getPortForNode(String node) {
+    return (String) ((Map) systemProps.get(node)).get(HTTP_PORT_PROP_NAME);
+  }
+
+  protected void setUp() throws Exception {
+    if(_log.isDebugEnabled()) _log.debug(getClass().getName() + ".setUp()");
+    // parse containers to start
+    String containersProp = System.getProperty("containers");
+    String containerProp = System.getProperty("container");
+    String nodesProp = System.getProperty("nodes");
+    String nodes[] = nodesProp.split(",");
+    if (null != containerProp) {
+      Installer installer = installContainer(containerProp);
+      String containerConfigBase = System.getProperty("container.config.dir") + "/" + containerProp;
+      String managerClassName = System.getProperty(containerProp + ".manager.class.name");
+      String cargoContainerName = System.getProperty(containerProp + ".cargo.container.name");
+      containers = new LocalContainer[nodes.length];
+      // starting one container type
+      for (int i = 0; i < nodes.length; i++) {
+        containers[i] = startContainer((String) nodes[i], containerConfigBase,
+            managerClassName, cargoContainerName, installer);
+      }
+    } else {
+      String containerNames[] = containersProp.split(",");
+      if (containerNames.length != nodes.length) {
+        throw new RuntimeException(
+            "Bad Configuration - containers list must match nodes list -"
+                + " nodes = " + nodesProp + " containers = " + containersProp);
+      }
+      containers = new LocalContainer[containerNames.length];
+      // starting several container types
+      for (int i = 0; i < containerNames.length; i++) {
+        Installer installer = installContainer(containerNames[i]);
+        String containerConfigBase = System.getProperty("container.config.dir") + "/" + containerNames[i];
+        String managerClassName = System.getProperty(containerNames[i] + ".manager.class.name");
+        String cargoContainerName = System.getProperty(containerNames[i] + ".cargo.container.name");
+        // starting one node on each container
+        containers[i] = startContainer((String) nodes[i], containerConfigBase,
+            managerClassName, cargoContainerName, installer);
+      }
+    }
+  }
+
+  // TODO: this assumes tomcat (with the copyJars method, need to rework for
+  // jetty and G)
+  private Installer installContainer(String containerName) throws IOException {
+    if(_log.isDebugEnabled()) _log.debug(getClass().getName() + ".installContainer(" + containerName + ")");
+    String containerUrl = System.getProperty(containerName + ".url");
+    String containerInstallDir = System.getProperty("container.install.dir");
+    Installer installer = installContainer(containerUrl, containerInstallDir);
+    copyJars(installer.getHome(), containerName);
+    if(_log.isDebugEnabled()) _log.debug("copy jars successful");
+    if (containerName.equals(TOMCAT55_KEY_NAME)) {
+      String compatibilityURL = System.getProperty("tomcat55.compatibility.url");
+      installTomcat55JDK14CompatibilityStuff(compatibilityURL,
+          containerInstallDir, installer.getHome().getPath());
+      if(_log.isDebugEnabled()) _log.debug("install compat success");
+    }
+    return installer;
+  }
+
+  private Installer installContainer(String url, String installDir)
+      throws IOException {
+    if(_log.isDebugEnabled()) _log.debug(getClass().getName() + ".installContainer(" + url + ", "
+        + installDir + ")");
+    Installer zipInstaller = new ZipURLInstaller(new URL(url), new File(
+        installDir));
+    zipInstaller.install();
+    return zipInstaller;
+  }
+
+  private void installTomcat55JDK14CompatibilityStuff(String url,
+      String installDir, String tc55InstallDir) throws IOException {
+    Installer zipInstaller = new ZipURLInstaller(new URL(url), new File(
+        installDir));
+    zipInstaller.install();
+    if(_log.isDebugEnabled()) _log.debug("installed compat");
+    // copy the jars
+    File jmx = new File(zipInstaller.getHome().getPath() + "/bin/jmx.jar");
+    File dest = new File(tc55InstallDir + "/bin/jmx.jar");
+    if(_log.isDebugEnabled()) _log.debug("about to copy " + jmx.getPath() + " to " + dest.getPath());
+    copy(jmx, dest);
+    File xerces = new File(zipInstaller.getHome().getPath()
+        + "/common/endorsed/xercesImpl.jar");
+    dest = new File(tc55InstallDir + "/common/endorsed/xercesImp.jar");
+    if(_log.isDebugEnabled()) _log.debug("about to copy " + xerces.getPath() + " to " + dest.getPath());
+    copy(xerces, dest);
+    File xml = new File(zipInstaller.getHome().getPath()
+        + "/common/endorsed/xml-apis.jar");
+    dest = new File(tc55InstallDir + "/common/endorsed/xml-apis.jar");
+    if(_log.isDebugEnabled()) _log.debug("about to copy " + xml.getPath() + " to " + dest.getPath());
+    copy(xml, dest);
+  }
+
+  protected void tearDown() throws Exception {
+    for (int i = 0; i < containers.length; i++) {
+      containers[i].stop();
+    }
+  }
+
+  private LocalContainer startContainer(String nodeName, String dirName,
+      String managerClassName, String cargoContainerName, Installer installer)
+      throws Exception {
+    if(_log.isDebugEnabled()) _log.debug("startContainer(" + nodeName + ", " + dirName + ", "
+        + managerClassName + ", " + cargoContainerName + ", "
+        + installer.getHome());
+    if (null == WADI_VERSION) {
+      if(_log.isDebugEnabled()) _log.debug("no wadi version");
+      throw new RuntimeException(
+          "Bad Configuration - wadi.version must be specified");
+    }
+    String m2Repo = System.getProperty("user.home") + "/.m2/repository";
+    String wadiWARPath = m2Repo + "/wadi/wadi-test-webapp/" + WADI_VERSION
+        + "/wadi-test-webapp-" + WADI_VERSION + ".war";
+    WAR wadi = new TomcatWAR(wadiWARPath);
+    wadi.setContext("wadi-test");
+    File configDir = new File(dirName + "_" + nodeName);
+    File log = new File(configDir.getPath() + "/cargo.log");
+    DefaultConfigurationFactory factory = new DefaultConfigurationFactory();
+    factory.registerConfiguration("tomcat5x",
+        "org.codehaus.wadi.itest.tomcat.Tomcat5xExtendedStandaloneLocalConfiguration",
+        ConfigurationType.STANDALONE);
+    LocalConfiguration config = (LocalConfiguration) factory
+        .createConfiguration(cargoContainerName, ConfigurationType.STANDALONE,
+            configDir);
+    config.setProperty(ExtendedTomcatPropertySet.MANAGER_CLASS_NAME, managerClassName);
+    config.addDeployable(wadi);
+    Map props = (Map) systemProps.get(nodeName);
+    config.setProperty(ServletPropertySet.PORT, (String) props
+        .get(HTTP_PORT_PROP_NAME));
+    config.setProperty(TomcatPropertySet.SHUTDOWN_PORT, (String) props
+        .get(STOP_PORT_PROP_NAME));
+    ContainerFactory containerFactory = new DefaultContainerFactory();
+    LocalContainer container = (LocalContainer) containerFactory
+        .createContainer(cargoContainerName, config);
+    container.setSystemProperties(props);
+    container.setHome(installer.getHome());
+    container.setOutput(log);
+    container.setTimeout(60000);
+    if(_log.isDebugEnabled()) _log.debug("about to start " + container.getName());
+    try {
+      container.start();
+      if(_log.isDebugEnabled()) _log.debug("started " + container.getName());
+    } catch (Exception e) {
+      if(_log.isDebugEnabled()) _log.debug("failed to start " + container.getName());
+      if(_log.isDebugEnabled()) _log.debug("throwable is ", e);
+    }
+    return container;
+  }
+
+  private String getWebappToken(WAR deployable, String managerClassName) {
+    StringBuffer contextTokenValue = new StringBuffer();
+    contextTokenValue.append("\t<Context path=\"");
+    contextTokenValue.append("/" + deployable.getContext());
+    contextTokenValue.append("\" docBase=\"");
+    // Tomcat requires an absolute path for the "docBase" attribute.
+    contextTokenValue.append(deployable.getFile().getAbsolutePath());
+    contextTokenValue.append("\">\n");
+    contextTokenValue.append("\t\t<Manager className=\"" + managerClassName
+        + "\"/>\n");
+    contextTokenValue.append("\t</Context>\n");
+    return contextTokenValue.toString();
+  }
+
+  private void copyJars(File home, String containerName) throws IOException {
+    if (null == WADI_VERSION) {
+      if(_log.isDebugEnabled()) _log.debug("about to throw beacuse of no wadi.version");
+      throw new RuntimeException(
+          "Bad Configuration - wadi.version must be specified");
+    }
+    String rootPath = System.getProperty("user.home") + "/.m2/repository";
+    String commonLibJars[] = new String[] {
+        rootPath
+            + "/activecluster/activecluster/WADI-1.1-SNAPSHOT/activecluster-WADI-1.1-SNAPSHOT.jar",
+        rootPath + "/activemq/activemq/WADI-3.2/activemq-WADI-3.2.jar",
+        rootPath + "/axion/axion/1.0-M3-dev/axion-1.0-M3-dev.jar",
+        rootPath
+            + "/commons-collections/commons-collections/3.1/commons-collections-3.1.jar",
+        rootPath
+            + "/commons-primitives/commons-primitives/1.0/commons-primitives-1.0.jar",
+        rootPath + "/concurrent/concurrent/1.3.4/concurrent-1.3.4.jar",
+        rootPath
+            + "/geronimo-spec/geronimo-spec-j2ee-management/1.0-rc4/geronimo-spec-j2ee-management-1.0-rc4.jar",
+        rootPath
+            + "/geronimo-spec/geronimo-spec-jms/1.1-rc4/geronimo-spec-jms-1.1-rc4.jar",
+        rootPath + "/regexp/regexp/1.3/regexp-1.3.jar",
+        rootPath + "/org/springframework/spring/1.2.5/spring-1.2.5.jar",
+        rootPath + "/wadi/wadi-core/" + WADI_VERSION + "/wadi-core-"
+            + WADI_VERSION + ".jar" };
+    for (int i = 0; i < commonLibJars.length; i++) {
+      File jarFile = new File(commonLibJars[i]);
+      if (!jarFile.exists()) {
+        if(_log.isDebugEnabled()) _log.debug("about to throw beause " + jarFile.getPath()
+            + " does not exist");
+        throw new RuntimeException("file " + jarFile.getPath()
+            + " does not exist");
+      } else {
+        // copy the jar to home/common/lib
+        File dest = new File(home.getAbsolutePath() + "/common/lib/"
+            + jarFile.getName());
+        if (!dest.exists()) {
+          copy(jarFile, dest);
+        }
+      }
+    }
+    String serverLibJar = rootPath + "/wadi/wadi-" + containerName + "/"
+        + WADI_VERSION + "/wadi-" + containerName + "-" + WADI_VERSION + ".jar";
+    File serverLibJarFile = new File(serverLibJar);
+    if (!serverLibJarFile.exists()) {
+      if(_log.isDebugEnabled()) _log.debug("about to throw because " + serverLibJarFile.getPath()
+          + " does not exist");
+      throw new RuntimeException("file " + serverLibJarFile.getPath()
+          + " does not exist");
+    } else {
+      // copy the jar to home/server/lib
+      File dest = new File(home.getAbsolutePath() + "/server/lib/"
+          + serverLibJarFile.getName());
+      if (!dest.exists()) {
+        copy(serverLibJarFile, dest);
+      }
+    }
+  }
+
+  private void copy(File src, File dst) throws IOException {
+    InputStream in = new FileInputStream(src);
+    OutputStream out = new FileOutputStream(dst);
+    // Transfer bytes from in to out
+    byte[] buf = new byte[1024];
+    int len;
+    while ((len = in.read(buf)) > 0) {
+      out.write(buf, 0, len);
+    }
+    in.close();
+    out.close();
+  }
+
+  static {
+    systemProps = new HashMap();
+    Map map = new HashMap();
+    systemProps.put(RED, map);
+    map.put(HTTP_PORT_PROP_NAME, "18080");
+    map.put(AJP_PORT_PROP_NAME, "18009");
+    map.put(JNDI_PORT_PROP_NAME, "11099");
+    map.put(STOP_PORT_PROP_NAME, "18040");
+    map.put(NODE_NAME_PROP_NAME, RED);
+    map = new HashMap();
+    systemProps.put(GREEN, map);
+    map.put(HTTP_PORT_PROP_NAME, "18081");
+    map.put(AJP_PORT_PROP_NAME, "18010");
+    map.put(JNDI_PORT_PROP_NAME, "11100");
+    map.put(STOP_PORT_PROP_NAME, "18041");
+    map.put(NODE_NAME_PROP_NAME, GREEN);
+    map = new HashMap();
+    systemProps.put(BLUE, map);
+    map.put(HTTP_PORT_PROP_NAME, "18082");
+    map.put(AJP_PORT_PROP_NAME, "18011");
+    map.put(JNDI_PORT_PROP_NAME, "11101");
+    map.put(STOP_PORT_PROP_NAME, "18042");
+    map.put(NODE_NAME_PROP_NAME, BLUE);
+    map = new HashMap();
+    systemProps.put(YELLOW, map);
+    map.put(HTTP_PORT_PROP_NAME, "18083");
+    map.put(AJP_PORT_PROP_NAME, "18012");
+    map.put(JNDI_PORT_PROP_NAME, "11102");
+    map.put(STOP_PORT_PROP_NAME, "18043");
+    map.put(NODE_NAME_PROP_NAME, YELLOW);
+    map = new HashMap();
+    systemProps.put(PINK, map);
+    map.put(HTTP_PORT_PROP_NAME, "18084");
+    map.put(AJP_PORT_PROP_NAME, "18013");
+    map.put(JNDI_PORT_PROP_NAME, "11103");
+    map.put(STOP_PORT_PROP_NAME, "18044");
+    map.put(NODE_NAME_PROP_NAME, PINK);
+    map = new HashMap();
+    systemProps.put(ORANGE, map);
+    map.put(HTTP_PORT_PROP_NAME, "18085");
+    map.put(AJP_PORT_PROP_NAME, "18014");
+    map.put(JNDI_PORT_PROP_NAME, "11104");
+    map.put(STOP_PORT_PROP_NAME, "18045");
+    map.put(NODE_NAME_PROP_NAME, ORANGE);
+    map = new HashMap();
+    systemProps.put(PURPLE, map);
+    map.put(HTTP_PORT_PROP_NAME, "18086");
+    map.put(AJP_PORT_PROP_NAME, "18015");
+    map.put(JNDI_PORT_PROP_NAME, "11105");
+    map.put(STOP_PORT_PROP_NAME, "18046");
+    map.put(NODE_NAME_PROP_NAME, PURPLE);
+    map = new HashMap();
+    systemProps.put(BROWN, map);
+    map.put(HTTP_PORT_PROP_NAME, "18087");
+    map.put(AJP_PORT_PROP_NAME, "18016");
+    map.put(JNDI_PORT_PROP_NAME, "11106");
+    map.put(STOP_PORT_PROP_NAME, "18047");
+    map.put(NODE_NAME_PROP_NAME, BROWN);
+    map = new HashMap();
+    systemProps.put(WHITE, map);
+    map.put(HTTP_PORT_PROP_NAME, "18088");
+    map.put(AJP_PORT_PROP_NAME, "18017");
+    map.put(JNDI_PORT_PROP_NAME, "11107");
+    map.put(STOP_PORT_PROP_NAME, "18048");
+    map.put(NODE_NAME_PROP_NAME, WHITE);
+    // install props
+    /*
+    installProps = new HashMap();
+    map = new HashMap();
+    installProps.put(TOMCAT50_KEY_NAME, map);
+    map.put(CONFIG_BASE_PROP_NAME, CONTAINER_CONFIG_DIR_BASE + "tomcat50");
+    map.put(INSTALL_DIR_PROP_NAME, "target/installs");
+    map.put(CONTAINER_URL_PROP_NAME,
+        "http://www.apache.org/dist/jakarta/tomcat-5/v5.0.30/bin/jakarta-tomcat-5.0.30.zip");
+    map.put(MANAGER_CLASS_NAME_PROP_NAME,
+        "org.codehaus.wadi.tomcat50.TomcatManager");
+    map.put(CARGO_CONTAINER_NAME_PROP_NAME, "tomcat5x");
+    map = new HashMap();
+    installProps.put(TOMCAT55_KEY_NAME, map);
+    map.put(CONFIG_BASE_PROP_NAME, CONTAINER_CONFIG_DIR_BASE + "tomcat55");
+    map.put(INSTALL_DIR_PROP_NAME, "target/installs");
+    map.put(CONTAINER_URL_PROP_NAME,
+        "http://www.apache.org/dist/tomcat/tomcat-5/v5.5.12/bin/apache-tomcat-5.5.12.zip");
+    map.put(MANAGER_CLASS_NAME_PROP_NAME,
+        "org.codehaus.wadi.tomcat55.TomcatManager");
+    map.put(CARGO_CONTAINER_NAME_PROP_NAME, "tomcat5x");
+    map
+        .put(
+            "tomcat55JDK14CompaitilityURL",
+            "http://apache.hoxt.com/tomcat/tomcat-5/v5.5.12/bin/apache-tomcat-5.5.12-compat.zip");
+            */
+  }
+}