You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tuscany.apache.org by an...@apache.org on 2009/12/31 08:59:30 UTC

svn commit: r894790 [1/2] - in /tuscany/sandbox/endpoint-ehcache: ./ META-INF/ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/tuscany/ src/main/java/org/apache/tuscany/sca/ src/main/java/org/apache/t...

Author: antelder
Date: Thu Dec 31 07:59:29 2009
New Revision: 894790

URL: http://svn.apache.org/viewvc?rev=894790&view=rev
Log:
Have a look at using ehcache in an endpoint registry impl. In sandbaox for now to avoid yet another impl that doesnt work properly in trunk. 

Added:
    tuscany/sandbox/endpoint-ehcache/   (with props)
    tuscany/sandbox/endpoint-ehcache/META-INF/
    tuscany/sandbox/endpoint-ehcache/META-INF/MANIFEST.MF
    tuscany/sandbox/endpoint-ehcache/pom.xml
    tuscany/sandbox/endpoint-ehcache/src/
    tuscany/sandbox/endpoint-ehcache/src/main/
    tuscany/sandbox/endpoint-ehcache/src/main/java/
    tuscany/sandbox/endpoint-ehcache/src/main/java/org/
    tuscany/sandbox/endpoint-ehcache/src/main/java/org/apache/
    tuscany/sandbox/endpoint-ehcache/src/main/java/org/apache/tuscany/
    tuscany/sandbox/endpoint-ehcache/src/main/java/org/apache/tuscany/sca/
    tuscany/sandbox/endpoint-ehcache/src/main/java/org/apache/tuscany/sca/endpoint/
    tuscany/sandbox/endpoint-ehcache/src/main/java/org/apache/tuscany/sca/endpoint/ehcache/
    tuscany/sandbox/endpoint-ehcache/src/main/java/org/apache/tuscany/sca/endpoint/ehcache/TuscanyRMICacheManagerPeerListener.java
    tuscany/sandbox/endpoint-ehcache/src/main/java/org/apache/tuscany/sca/endpoint/ehcache/TuscanyRMICacheManagerPeerListenerFactory.java
    tuscany/sandbox/endpoint-ehcache/src/main/resources/
    tuscany/sandbox/endpoint-ehcache/src/main/resources/META-INF/
    tuscany/sandbox/endpoint-ehcache/src/main/resources/META-INF/services/
    tuscany/sandbox/endpoint-ehcache/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.EndpointRegistry
    tuscany/sandbox/endpoint-ehcache/src/test/
    tuscany/sandbox/endpoint-ehcache/src/test/java/
    tuscany/sandbox/endpoint-ehcache/src/test/java/org/
    tuscany/sandbox/endpoint-ehcache/src/test/java/org/apache/
    tuscany/sandbox/endpoint-ehcache/src/test/java/org/apache/tuscany/
    tuscany/sandbox/endpoint-ehcache/src/test/java/org/apache/tuscany/sca/
    tuscany/sandbox/endpoint-ehcache/src/test/java/org/apache/tuscany/sca/endpoint/
    tuscany/sandbox/endpoint-ehcache/src/test/java/org/apache/tuscany/sca/endpoint/tribes/
    tuscany/sandbox/endpoint-ehcache/src/test/java/org/apache/tuscany/sca/endpoint/tribes/RegistryTestCase.java
    tuscany/sandbox/endpoint-ehcache/src/test/resources/
    tuscany/sandbox/endpoint-ehcache/src/test/resources/ehcache.xml
    tuscany/sandbox/endpoint-ehcache/src/test/resources/ehcache1.xml
    tuscany/sandbox/endpoint-ehcache/src/test/resources/ehcache2.xml

Propchange: tuscany/sandbox/endpoint-ehcache/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Dec 31 07:59:29 2009
@@ -0,0 +1,20 @@
+target
+work
+dojo
+*.iws
+*.ipr
+*.iml
+derby.log
+maven.log
+maven-eclipse.xml
+build.xml
+build-dependency.xml
+velocity.log*
+junit*.properties
+surefire*.properties
+.project
+.classpath
+.settings
+.deployables
+.wtpmodules
+.externalToolBuilders

Added: tuscany/sandbox/endpoint-ehcache/META-INF/MANIFEST.MF
URL: http://svn.apache.org/viewvc/tuscany/sandbox/endpoint-ehcache/META-INF/MANIFEST.MF?rev=894790&view=auto
==============================================================================
--- tuscany/sandbox/endpoint-ehcache/META-INF/MANIFEST.MF (added)
+++ tuscany/sandbox/endpoint-ehcache/META-INF/MANIFEST.MF Thu Dec 31 07:59:29 2009
@@ -0,0 +1,28 @@
+Manifest-Version: 1.0
+Private-Package: org.apache.tuscany.sca.xsd.impl;version="2.0.0"
+SCA-Version: 1.1
+Bundle-Name: Apache Tuscany SCA Tomcat Tribes Based EndPoint Registry
+Bundle-Vendor: The Apache Software Foundation
+Bundle-Version: 2.0.0
+Bundle-ManifestVersion: 2
+Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt
+Bundle-Description: Apache Tuscany SCA XSD Model
+Bundle-SymbolicName: org.apache.tuscany.sca.endpoint.tribes
+Bundle-DocURL: http://www.apache.org/
+Bundle-RequiredExecutionEnvironment: J2SE-1.5,JavaSE-1.6
+Import-Package: org.apache.catalina.tribes,
+ org.apache.catalina.tribes.group,
+ org.apache.catalina.tribes.group.interceptors,
+ org.apache.catalina.tribes.io,
+ org.apache.catalina.tribes.membership,
+ org.apache.catalina.tribes.tipis,
+ org.apache.catalina.tribes.transport,
+ org.apache.catalina.tribes.util,
+ org.apache.juli.logging;resolution:=optional,
+ org.apache.tuscany.sca.assembly;version="2.0.0",
+ org.apache.tuscany.sca.core;version="2.0.0",
+ org.apache.tuscany.sca.core.assembly.impl;scope=internal;version="2.0.0";resolution:=optional,
+ org.apache.tuscany.sca.management;version="2.0.0",
+ org.apache.tuscany.sca.policy;version="2.0.0",
+ org.apache.tuscany.sca.runtime;version="2.0.0"
+Export-Package: org.apache.tuscany.sca.endpoint.tribes;version="2.0.0"

Added: tuscany/sandbox/endpoint-ehcache/pom.xml
URL: http://svn.apache.org/viewvc/tuscany/sandbox/endpoint-ehcache/pom.xml?rev=894790&view=auto
==============================================================================
--- tuscany/sandbox/endpoint-ehcache/pom.xml (added)
+++ tuscany/sandbox/endpoint-ehcache/pom.xml Thu Dec 31 07:59:29 2009
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+-->
+<project>
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.tuscany.sca</groupId>
+        <artifactId>tuscany-modules</artifactId>
+        <version>2.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <artifactId>tuscany-endpoint-echache</artifactId>
+    <name>Apache Tuscany SCA EndPoint Registry using Ehcache</name>
+
+    <repositories>
+       <repository>
+          <id>sourceforge</id>
+          <url>http://oss.sonatype.org/content/groups/sourceforge/</url>
+          <releases>
+             <enabled>true</enabled>
+          </releases>
+       </repository>
+    </repositories>
+
+    <dependencies>
+        <dependency>
+            <groupId>net.sf.ehcache</groupId>
+            <artifactId>ehcache-core</artifactId>
+            <version>1.7.0</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.tuscany.sca</groupId>
+            <artifactId>tuscany-core-spi</artifactId>
+            <version>2.0-SNAPSHOT</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.tuscany.sca</groupId>
+            <artifactId>tuscany-core</artifactId>
+            <version>2.0-SNAPSHOT</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.tuscany.sca</groupId>
+            <artifactId>tuscany-deployment</artifactId>
+            <version>2.0-SNAPSHOT</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.tuscany.sca</groupId>
+            <artifactId>tuscany-implementation-java-runtime</artifactId>
+            <version>2.0-SNAPSHOT</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+</project>

Added: tuscany/sandbox/endpoint-ehcache/src/main/java/org/apache/tuscany/sca/endpoint/ehcache/TuscanyRMICacheManagerPeerListener.java
URL: http://svn.apache.org/viewvc/tuscany/sandbox/endpoint-ehcache/src/main/java/org/apache/tuscany/sca/endpoint/ehcache/TuscanyRMICacheManagerPeerListener.java?rev=894790&view=auto
==============================================================================
--- tuscany/sandbox/endpoint-ehcache/src/main/java/org/apache/tuscany/sca/endpoint/ehcache/TuscanyRMICacheManagerPeerListener.java (added)
+++ tuscany/sandbox/endpoint-ehcache/src/main/java/org/apache/tuscany/sca/endpoint/ehcache/TuscanyRMICacheManagerPeerListener.java Thu Dec 31 07:59:29 2009
@@ -0,0 +1,602 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+
+package org.apache.tuscany.sca.endpoint.ehcache;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.UnknownHostException;
+import java.rmi.Naming;
+import java.rmi.NotBoundException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.rmi.server.ExportException;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import net.sf.ehcache.CacheException;
+import net.sf.ehcache.CacheManager;
+import net.sf.ehcache.Ehcache;
+import net.sf.ehcache.Status;
+import net.sf.ehcache.distribution.CacheManagerPeerListener;
+import net.sf.ehcache.distribution.CacheReplicator;
+import net.sf.ehcache.distribution.RMICacheManagerPeerListener;
+import net.sf.ehcache.distribution.RMICachePeer;
+import net.sf.ehcache.event.CacheEventListener;
+
+/**
+ * A cache server which exposes available cache operations remotely through RMI.
+ * <p/>
+ * It acts as a Decorator to a Cache. It holds an instance of cache, which is a local cache it talks to.
+ * <p/>
+ * This class could specify a security manager with code like:
+ * <pre>
+ * if (System.getSecurityManager() == null) {
+ *     System.setSecurityManager(new RMISecurityManager());
+ * }
+ * </pre>
+ * Doing so would require the addition of <code>grant</code> statements in the <code>java.policy</code> file.
+ * <p/>
+ * Per the JDK documentation: "If no security manager is specified no class loading, by RMI clients or servers, is allowed,
+ * aside from what can be found in the local CLASSPATH." The classpath of each instance of this class should have
+ * all required classes to enable distribution, so no remote classloading is required or desirable. Accordingly,
+ * no security manager is set and there are no special JVM configuration requirements.
+ * <p/>
+ * This class opens a ServerSocket. The dispose method should be called for orderly closure of that socket. This class
+ * has a shutdown hook which calls dispose() as a convenience feature for developers.
+ *
+ * @author Greg Luck
+ * @version $Id: RMICacheManagerPeerListener.java 1012 2009-08-20 04:23:00Z gregluck $
+ */
+public class TuscanyRMICacheManagerPeerListener implements CacheManagerPeerListener {
+
+    private static final Logger LOG = Logger.getLogger(TuscanyRMICacheManagerPeerListener.class.getName());
+    private static final int MINIMUM_SENSIBLE_TIMEOUT = 200;
+    private static final int NAMING_UNBIND_RETRY_INTERVAL = 400;
+    private static final int NAMING_UNBIND_MAX_RETRIES = 10;
+
+    /**
+     * The cache peers. The value is an RMICachePeer.
+     */
+    protected final Map cachePeers = new HashMap();
+
+    /**
+     * status.
+     */
+    protected Status status;
+
+    /**
+     * The RMI listener port
+     */
+    protected Integer port;
+
+    private Registry registry;
+    private boolean registryCreated;
+    private final String hostName;
+
+    private CacheManager cacheManager;
+    private Integer socketTimeoutMillis;
+    private Integer remoteObjectPort;
+
+    /**
+     * Constructor with full arguments.
+     *
+     * @param hostName            may be null, in which case the hostName will be looked up. Machines with multiple
+     *                            interfaces should specify this if they do not want it to be the default NIC.
+     * @param port                a port in the range 1025 - 65536
+     * @param remoteObjectPort    the port number on which the remote objects bound in the registry receive calls.
+                                  This defaults to a free port if not specified.
+     * @param cacheManager        the CacheManager this listener belongs to
+     * @param socketTimeoutMillis TCP/IP Socket timeout when waiting on response
+     */
+    public TuscanyRMICacheManagerPeerListener(String hostName, Integer port, Integer remoteObjectPort, CacheManager cacheManager,
+                                       Integer socketTimeoutMillis) throws UnknownHostException {
+
+        status = Status.STATUS_UNINITIALISED;
+
+        if (hostName != null && hostName.length() != 0) {
+            this.hostName = hostName;
+            if (hostName.equals("localhost")) {
+                LOG.log(Level.WARNING, "Explicitly setting the listener hostname to 'localhost' is not recommended. "
+                        + "It will only work if all CacheManager peers are on the same machine.");
+            }
+        } else {
+            this.hostName = calculateHostAddress();
+        }
+        if (port == null || port.intValue() == 0) {
+            assignFreePort(false);
+        } else {
+            this.port = port;
+        }
+
+        //by default is 0, which is ok.
+        this.remoteObjectPort = remoteObjectPort;
+
+        this.cacheManager = cacheManager;
+        if (socketTimeoutMillis == null || socketTimeoutMillis.intValue() < MINIMUM_SENSIBLE_TIMEOUT) {
+            throw new IllegalArgumentException("socketTimoutMillis must be a reasonable value greater than 200ms");
+        }
+        this.socketTimeoutMillis = socketTimeoutMillis;
+
+    }
+
+    /**
+     * Assigns a free port to be the listener port.
+     *
+     * @throws IllegalStateException if the statis of the listener is not {@link net.sf.ehcache.Status#STATUS_UNINITIALISED}
+     */
+    protected void assignFreePort(boolean forced) throws IllegalStateException {
+        if (status != Status.STATUS_UNINITIALISED) {
+            throw new IllegalStateException("Cannot change the port of an already started listener.");
+        }
+        this.port = new Integer(this.getFreePort());
+        if (forced) {
+            LOG.log(Level.WARNING, "Resolving RMI port conflict by automatically using a free TCP/IP port to listen on: " + this.port);
+        } else {
+            LOG.log(Level.FINE, "Automatically finding a free TCP/IP port to listen on: " + this.port);
+        }
+    }
+
+
+    /**
+     * Calculates the host address as the default NICs IP address
+     *
+     * @throws UnknownHostException
+     */
+    protected String calculateHostAddress() throws UnknownHostException {
+        return InetAddress.getLocalHost().getHostAddress();
+    }
+
+
+    /**
+     * Gets a free server socket port.
+     *
+     * @return a number in the range 1025 - 65536 that was free at the time this method was executed
+     * @throws IllegalArgumentException
+     */
+    protected int getFreePort() throws IllegalArgumentException {
+        ServerSocket serverSocket = null;
+        try {
+            serverSocket = new ServerSocket(0);
+            return serverSocket.getLocalPort();
+        } catch (IOException e) {
+            throw new IllegalArgumentException("Could not acquire a free port number.");
+        } finally {
+            if (serverSocket != null && !serverSocket.isClosed()) {
+                try {
+                    serverSocket.close();
+                } catch (Exception e) {
+                    LOG.log(Level.FINE, "Error closing ServerSocket: " + e.getMessage());
+                }
+            }
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void init() throws CacheException {
+        if (!status.equals(Status.STATUS_UNINITIALISED)) {
+            return;
+        }
+        RMICachePeer rmiCachePeer = null;
+        try {
+            startRegistry();
+            int counter = 0;
+            populateListOfRemoteCachePeers();
+            synchronized (cachePeers) {
+                for (Iterator iterator = cachePeers.values().iterator(); iterator.hasNext();) {
+                    rmiCachePeer = (RMICachePeer) iterator.next();
+                    bind(rmiCachePeer.getUrl(), rmiCachePeer);
+                    counter++;
+                }
+            }
+            LOG.log(Level.FINE, counter + " RMICachePeers bound in registry for RMI listener");
+            status = Status.STATUS_ALIVE;
+        } catch (Exception e) {
+            String url = null;
+            if (rmiCachePeer != null) {
+                url = rmiCachePeer.getUrl();
+            }
+
+            throw new CacheException("Problem starting listener for RMICachePeer "
+                    + url + ". Initial cause was " + e.getMessage(), e);
+        }
+    }
+
+    /**
+     * Bind a cache peer
+     *
+     * @param rmiCachePeer
+     */
+    protected void bind(String peerName, RMICachePeer rmiCachePeer) throws Exception {
+        Naming.rebind(peerName, rmiCachePeer);
+    }
+
+    /**
+     * Returns a list of bound objects.
+     * <p/>
+     * This should match the list of cachePeers i.e. they should always be bound
+     *
+     * @return a list of String representations of <code>RMICachePeer</code> objects
+     */
+    protected String[] listBoundRMICachePeers() throws CacheException {
+        try {
+            return registry.list();
+        } catch (RemoteException e) {
+            throw new CacheException("Unable to list cache peers " + e.getMessage());
+        }
+    }
+
+    /**
+     * Returns a reference to the remote object.
+     *
+     * @param name the name of the cache e.g. <code>sampleCache1</code>
+     */
+    protected Remote lookupPeer(String name) throws CacheException {
+        try {
+            return registry.lookup(name);
+        } catch (Exception e) {
+            throw new CacheException("Unable to lookup peer for replicated cache " + name + " "
+                    + e.getMessage());
+        }
+    }
+
+    /**
+     * Should be called on init because this is one of the last things that should happen on CacheManager startup.
+     */
+    protected void populateListOfRemoteCachePeers() throws RemoteException {
+        String[] names = cacheManager.getCacheNames();
+        for (int i = 0; i < names.length; i++) {
+            String name = names[i];
+            Ehcache cache = cacheManager.getEhcache(name);
+            synchronized (cachePeers) {
+                if (cachePeers.get(name) == null) {
+                    if (isDistributed(cache)) {
+                        RMICachePeer peer = new RMICachePeer(cache, hostName, port, remoteObjectPort, socketTimeoutMillis);
+                        cachePeers.put(name, peer);
+                    }
+                }
+            }
+        }
+
+    }
+
+    /**
+     * Determine if the given cache is distributed.
+     *
+     * @param cache the cache to check
+     * @return true if a <code>CacheReplicator</code> is found in the listeners
+     */
+    protected boolean isDistributed(Ehcache cache) {
+        Set listeners = cache.getCacheEventNotificationService().getCacheEventListeners();
+        for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+            CacheEventListener cacheEventListener = (CacheEventListener) iterator.next();
+            if (cacheEventListener instanceof CacheReplicator) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Start the rmiregistry.
+     * <p/>
+     * The alternative is to use the <code>rmiregistry</code> binary, in which case:
+     * <ol/>
+     * <li>rmiregistry running
+     * <li>-Djava.rmi.server.codebase="file:///Users/gluck/work/ehcache/build/classes/ file:///Users/gluck/work/ehcache/lib/commons-logging-1.0.4.jar"
+     * </ol>
+     *
+     * @throws RemoteException
+     */
+    protected void startRegistry() throws RemoteException {
+        try {
+            registry = LocateRegistry.getRegistry(port.intValue());
+            try {
+                //may not be created. Let's create it.
+                registry = LocateRegistry.createRegistry(port.intValue());
+                registryCreated = true;
+            } catch (RemoteException e) {
+                registry.list();
+            }
+        } catch (ExportException exception) {
+            LOG.log(Level.SEVERE, "Exception starting RMI registry. Error was " + exception.getMessage(), exception);
+        }
+    }
+
+    /**
+     * Stop the rmiregistry if it was started by this class.
+     *
+     * @throws RemoteException
+     */
+    protected void stopRegistry() throws RemoteException {
+        if (registryCreated) {
+            // the unexportObject call must be done on the Registry object returned
+            // by createRegistry not by getRegistry, a NoSuchObjectException is
+            // thrown otherwise
+            boolean success = UnicastRemoteObject.unexportObject(registry, true);
+            if (success) {
+                LOG.log(Level.FINE, "rmiregistry unexported.");
+            } else {
+                LOG.log(Level.WARNING, "Could not unexport rmiregistry.");
+            }
+        }
+    }
+
+    /**
+     * Stop the listener. It
+     * <ul>
+     * <li>unbinds the objects from the registry
+     * <li>unexports Remote objects
+     * </ul>
+     */
+    public void dispose() throws CacheException {
+        if (!status.equals(Status.STATUS_ALIVE)) {
+            return;
+        }
+        try {
+            int counter = 0;
+            synchronized (cachePeers) {
+                for (Iterator iterator = cachePeers.values().iterator(); iterator.hasNext();) {
+                    RMICachePeer rmiCachePeer = (RMICachePeer) iterator.next();
+                    disposeRMICachePeer(rmiCachePeer);
+                    counter++;
+                }
+                stopRegistry();
+            }
+            LOG.log(Level.FINE, counter + " RMICachePeers unbound from registry in RMI listener");
+            status = Status.STATUS_SHUTDOWN;
+        } catch (Exception e) {
+            throw new CacheException("Problem unbinding remote cache peers. Initial cause was " + e.getMessage(), e);
+        }
+    }
+
+    /**
+     * A template method to dispose an individual RMICachePeer. This consists of:
+     * <ol>
+     * <li>Unbinding the peer from the naming service
+     * <li>Unexporting the peer
+     * </ol>
+     * Override to specialise behaviour
+     *
+     * @param rmiCachePeer the cache peer to dispose of
+     * @throws Exception thrown if something goes wrong
+     */
+    protected void disposeRMICachePeer(RMICachePeer rmiCachePeer) throws Exception {
+        unbind(rmiCachePeer);
+    }
+
+    /**
+     * Unbinds an RMICachePeer and unexports it.
+     * <p/>
+     * We unbind from the registry first before unexporting.
+     * Unbinding first removes the very small possibility of a client
+     * getting the object from the registry while we are trying to unexport it.
+     * <p/>
+     * This method may take up to 4 seconds to complete, if we are having trouble
+     * unexporting the peer.
+     *
+     * @param rmiCachePeer the bound and exported cache peer
+     * @throws Exception
+     */
+    protected void unbind(RMICachePeer rmiCachePeer) throws Exception {
+        String url = rmiCachePeer.getUrl();
+        try {
+            Naming.unbind(url);
+        } catch (NotBoundException e) {
+            LOG.log(Level.WARNING, url + " not bound therefore not unbinding.");
+        }
+        // Try to gracefully unexport before forcing it.
+        boolean unexported = UnicastRemoteObject.unexportObject(rmiCachePeer, false);
+        for (int count = 1; (count < NAMING_UNBIND_MAX_RETRIES) && !unexported; count++) {
+            try {
+                Thread.sleep(NAMING_UNBIND_RETRY_INTERVAL);
+            } catch (InterruptedException ie) {
+                // break out of the unexportObject loop
+                break;
+            }
+            unexported = UnicastRemoteObject.unexportObject(rmiCachePeer, false);
+        }
+
+        // If we still haven't been able to unexport, force the unexport
+        // as a last resort.
+        if (!unexported) {
+            if (!UnicastRemoteObject.unexportObject(rmiCachePeer, true)) {
+                LOG.log(Level.WARNING, "Unable to unexport rmiCachePeer: " + rmiCachePeer.getUrl() + ".  Skipping.");
+            }
+        }
+    }
+
+    /**
+     * All of the caches which are listening for remote changes.
+     *
+     * @return a list of <code>RMICachePeer</code> objects. The list if not live
+     */
+    public List getBoundCachePeers() {
+        List cachePeerList = new ArrayList();
+        synchronized (cachePeers) {
+            for (Iterator iterator = cachePeers.values().iterator(); iterator.hasNext();) {
+                RMICachePeer rmiCachePeer = (RMICachePeer) iterator.next();
+                cachePeerList.add(rmiCachePeer);
+            }
+        }
+        return cachePeerList;
+    }
+
+    /**
+     * Returns the listener status.
+     */
+    public Status getStatus() {
+        return status;
+    }
+
+    /**
+     * A listener will normally have a resource that only one instance can use at the same time,
+     * such as a port. This identifier is used to tell if it is unique and will not conflict with an
+     * existing instance using the resource.
+     *
+     * @return a String identifier for the resource
+     */
+    public String getUniqueResourceIdentifier() {
+        return "RMI listener port: " + port;
+    }
+
+    /**
+     * If a conflict is detected in unique resource use, this method signals the listener to attempt
+     * automatic resolution of the resource conflict.
+     *
+     * @throws IllegalStateException if the statis of the listener is not {@link net.sf.ehcache.Status#STATUS_UNINITIALISED}
+     */
+    public void attemptResolutionOfUniqueResourceConflict() throws IllegalStateException, CacheException {
+        assignFreePort(true);
+    }
+
+    /**
+     * The replication scheme this listener interacts with.
+     * Each peer provider has a scheme name, which can be used by caches to specify for replication and bootstrap purposes.
+     *
+     * @return the well-known scheme name, which is determined by the replication provider author.
+     */
+    public String getScheme() {
+        return "RMI";
+    }
+
+    /**
+     * Called immediately after a cache has been added and activated.
+     * <p/>
+     * Note that the CacheManager calls this method from a synchronized method. Any attempt to call a synchronized
+     * method on CacheManager from this method will cause a deadlock.
+     * <p/>
+     * Note that activation will also cause a CacheEventListener status change notification from
+     * {@link net.sf.ehcache.Status#STATUS_UNINITIALISED} to {@link net.sf.ehcache.Status#STATUS_ALIVE}. Care should be
+     * taken on processing that notification because:
+     * <ul>
+     * <li>the cache will not yet be accessible from the CacheManager.
+     * <li>the addCaches methods whih cause this notification are synchronized on the CacheManager. An attempt to call
+     * {@link net.sf.ehcache.CacheManager#getCache(String)} will cause a deadlock.
+     * </ul>
+     * The calling method will block until this method returns.
+     * <p/>
+     * Repopulates the list of cache peers and rebinds the list.
+     * This method should be called if a cache is dynamically added
+     *
+     * @param cacheName the name of the <code>Cache</code> the operation relates to
+     * @see net.sf.ehcache.event.CacheEventListener
+     */
+    public void notifyCacheAdded(String cacheName) throws CacheException {
+
+        if (LOG.isLoggable(Level.FINE)) {
+            LOG.log(Level.FINE, "Adding " + cacheName + " to RMI listener");
+        }
+
+        //Don't add if exists.
+        synchronized (cachePeers) {
+            if (cachePeers.get(cacheName) != null) {
+                return;
+            }
+        }
+
+        Ehcache cache = cacheManager.getEhcache(cacheName);
+        if (isDistributed(cache)) {
+            RMICachePeer rmiCachePeer = null;
+            String url = null;
+            try {
+                rmiCachePeer = new RMICachePeer(cache, hostName, port, remoteObjectPort, socketTimeoutMillis);
+                url = rmiCachePeer.getUrl();
+                bind(url, rmiCachePeer);
+            } catch (Exception e) {
+                throw new CacheException("Problem starting listener for RMICachePeer "
+                        + url + ". Initial cause was " + e.getMessage(), e);
+            }
+
+            synchronized (cachePeers) {
+                cachePeers.put(cacheName, rmiCachePeer);
+            }
+
+        }
+        if (LOG.isLoggable(Level.FINE)) {
+            LOG.log(Level.FINE, cachePeers.size() + " RMICachePeers bound in registry for RMI listener");
+        }
+    }
+
+    /**
+     * Called immediately after a cache has been disposed and removed. The calling method will block until
+     * this method returns.
+     * <p/>
+     * Note that the CacheManager calls this method from a synchronized method. Any attempt to call a synchronized
+     * method on CacheManager from this method will cause a deadlock.
+     * <p/>
+     * Note that a {@link net.sf.ehcache.event.CacheEventListener} status changed will also be triggered. Any attempt from that notification
+     * to access CacheManager will also result in a deadlock.
+     *
+     * @param cacheName the name of the <code>Cache</code> the operation relates to
+     */
+    public void notifyCacheRemoved(String cacheName) {
+
+        if (LOG.isLoggable(Level.FINE)) {
+            LOG.log(Level.FINE, "Removing " + cacheName + " from RMI listener");
+        }
+
+        //don't remove if already removed.
+        synchronized (cachePeers) {
+            if (cachePeers.get(cacheName) == null) {
+                return;
+            }
+        }
+
+        RMICachePeer rmiCachePeer;
+        synchronized (cachePeers) {
+            rmiCachePeer = (RMICachePeer) cachePeers.remove(cacheName);
+        }
+        String url = null;
+        try {
+            unbind(rmiCachePeer);
+        } catch (Exception e) {
+            throw new CacheException("Error removing Cache Peer "
+                    + url + " from listener. Message was: " + e.getMessage(), e);
+        }
+
+        if (LOG.isLoggable(Level.FINE)) {
+            LOG.log(Level.FINE, cachePeers.size() + " RMICachePeers bound in registry for RMI listener");
+        }
+    }
+
+
+    /**
+     * Package local method for testing
+     */
+    void addCachePeer(String name, RMICachePeer peer) {
+        synchronized (cachePeers) {
+            cachePeers.put(name, peer);
+
+        }
+    }
+}

Added: tuscany/sandbox/endpoint-ehcache/src/main/java/org/apache/tuscany/sca/endpoint/ehcache/TuscanyRMICacheManagerPeerListenerFactory.java
URL: http://svn.apache.org/viewvc/tuscany/sandbox/endpoint-ehcache/src/main/java/org/apache/tuscany/sca/endpoint/ehcache/TuscanyRMICacheManagerPeerListenerFactory.java?rev=894790&view=auto
==============================================================================
--- tuscany/sandbox/endpoint-ehcache/src/main/java/org/apache/tuscany/sca/endpoint/ehcache/TuscanyRMICacheManagerPeerListenerFactory.java (added)
+++ tuscany/sandbox/endpoint-ehcache/src/main/java/org/apache/tuscany/sca/endpoint/ehcache/TuscanyRMICacheManagerPeerListenerFactory.java Thu Dec 31 07:59:29 2009
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+
+package org.apache.tuscany.sca.endpoint.ehcache;
+
+import java.net.UnknownHostException;
+import java.util.Properties;
+
+import net.sf.ehcache.CacheException;
+import net.sf.ehcache.CacheManager;
+import net.sf.ehcache.distribution.CacheManagerPeerListener;
+import net.sf.ehcache.distribution.CacheManagerPeerListenerFactory;
+import net.sf.ehcache.distribution.RMICacheManagerPeerListener;
+import net.sf.ehcache.util.PropertyUtil;
+
+/**
+ * Builds a listener based on RMI.
+ * <p/>
+ * Expected configuration line:
+ * <p/>
+ * <code>
+ * &lt;cachePeerListenerFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
+ * properties="hostName=localhost, port=5000" /&gt;
+ * </code>
+ *
+ * @author Greg Luck
+ * @version $Id: RMICacheManagerPeerListenerFactory.java 1012 2009-08-20 04:23:00Z gregluck $
+ */
+public class TuscanyRMICacheManagerPeerListenerFactory extends CacheManagerPeerListenerFactory {
+
+    /**
+     * The default timeout for cache replication for a single replication action.
+     * This may need to be increased for large data transfers.
+     */
+    public static final Integer DEFAULT_SOCKET_TIMEOUT_MILLIS = new Integer(120000);
+
+    private static final String HOSTNAME = "hostName";
+    private static final String PORT = "port";
+    private static final String REMOTE_OBJECT_PORT = "remoteObjectPort";
+    private static final String SOCKET_TIMEOUT_MILLIS = "socketTimeoutMillis";
+
+    /**
+     * @param properties implementation specific properties. These are configured as comma
+     *                   separated name value pairs in ehcache.xml
+     */
+    public final CacheManagerPeerListener createCachePeerListener(CacheManager cacheManager, Properties properties)
+            throws CacheException {
+        String hostName = PropertyUtil.extractAndLogProperty(HOSTNAME, properties);
+
+        String portString = PropertyUtil.extractAndLogProperty(PORT, properties);
+        Integer port = null;
+        if (portString != null && portString.length() != 0) {
+            port = new Integer(portString);
+        } else {
+            port = new Integer(0);
+        }
+
+        //0 means any port in UnicastRemoteObject, so it is ok if not specified to make it 0
+        String remoteObjectPortString = PropertyUtil.extractAndLogProperty(REMOTE_OBJECT_PORT, properties);
+        Integer remoteObjectPort = null;
+        if (remoteObjectPortString != null && remoteObjectPortString.length() != 0) {
+            remoteObjectPort = new Integer(remoteObjectPortString);
+        } else {
+            remoteObjectPort = new Integer(0);
+        }
+
+        String socketTimeoutMillisString = PropertyUtil.extractAndLogProperty(SOCKET_TIMEOUT_MILLIS, properties);
+        Integer socketTimeoutMillis;
+        if (socketTimeoutMillisString == null || socketTimeoutMillisString.length() == 0) {
+            socketTimeoutMillis = DEFAULT_SOCKET_TIMEOUT_MILLIS;
+        } else {
+            socketTimeoutMillis = new Integer(socketTimeoutMillisString);
+        }
+        return doCreateCachePeerListener(hostName, port, remoteObjectPort, cacheManager, socketTimeoutMillis);
+    }
+
+    /**
+     * A template method to actually create the factory
+     *
+     * @param hostName
+     * @param port
+     * @param remoteObjectPort
+     * @param cacheManager
+     * @param socketTimeoutMillis @return a crate CacheManagerPeerListener
+     */
+    protected CacheManagerPeerListener doCreateCachePeerListener(String hostName,
+                                                                 Integer port,
+                                                                 Integer remoteObjectPort,
+                                                                 CacheManager cacheManager,
+                                                                 Integer socketTimeoutMillis) {
+        try {
+            return new TuscanyRMICacheManagerPeerListener(hostName, port, remoteObjectPort, cacheManager, socketTimeoutMillis);
+        } catch (UnknownHostException e) {
+            throw new CacheException("Unable to create CacheManagerPeerListener. Initial cause was " + e.getMessage(), e);
+        }
+    }
+}

Added: tuscany/sandbox/endpoint-ehcache/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.EndpointRegistry
URL: http://svn.apache.org/viewvc/tuscany/sandbox/endpoint-ehcache/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.EndpointRegistry?rev=894790&view=auto
==============================================================================
--- tuscany/sandbox/endpoint-ehcache/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.EndpointRegistry (added)
+++ tuscany/sandbox/endpoint-ehcache/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.EndpointRegistry Thu Dec 31 07:59:29 2009
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+org.apache.tuscany.sca.endpoint.tribes.ReplicatedEndpointRegistry;ranking=150,address=228.0.0.100,port=50000,timeout=50,scheme=tribes

Added: tuscany/sandbox/endpoint-ehcache/src/test/java/org/apache/tuscany/sca/endpoint/tribes/RegistryTestCase.java
URL: http://svn.apache.org/viewvc/tuscany/sandbox/endpoint-ehcache/src/test/java/org/apache/tuscany/sca/endpoint/tribes/RegistryTestCase.java?rev=894790&view=auto
==============================================================================
--- tuscany/sandbox/endpoint-ehcache/src/test/java/org/apache/tuscany/sca/endpoint/tribes/RegistryTestCase.java (added)
+++ tuscany/sandbox/endpoint-ehcache/src/test/java/org/apache/tuscany/sca/endpoint/tribes/RegistryTestCase.java Thu Dec 31 07:59:29 2009
@@ -0,0 +1,193 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+
+package org.apache.tuscany.sca.endpoint.tribes;
+
+import java.util.Properties;
+
+import junit.framework.Assert;
+import net.sf.ehcache.Cache;
+import net.sf.ehcache.CacheManager;
+import net.sf.ehcache.Ehcache;
+import net.sf.ehcache.Element;
+import net.sf.ehcache.bootstrap.BootstrapCacheLoader;
+import net.sf.ehcache.config.CacheConfiguration;
+import net.sf.ehcache.config.Configuration;
+import net.sf.ehcache.config.ConfigurationHelper;
+import net.sf.ehcache.config.FactoryConfiguration;
+import net.sf.ehcache.config.TerracottaConfiguration;
+import net.sf.ehcache.distribution.CacheManagerPeerProvider;
+import net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory;
+import net.sf.ehcache.distribution.RMICacheManagerPeerListener;
+import net.sf.ehcache.distribution.RMICacheReplicatorFactory;
+import net.sf.ehcache.event.CacheEventListener;
+import net.sf.ehcache.event.RegisteredEventListeners;
+import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
+
+import org.junit.Test;
+
+public class RegistryTestCase {
+
+
+    @Test
+    public void foo() throws InterruptedException {
+        Cache cache2 = createCache2("ehcache2.xml");
+//        Thread.sleep(4000);
+        Cache cache1 = createCache2("ehcache1.xml");
+        cache1.put(new Element("key1", "bla1"));
+        Thread.sleep(400);
+        
+        Assert.assertEquals("bla1", cache2.get("key1").getObjectValue());
+        cache2.put(new Element("k2", "foo2"));
+        Thread.sleep(400);
+        Assert.assertEquals("foo2", cache1.get("k2").getObjectValue());
+    }
+
+    private Cache createCache2(String file) {
+        CacheManager manager = new CacheManager("target/test-classes/" + file);
+        Cache test = manager.getCache("sampleDistributedCache1");
+
+        manager.addCache("foo");
+        Cache test2 = manager.getCache("foo");
+
+        return test;
+    }
+
+//    final Ehcache createCache(CacheConfiguration cacheConfiguration) {
+//        boolean terracottaClustered = false;
+//        String terracottaValueMode = null;
+//        boolean terracottaCoherentReads = true;
+//        TerracottaConfiguration tcConfiguration = cacheConfiguration.getTerracottaConfiguration();
+//        if (tcConfiguration != null) {
+//            terracottaClustered = tcConfiguration.isClustered();
+//            terracottaValueMode = tcConfiguration.getValueMode().name();
+//            terracottaCoherentReads = tcConfiguration.getCoherentReads();
+//        }
+//        
+//        Ehcache cache = new Cache(cacheConfiguration.name,
+//                cacheConfiguration.maxElementsInMemory,
+//                cacheConfiguration.memoryStoreEvictionPolicy,
+//                cacheConfiguration.overflowToDisk,
+//                getDiskStorePath(),
+//                cacheConfiguration.eternal,
+//                cacheConfiguration.timeToLiveSeconds,
+//                cacheConfiguration.timeToIdleSeconds,
+//                cacheConfiguration.diskPersistent,
+//                cacheConfiguration.diskExpiryThreadIntervalSeconds,
+//                null,
+//                null,
+//                cacheConfiguration.maxElementsOnDisk,
+//                cacheConfiguration.diskSpoolBufferSizeMB,
+//                cacheConfiguration.clearOnFlush,
+//                terracottaClustered,
+//                terracottaValueMode,
+//                terracottaCoherentReads);
+//        RegisteredEventListeners listeners = cache.getCacheEventNotificationService();
+//        registerCacheListeners(cacheConfiguration, listeners);
+//        registerCacheExtensions(cacheConfiguration, cache);
+//        BootstrapCacheLoader bootstrapCacheLoader = createBootstrapCacheLoader(
+//                cacheConfiguration.getBootstrapCacheLoaderFactoryConfiguration());
+//        cache.setBootstrapCacheLoader(bootstrapCacheLoader);
+//        registerCacheLoaders(cacheConfiguration, cache);
+//        cache = applyCacheExceptionHandler(cacheConfiguration, cache);
+//        return cache;
+//    }
+    
+//    private Ehcache create(CacheManager manager, String name) {
+//        ConfigurationHelper ch = new ConfigurationHelper(manager, null);
+//        CacheConfiguration cc = new CacheConfiguration();
+//        cc.
+//        
+//        
+//        Ehcache cache = new Cache(name,
+//                                  10000,
+//                                  MemoryStoreEvictionPolicy.LRU,
+//                                  false,
+//                                  "",
+//                                  true,
+//                                  0,
+//                                  0,
+//                                  false,
+//                                  0,
+//                                  null,
+//                                  null,
+//                                  0,
+//                                  0,
+//                                  false,
+//                                  false,
+//                                  null,
+//                                  false);
+//                          RegisteredEventListeners listeners = cache.getCacheEventNotificationService();
+//                          Properties properties = new Properties();
+//                          properties.put("asynchronousReplicationIntervalMillis", "100");
+//                          listeners.registerListener(new RMICacheReplicatorFactory().createCacheEventListener(properties));
+////                          registerCacheListeners(cacheConfiguration, listeners);
+////                          registerCacheExtensions(cacheConfiguration, cache);
+//                          cache.setBootstrapCacheLoader(new RMIBootstrapCacheLoaderFactory().createBootstrapCacheLoader(null));
+////                          registerCacheLoaders(cacheConfiguration, cache);
+//  //                        cache = applyCacheExceptionHandler(cacheConfiguration, cache);
+//       return cache;
+//    }
+    
+   private Cache createCache(int port, boolean multicast, String remotes) {
+        Configuration config = new Configuration();
+
+        if (remotes != null && remotes.length() > 0) {
+            FactoryConfiguration factory = new FactoryConfiguration();
+            factory.setClass("net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory");
+            factory.setPropertySeparator(",");
+            factory.setProperties("peerDiscovery=manual,rmiUrls=//" + remotes);
+            config.addCacheManagerPeerProviderFactory(factory);
+        }
+        
+//        <cacheManagerPeerProviderFactory
+//        class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
+//        properties="peerDiscovery=automatic,
+//                    multicastGroupAddress=230.0.0.1,
+//                    multicastGroupPort=4446, timeToLive=1"/>
+//-->
+
+        if (multicast) {
+            FactoryConfiguration factory = new FactoryConfiguration();
+            factory.setClass("net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory");
+            factory.setPropertySeparator(",");
+            factory.setProperties("peerDiscovery=automatic,multicastGroupAddress=230.0.0.1,multicastGroupPort=4446,timeToLive=1");
+            config.addCacheManagerPeerProviderFactory(factory);
+        }
+        RMICacheManagerPeerListener xxx;
+        FactoryConfiguration factoryx = new FactoryConfiguration();
+        factoryx.setClass("net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory");
+        factoryx.setPropertySeparator(",");
+        factoryx.setProperties("hostname=192.168.0.101,port=" + port);
+        config.addCacheManagerPeerListenerFactory(factoryx);
+        
+        CacheConfiguration defaultCacheConfiguration = new CacheConfiguration();
+        defaultCacheConfiguration.setDiskPersistent(false);
+        config.setDefaultCacheConfiguration(defaultCacheConfiguration);
+        CacheManager singletonManager = new CacheManager(config);
+        CacheManagerPeerProvider pp = singletonManager.getCacheManagerPeerProvider("RMI");
+        Cache memoryOnlyCache = new Cache("testCache", 5000, false, false, 5, 2);
+//        CacheEventListener cacheEventListener = new CacheEventListener();
+//        memoryOnlyCache.getCacheEventNotificationService().registerListener(cacheEventListener);
+        singletonManager.addCache(memoryOnlyCache);
+        Cache test = singletonManager.getCache("testCache");
+        return test;
+    }
+    
+}

Added: tuscany/sandbox/endpoint-ehcache/src/test/resources/ehcache.xml
URL: http://svn.apache.org/viewvc/tuscany/sandbox/endpoint-ehcache/src/test/resources/ehcache.xml?rev=894790&view=auto
==============================================================================
--- tuscany/sandbox/endpoint-ehcache/src/test/resources/ehcache.xml (added)
+++ tuscany/sandbox/endpoint-ehcache/src/test/resources/ehcache.xml Thu Dec 31 07:59:29 2009
@@ -0,0 +1,741 @@
+<?xml version="1.0" encoding="UTF-8"?>
+        
+<!--
+CacheManager Configuration
+==========================
+An ehcache.xml corresponds to a single CacheManager.
+
+See instructions below or the ehcache schema (ehcache.xsd) on how to configure.
+
+System property tokens can be specified in this file which are replaced when the configuration
+is loaded. For example multicastGroupPort=${multicastGroupPort} can be replaced with the
+System property either from an environment variable or a system property specified with a
+command line switch such as -DmulticastGroupPort=4446.
+
+The attributes of <ehcache> are:
+* name - an optional name for the CacheManager.  The name is optional and primarily used 
+for documentation or to distinguish Terracotta clustered cache state.  With Terracotta 
+clustered caches, a combination of CacheManager name and cache name uniquely identify a 
+particular cache store in the Terracotta clustered memory.
+* updateCheck - an optional boolean flag specifying whether this CacheManager should check
+for new versions of Ehcache over the Internet.  If not specified, updateCheck="true".
+* monitoring - an optional setting that determines whether the CacheManager should 
+automatically register the SampledCacheMBean with the system MBean server.
+
+Currently, this monitoring is only useful when using Terracotta clustering and using the
+Terracotta Developer Console. With the "autodetect" value, the presence of Terracotta clustering
+will be detected and monitoring, via the Developer Console, will be enabled. Other allowed values
+are "on" and "off".  The default is "autodetect". This setting does not perform any function when
+used with JMX monitors.
+-->    
+<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:noNamespaceSchemaLocation="ehcache.xsd"
+             updateCheck="true" monitoring="autodetect">
+    
+    <!-- 
+    DiskStore configuration
+    =======================
+
+    The diskStore element is optional. To turn off disk store path creation, comment out the diskStore
+    element below.
+
+    Configure it if you have overflowToDisk or diskPersistent enabled for any cache.
+
+    If it is not configured, and a cache is created which requires a disk store, a warning will be
+     issued and java.io.tmpdir will automatically be used.
+
+    diskStore has only one attribute - "path". It is the path to the directory where
+    .data and .index files will be created.
+
+    If the path is one of the following Java System Property it is replaced by its value in the
+    running VM. For backward compatibility these are not specified without being enclosed in the ${token}
+    replacement syntax.
+
+    The following properties are translated:
+    * user.home - User's home directory
+    * user.dir - User's current working directory
+    * java.io.tmpdir - Default temp file path
+    * ehcache.disk.store.dir - A system property you would normally specify on the command line
+      e.g. java -Dehcache.disk.store.dir=/u01/myapp/diskdir ...
+
+    Subdirectories can be specified below the property e.g. java.io.tmpdir/one
+
+    -->
+    <diskStore path="java.io.tmpdir"/>
+
+    <!--
+    CacheManagerEventListener
+    =========================
+    Specifies a CacheManagerEventListenerFactory which is notified when Caches are added
+    or removed from the CacheManager.
+
+    The attributes of CacheManagerEventListenerFactory are:
+    * class - a fully qualified factory class name
+    * properties - comma separated properties having meaning only to the factory.
+
+    Sets the fully qualified class name to be registered as the CacheManager event listener.
+
+    The events include:
+    * adding a Cache
+    * removing a Cache
+
+    Callbacks to listener methods are synchronous and unsynchronized. It is the responsibility
+    of the implementer to safely handle the potential performance and thread safety issues
+    depending on what their listener is doing.
+
+    If no class is specified, no listener is created. There is no default.
+    -->
+    <cacheManagerEventListenerFactory class="" properties=""/>
+
+
+    <!--
+    CacheManagerPeerProvider
+    ========================
+    (For distributed operation)
+
+    Specifies a CacheManagerPeerProviderFactory which will be used to create a
+    CacheManagerPeerProvider, which discovers other CacheManagers in the cluster.
+
+    One or more providers can be configured. The first one in the ehcache.xml is the default, which is used
+    for replication and bootstrapping.
+
+    The attributes of cacheManagerPeerProviderFactory are:
+    * class - a fully qualified factory class name
+    * properties - comma separated properties having meaning only to the factory.
+
+    Providers are available for RMI, JGroups and JMS as shown following.
+
+    RMICacheManagerPeerProvider
+    +++++++++++++++++++++++++++
+
+    Ehcache comes with a built-in RMI-based distribution system with two means of discovery of
+    CacheManager peers participating in the cluster:
+    * automatic, using a multicast group. This one automatically discovers peers and detects
+      changes such as peers entering and leaving the group
+    * manual, using manual rmiURL configuration. A hardcoded list of peers is provided at
+      configuration time.
+
+    Configuring Automatic Discovery:
+    Automatic discovery is configured as per the following example:
+    <cacheManagerPeerProviderFactory
+                        class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
+                        properties="hostName=fully_qualified_hostname_or_ip,
+                                    peerDiscovery=automatic, multicastGroupAddress=230.0.0.1,
+                                    multicastGroupPort=4446, timeToLive=32"/>
+
+    Valid properties are:
+    * peerDiscovery (mandatory) - specify "automatic"
+    * multicastGroupAddress (mandatory) - specify a valid multicast group address
+    * multicastGroupPort (mandatory) - specify a dedicated port for the multicast heartbeat
+      traffic
+    * timeToLive - specify a value between 0 and 255 which determines how far the packets will
+      propagate.
+
+      By convention, the restrictions are:
+      0   - the same host
+      1   - the same subnet
+      32  - the same site
+      64  - the same region
+      128 - the same continent
+      255 - unrestricted
+
+     * hostName - the hostname or IP of the interface to be used for sending and receiving multicast packets
+       (relevant to mulithomed hosts only)
+
+    Configuring Manual Discovery:
+    Manual discovery requires a unique configuration per host. It is contains a list of rmiURLs for the peers, other
+    than itself. So, if we have server1, server2 and server3 the configuration will be:
+
+    In server1's configuration:
+    <cacheManagerPeerProviderFactory class=
+                          "net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
+                          properties="peerDiscovery=manual,
+                          rmiUrls=//server2:40000/sampleCache1|//server3:40000/sampleCache1
+                          | //server2:40000/sampleCache2|//server3:40000/sampleCache2"
+                          propertySeparator="," />
+
+    In server2's configuration:
+    <cacheManagerPeerProviderFactory class=
+                          "net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
+                          properties="peerDiscovery=manual,
+                          rmiUrls=//server1:40000/sampleCache1|//server3:40000/sampleCache1
+                          | //server1:40000/sampleCache2|//server3:40000/sampleCache2"
+                          propertySeparator="," />
+
+    In server3's configuration:
+    <cacheManagerPeerProviderFactory class=
+                          "net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
+                          properties="peerDiscovery=manual,
+                          rmiUrls=//server1:40000/sampleCache1|//server2:40000/sampleCache1
+                          | //server1:40000/sampleCache2|//server2:40000/sampleCache2"
+                          propertySeparator="," />
+
+
+    Valid properties are:
+    * peerDiscovery (mandatory) - specify "manual"
+    * rmiUrls (mandatory) - specify a pipe separated list of rmiUrls, in the form
+                            //hostname:port
+    * hostname (optional) - the hostname is the hostname of the remote CacheManager peer. The port is the listening
+      port of the RMICacheManagerPeerListener of the remote CacheManager peer.
+    
+    JGroupsCacheManagerPeerProvider
+    +++++++++++++++++++++++++++++++
+    <cacheManagerPeerProviderFactory class="net.sf.ehcache.distribution.jgroups.JGroupsCacheManagerPeerProviderFactory"
+                                     properties="connect=UDP(mcast_addr=231.12.21.132;mcast_port=45566;ip_ttl=32;
+                                     mcast_send_buf_size=150000;mcast_recv_buf_size=80000):
+                                     PING(timeout=2000;num_initial_members=6):
+                                     MERGE2(min_interval=5000;max_interval=10000):
+                                     FD_SOCK:VERIFY_SUSPECT(timeout=1500):
+                                     pbcast.NAKACK(gc_lag=10;retransmit_timeout=3000):
+                                     UNICAST(timeout=5000):
+                                     pbcast.STABLE(desired_avg_gossip=20000):
+                                     FRAG:
+                                     pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;shun=false;print_local_addr=false)"
+                                     propertySeparator="::"
+            />
+     The only property necessary is the connect String used by jgroups to configure itself. Refer to the Jgroups documentation for explanation
+     of all the protocols. The example above uses UDP multicast. If the connect property is not specified the default JGroups connection will be
+     used.       
+
+
+    JMSCacheManagerPeerProviderFactory
+    ++++++++++++++++++++++++++++++++++
+    <cacheManagerPeerProviderFactory
+            class="net.sf.ehcache.distribution.jms.JMSCacheManagerPeerProviderFactory"
+            properties="..."
+            propertySeparator=","
+            />
+
+    The JMS PeerProviderFactory uses JNDI to maintain message queue independence. Refer to the manual for full configuration
+    examples using ActiveMQ and Open Message Queue.
+
+    Valid properties are:
+    * initialContextFactoryName (mandatory) - the name of the factory used to create the message queue initial context.
+    * providerURL (mandatory) - the JNDI configuration information for the service provider to use.
+    * topicConnectionFactoryBindingName (mandatory) - the JNDI binding name for the TopicConnectionFactory
+    * topicBindingName (mandatory) - the JNDI binding name for the topic name
+    * getQueueBindingName (mandatory only if using jmsCacheLoader) - the JNDI binding name for the queue name
+    * securityPrincipalName - the JNDI java.naming.security.principal
+    * securityCredentials - the JNDI java.naming.security.credentials
+    * urlPkgPrefixes - the JNDI java.naming.factory.url.pkgs
+    * userName - the user name to use when creating the TopicConnection to the Message Queue
+    * password - the password to use when creating the TopicConnection to the Message Queue
+    * acknowledgementMode - the JMS Acknowledgement mode for both publisher and subscriber. The available choices are
+                            AUTO_ACKNOWLEDGE, DUPS_OK_ACKNOWLEDGE and SESSION_TRANSACTED. The default is AUTO_ACKNOWLEDGE.
+    -->
+    <cacheManagerPeerProviderFactory
+            class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
+            properties="peerDiscovery=automatic,
+                        multicastGroupAddress=230.0.0.1,
+                        multicastGroupPort=4446, timeToLive=1"
+            propertySeparator=","
+            />
+
+
+    <!--
+    CacheManagerPeerListener
+    ========================
+    (Enable for distributed operation)
+
+    Specifies a CacheManagerPeerListenerFactory which will be used to create a
+    CacheManagerPeerListener, which listens for messages from cache replicators participating in the cluster.
+
+    The attributes of cacheManagerPeerListenerFactory are:
+    class - a fully qualified factory class name
+    properties - comma separated properties having meaning only to the factory.
+
+    Ehcache comes with a built-in RMI-based distribution system. The listener component is
+    RMICacheManagerPeerListener which is configured using
+    RMICacheManagerPeerListenerFactory. It is configured as per the following example:
+
+    <cacheManagerPeerListenerFactory
+        class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
+        properties="hostName=fully_qualified_hostname_or_ip,
+                    port=40001,
+                    remoteObjectPort=40002,
+                    socketTimeoutMillis=120000"
+                    propertySeparator="," />
+
+    All properties are optional. They are:
+    * hostName - the hostName of the host the listener is running on. Specify
+      where the host is multihomed and you want to control the interface over which cluster
+      messages are received. Defaults to the host name of the default interface if not
+      specified.
+    * port - the port the RMI Registry listener listens on. This defaults to a free port if not specified.
+    * remoteObjectPort - the port number on which the remote objects bound in the registry receive calls.
+                         This defaults to a free port if not specified.
+    * socketTimeoutMillis - the number of ms client sockets will stay open when sending
+      messages to the listener. This should be long enough for the slowest message.
+      If not specified it defaults to 120000ms.
+
+    -->
+    <cacheManagerPeerListenerFactory
+            class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"/>
+
+    <!--
+    TerracottaConfig
+    ========================
+    (Enable for Terracotta clustered operation)
+
+    Note: You need to install and run one or more Terracotta servers to use Terracotta clustering.
+    See http://www.terracotta.org/web/display/orgsite/Download.
+
+    Specifies a TerracottaConfig which will be used to configure the Terracotta
+    runtime for this CacheManager.
+    
+    Configuration can be specified in two main ways: by reference to a source of 
+    configuration or by use of an embedded Terracotta configuration file.
+    
+    To specify a reference to a source (or sources) of configuration, use the url 
+    attribute.  The url attribute must contain a comma-separated list of:
+    * path to Terracotta configuration file (usually named tc-config.xml)
+    * URL to Terracotta configuration file
+    * <server host>:<port> of running Terracotta Server instance
+    
+    Simplest example for pointing to a Terracotta server on this machine:
+    <terracottaConfig url="localhost:9510"/>
+    
+    Example using a path to Terracotta configuration file:
+    <terracottaConfig url="/app/config/tc-config.xml"/>
+    
+    Example using a URL to a Terracotta configuration file:
+    <terracottaConfig url="http://internal/ehcache/app/tc-config.xml"/>
+    
+    Example using multiple Terracotta server instance URLs (for fault tolerance):
+    <terracottaConfig url="host1:9510,host2:9510,host3:9510"/>
+
+    To embed a Terracotta configuration file within the ehcache configuration, simply 
+    place a normal Terracotta XML config within the <terracottaConfig> element.
+    
+    Example:
+    <terracottaConfig>
+        <tc-config>
+            <servers>
+                <server host="server1" name="s1"/>
+                <server host="server2" name="s2"/>
+            </servers>
+            <clients>
+                <logs>app/logs-%i</logs>
+            </clients>           
+        </tc-config>
+    </terracottaConfig>
+    
+    For more information on the Terracotta configuration, see the Terracotta documentation.
+    -->
+
+    <!--
+    Cache configuration
+    ===================
+
+    The following attributes are required.
+
+    name:
+    Sets the name of the cache. This is used to identify the cache. It must be unique.
+
+    maxElementsInMemory:
+    Sets the maximum number of objects that will be created in memory
+
+	maxElementsOnDisk:
+    Sets the maximum number of objects that will be maintained in the DiskStore
+	The default value is zero, meaning unlimited.
+
+    eternal:
+    Sets whether elements are eternal. If eternal,  timeouts are ignored and the
+    element is never expired.
+
+    overflowToDisk:
+    Sets whether elements can overflow to disk when the memory store
+    has reached the maxInMemory limit.
+
+    The following attributes and elements are optional.
+
+    timeToIdleSeconds:
+    Sets the time to idle for an element before it expires.
+    i.e. The maximum amount of time between accesses before an element expires
+    Is only used if the element is not eternal.
+    Optional attribute. A value of 0 means that an Element can idle for infinity.
+    The default value is 0.
+
+    timeToLiveSeconds:
+    Sets the time to live for an element before it expires.
+    i.e. The maximum time between creation time and when an element expires.
+    Is only used if the element is not eternal.
+    Optional attribute. A value of 0 means that and Element can live for infinity.
+    The default value is 0.
+
+    diskPersistent:
+    Whether the disk store persists between restarts of the Virtual Machine.
+    The default value is false.
+
+    diskExpiryThreadIntervalSeconds:
+    The number of seconds between runs of the disk expiry thread. The default value
+    is 120 seconds.
+
+    diskSpoolBufferSizeMB:
+    This is the size to allocate the DiskStore for a spool buffer. Writes are made
+    to this area and then asynchronously written to disk. The default size is 30MB.
+    Each spool buffer is used only by its cache. If you get OutOfMemory errors consider
+    lowering this value. To improve DiskStore performance consider increasing it. Trace level
+    logging in the DiskStore will show if put back ups are occurring.
+
+    clearOnFlush:
+    whether the MemoryStore should be cleared when flush() is called on the cache.
+    By default, this is true i.e. the MemoryStore is cleared.
+
+    memoryStoreEvictionPolicy:
+    Policy would be enforced upon reaching the maxElementsInMemory limit. Default
+    policy is Least Recently Used (specified as LRU). Other policies available -
+    First In First Out (specified as FIFO) and Less Frequently Used
+    (specified as LFU)
+
+    Cache elements can also contain sub elements which take the same format of a factory class
+    and properties. Defined sub-elements are:
+
+    * cacheEventListenerFactory - Enables registration of listeners for cache events, such as
+      put, remove, update, and expire.
+
+    * bootstrapCacheLoaderFactory - Specifies a BootstrapCacheLoader, which is called by a
+      cache on initialisation to prepopulate itself.
+
+    * cacheExtensionFactory - Specifies a CacheExtension, a generic mechansim to tie a class
+      which holds a reference to a cache to the cache lifecycle.
+
+    * cacheExceptionHandlerFactory - Specifies a CacheExceptionHandler, which is called when
+      cache exceptions occur.
+
+    * cacheLoaderFactory - Specifies a CacheLoader, which can be used both asynchronously and
+      synchronously to load objects into a cache. More than one cacheLoaderFactory element
+      can be added, in which case the loaders form a chain which are executed in order. If a
+      loader returns null, the next in chain is called.
+      
+
+    RMI Cache Replication
+    +++++++++++++++++++++
+
+    Each cache that will be distributed needs to set a cache event listener which replicates
+    messages to the other CacheManager peers. For the built-in RMI implementation this is done
+    by adding a cacheEventListenerFactory element of type RMICacheReplicatorFactory to each
+    distributed cache's configuration as per the following example:
+
+    <cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+         properties="replicateAsynchronously=true,
+         replicatePuts=true,
+         replicatePutsViaCopy=false,
+         replicateUpdates=true,
+         replicateUpdatesViaCopy=true,
+         replicateRemovals=true
+         asynchronousReplicationIntervalMillis=<number of milliseconds"
+         propertySeparator="," />
+
+    The RMICacheReplicatorFactory recognises the following properties:
+
+    * replicatePuts=true|false - whether new elements placed in a cache are
+      replicated to others. Defaults to true.
+
+    * replicatePutsViaCopy=true|false - whether the new elements are
+      copied to other caches (true), or whether a remove message is sent. Defaults to true.  
+
+    * replicateUpdates=true|false - whether new elements which override an
+      element already existing with the same key are replicated. Defaults to true.
+
+    * replicateRemovals=true - whether element removals are replicated. Defaults to true.
+
+    * replicateAsynchronously=true | false - whether replications are
+      asynchronous (true) or synchronous (false). Defaults to true.
+
+    * replicateUpdatesViaCopy=true | false - whether the new elements are
+      copied to other caches (true), or whether a remove message is sent. Defaults to true.
+
+    * asynchronousReplicationIntervalMillis=<number of milliseconds> - The asynchronous
+      replicator runs at a set interval of milliseconds. The default is 1000. The minimum
+      is 10. This property is only applicable if replicateAsynchronously=true
+
+
+    JGroups Replication
+    +++++++++++++++++++
+
+	For the Jgroups replication this is done with:
+	<cacheEventListenerFactory class="net.sf.ehcache.distribution.jgroups.JGroupsCacheReplicatorFactory"
+                            properties="replicateAsynchronously=true, replicatePuts=true,
+ 							replicateUpdates=true, replicateUpdatesViaCopy=false,
+ 							replicateRemovals=true,asynchronousReplicationIntervalMillis=1000"/>
+    This listener supports the same properties as the RMICacheReplicationFactory.
+
+
+    JMS Replication
+    +++++++++++++++
+
+	For JMS-based replication this is done with:
+	<cacheEventListenerFactory
+          class="net.sf.ehcache.distribution.jms.JMSCacheReplicatorFactory"
+          properties="replicateAsynchronously=true,
+                       replicatePuts=true,
+                       replicateUpdates=true,
+                       replicateUpdatesViaCopy=true,
+                       replicateRemovals=true,
+                       asynchronousReplicationIntervalMillis=1000"
+           propertySeparator=","/>
+
+    This listener supports the same properties as the RMICacheReplicationFactory.
+    
+    Cluster Bootstrapping
+    +++++++++++++++++++++
+
+    Bootstrapping a cluster may use a different mechanism to replication. e.g you can mix
+    JMS replication with bootstrap via RMI - just make sure you have the cacheManagerPeerProviderFactory
+    and cacheManagerPeerListenerFactory configured.
+
+    There are two bootstrapping mechanisms: RMI and JGroups.
+
+    RMI Bootstrap
+
+    The RMIBootstrapCacheLoader bootstraps caches in clusters where RMICacheReplicators are
+    used. It is configured as per the following example:
+
+    <bootstrapCacheLoaderFactory
+        class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+        properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"
+        propertySeparator="," />
+
+    The RMIBootstrapCacheLoaderFactory recognises the following optional properties:
+
+    * bootstrapAsynchronously=true|false - whether the bootstrap happens in the background
+      after the cache has started. If false, bootstrapping must complete before the cache is
+      made available. The default value is true.
+
+    * maximumChunkSizeBytes=<integer> - Caches can potentially be very large, larger than the
+      memory limits of the VM. This property allows the bootstraper to fetched elements in
+      chunks. The default chunk size is 5000000 (5MB).
+
+    JGroups Bootstrap
+
+    Here is an example of bootstrap configuration using JGroups boostrap:
+
+    <bootstrapCacheLoaderFactory class="net.sf.ehcache.distribution.jgroups.JGroupsBootstrapCacheLoaderFactory"
+                                    properties="bootstrapAsynchronously=true"/>
+
+    The configuration properties are the same as for RMI above. Note that JGroups bootstrap only supports
+    asynchronous bootstrap mode.                                
+
+
+    Cache Exception Handling
+
+    By default, most cache operations will propagate a runtime CacheException on failure. An
+    interceptor, using a dynamic proxy, may be configured so that a CacheExceptionHandler can
+    be configured to intercept Exceptions. Errors are not intercepted.
+
+    It is configured as per the following example:
+
+      <cacheExceptionHandlerFactory class="com.example.ExampleExceptionHandlerFactory"
+                                      properties="logLevel=FINE"/>
+
+    Caches with ExceptionHandling configured are not of type Cache, but are of type Ehcache only,
+    and are not available using CacheManager.getCache(), but using CacheManager.getEhcache().
+
+
+    Cache Loader
+
+    A default CacheLoader may be set which loads objects into the cache through asynchronous and
+    synchronous methods on Cache. This is different to the bootstrap cache loader, which is used
+    only in distributed caching.
+
+    It is configured as per the following example:
+
+        <cacheLoaderFactory class="com.example.ExampleCacheLoaderFactory"
+                                      properties="type=int,startCounter=10"/>
+
+    Cache Extension
+
+    CacheExtensions are a general purpose mechanism to allow generic extensions to a Cache.
+    CacheExtensions are tied into the Cache lifecycle.
+
+    CacheExtensions are created using the CacheExtensionFactory which has a
+    <code>createCacheCacheExtension()</code> method which takes as a parameter a
+    Cache and properties. It can thus call back into any public method on Cache, including, of
+    course, the load methods.
+
+    Extensions are added as per the following example:
+
+         <cacheExtensionFactory class="com.example.FileWatchingCacheRefresherExtensionFactory"
+                             properties="refreshIntervalMillis=18000, loaderTimeout=3000,
+                                         flushPeriod=whatever, someOtherProperty=someValue ..."/>
+
+    Terracotta Clustering 
+    
+    Cache elements can also contain information about whether the cache can be clustered with Terracotta.
+    The <terracotta> sub-element has the following attributes:
+
+    * clustered=true|false - indicates whether this cache should be clustered with Terracotta. By 
+      default, if the <terracotta> element is included, clustered=true.
+    * valueMode=serialization|identity - indicates whether this cache should be clustered with 
+      serialized copies of the values or using Terracotta identity mode.  By default, values will
+      be cached in serialization mode which is similar to other replicated Ehcache modes.  The identity
+      mode is only available in certain Terracotta deployment scenarios and will maintain actual object
+      identity of the keys and values across the cluster.  In this case, all users of a value retrieved from 
+      the cache are using the same clustered value and must provide appropriate locking for any changes 
+      made to the value (or objects referred to by the value).
+    * coherentReads=true|false - indicates whether this cache should have coherent reads with guaranteed 
+      consistency across the cluster.  By default, this setting is true.  If you set this property to 
+      false, reads are allowed to check the local value without locking, possibly seeing stale values.  
+      This is a performance optimization with weaker concurrency guarantees and should generally be used 
+      with caches that contain read-only data or where the application can tolerate reading stale
+      data.
+    
+    Simplest example to indicate clustering:
+        <terracotta/>
+        
+    To indicate the cache should not be clustered (or remove the <terracotta> element altogether):    
+        <terracotta clustered="false"/> 
+
+    To indicate the cache should be clustered using identity mode:
+        <terracotta clustered="true" valueMode="identity"/>        
+    -->
+
+    <!--
+    Mandatory Default Cache configuration. These settings will be applied to caches
+    created programmtically using CacheManager.add(String cacheName).
+
+    The defaultCache has an implicit name "default" which is a reserved cache name.
+    -->
+    <defaultCache
+            maxElementsInMemory="10000"
+            eternal="false"
+            timeToIdleSeconds="120"
+            timeToLiveSeconds="120"
+            overflowToDisk="true"
+            diskSpoolBufferSizeMB="30"
+            maxElementsOnDisk="10000000"
+            diskPersistent="false"
+            diskExpiryThreadIntervalSeconds="120"
+            memoryStoreEvictionPolicy="LRU"
+            />
+
+    <!--
+    Sample caches. Following are some example caches. Remove these before use.
+    -->
+
+    <!--
+    Sample cache named sampleCache1
+    This cache contains a maximum in memory of 10000 elements, and will expire
+    an element if it is idle for more than 5 minutes and lives for more than
+    10 minutes.
+
+    If there are more than 10000 elements it will overflow to the
+    disk cache, which in this configuration will go to wherever java.io.tmp is
+    defined on your system. On a standard Linux system this will be /tmp"
+    -->
+    <cache name="sampleCache1"
+           maxElementsInMemory="10000"
+           maxElementsOnDisk="1000"
+           eternal="false"
+           overflowToDisk="true"
+           diskSpoolBufferSizeMB="20"
+           timeToIdleSeconds="300"
+           timeToLiveSeconds="600"
+           memoryStoreEvictionPolicy="LFU"
+            />
+
+
+    <!--
+    Sample cache named sampleCache2
+    This cache has a maximum of 1000 elements in memory. There is no overflow to disk, so 1000
+    is also the maximum cache size. Note that when a cache is eternal, timeToLive and
+    timeToIdle are not used and do not need to be specified.
+    -->
+    <cache name="sampleCache2"
+           maxElementsInMemory="1000"
+           eternal="true"
+           overflowToDisk="false"
+           memoryStoreEvictionPolicy="FIFO"
+            />
+
+
+    <!--
+    Sample cache named sampleCache3. This cache overflows to disk. The disk store is
+    persistent between cache and VM restarts. The disk expiry thread interval is set to 10
+    minutes, overriding the default of 2 minutes.
+    -->
+    <cache name="sampleCache3"
+           maxElementsInMemory="500"
+           eternal="false"
+           overflowToDisk="true"
+           timeToIdleSeconds="300"
+           timeToLiveSeconds="600"
+           diskPersistent="true"
+           diskExpiryThreadIntervalSeconds="1"
+           memoryStoreEvictionPolicy="LFU"
+            />
+
+
+    <!--
+    Sample distributed cache named sampleDistributedCache1.
+    This cache replicates using defaults.
+    It also bootstraps from the cluster, using default properties.
+    -->
+    <cache name="sampleDistributedCache1"
+           maxElementsInMemory="10"
+           eternal="false"
+           timeToIdleSeconds="100"
+           timeToLiveSeconds="100"
+           overflowToDisk="false">
+
+        <cacheEventListenerFactory
+                class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"/>
+        <bootstrapCacheLoaderFactory
+                class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"/>
+    </cache>
+
+
+    <!--
+    Sample distributed cache named sampleDistributedCache2.
+    This cache replicates using specific properties.
+    It only replicates updates and does so synchronously via copy
+    -->
+    <cache name="sampleDistributedCache2"
+           maxElementsInMemory="10"
+           eternal="false"
+           timeToIdleSeconds="100"
+           timeToLiveSeconds="100"
+           overflowToDisk="false">
+        <cacheEventListenerFactory
+                class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+                properties="replicateAsynchronously=false, replicatePuts=false,
+                            replicatePutsViaCopy=false, replicateUpdates=true,
+                            replicateUpdatesViaCopy=true, replicateRemovals=false"/>
+    </cache>
+
+    <!--
+    Sample distributed cache named sampleDistributedCache3.
+    This cache replicates using defaults except that the asynchronous replication
+    interval is set to 200ms.
+    This one includes / and # which were illegal in ehcache 1.5.
+    -->
+    <cache name="sample/DistributedCache3"
+           maxElementsInMemory="10"
+           eternal="false"
+           timeToIdleSeconds="100"
+           timeToLiveSeconds="100"
+           overflowToDisk="true">
+        <cacheEventListenerFactory
+                class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+                properties="asynchronousReplicationIntervalMillis=200"/>
+    </cache>
+
+    <!--
+    Sample Terracotta clustered cache named sampleTerracottaCache.
+    This cache uses Terracotta to cluster the contents of the cache.
+    -->
+    <!--
+    <cache name="sampleTerracottaCache"
+           maxElementsInMemory="1000"
+           eternal="false"
+           timeToIdleSeconds="3600"
+           timeToLiveSeconds="1800"
+           overflowToDisk="false">
+        <terracotta/>
+    </cache>
+    -->
+    
+
+
+</ehcache>

Added: tuscany/sandbox/endpoint-ehcache/src/test/resources/ehcache1.xml
URL: http://svn.apache.org/viewvc/tuscany/sandbox/endpoint-ehcache/src/test/resources/ehcache1.xml?rev=894790&view=auto
==============================================================================
--- tuscany/sandbox/endpoint-ehcache/src/test/resources/ehcache1.xml (added)
+++ tuscany/sandbox/endpoint-ehcache/src/test/resources/ehcache1.xml Thu Dec 31 07:59:29 2009
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:noNamespaceSchemaLocation="ehcache.xsd"
+             updateCheck="false" monitoring="autodetect">
+    
+    <cacheManagerEventListenerFactory class="" properties=""/>
+
+    <cacheManagerPeerProviderFactory
+        class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
+        properties="peerDiscovery=manual,
+                    rmiUrls=//localhost:40009/sampleDistributedCache1"
+        propertySeparator="," />
+
+    <cacheManagerPeerListenerFactory
+        class="org.apache.tuscany.sca.endpoint.ehcache.TuscanyRMICacheManagerPeerListenerFactory"
+        properties="localhost,
+                    port=40001,
+                    remoteObjectPort=40002,
+                    socketTimeoutMillis=120000"
+        propertySeparator="," />
+
+    <defaultCache
+           maxElementsInMemory="10000"
+           eternal="true"
+           overflowToDisk="false">
+        <cacheEventListenerFactory
+                class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+                properties="asynchronousReplicationIntervalMillis=100"/>
+        <bootstrapCacheLoaderFactory
+                class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+                properties="bootstrapAsynchronously=false "/>
+    </defaultCache>
+
+    <cache name="sampleDistributedCache1"
+           maxElementsInMemory="10000"
+           eternal="true"
+           overflowToDisk="false">
+        <cacheEventListenerFactory
+                class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+                properties="asynchronousReplicationIntervalMillis=100"/>
+        <bootstrapCacheLoaderFactory
+                class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+                properties="bootstrapAsynchronously=false "/>
+    </cache>
+
+</ehcache>