svn commit: r726149 [1/3] - in /jakarta/jcs/trunk: ./ src/conf/ src/java/org/apache/jcs/auxiliary/remote/ src/java/org/apache/jcs/auxiliary/remote/behavior/ src/java/org/apache/jcs/auxiliary/remote/http/behavior/ src/java/org/apache/jcs/auxiliary/remot...

[email protected] Fri, 12 Dec 2008 23:37:23 -0000
Newsgroups gmane.comp.jakarta.turbine.jcs.devel
Message-ID <[email protected]>
Author: asmuts
Date: Fri Dec 12 15:37:22 2008
New Revision: 726149

URL: http://svn.apache.org/viewvc?rev=726149&view=rev
Log:
This is a rough http cache client.

Added:
    jakarta/jcs/trunk/src/conf/cacheRHTTP.ccf
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/AbsractRemoteCacheListener.java
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/AbstractRemoteAuxiliaryCache.java
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/AbstractRemoteCacheNoWaitFacade.java
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/behavior/IRemoteCacheDispatcher.java
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/http/client/AbstractHttpClient.java
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/http/client/RemoteHttpCache.java
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/http/client/RemoteHttpCacheAttributes.java
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/http/client/RemoteHttpCacheClient.java
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/http/client/RemoteHttpCacheDispatcher.java
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/http/client/RemoteHttpCacheFactory.java
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/http/client/RemoteHttpCacheManager.java
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/http/client/RemoteHttpCacheMonitor.java
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/http/client/RemoteHttpClientListener.java
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/util/
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/util/RemoteCacheRequestFactory.java   (contents, props changed)
      - copied, changed from r724518, jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/http/client/RemoteHttpClientRequestFactory.java
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/util/RemoteCacheRequestUtil.java
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/value/
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/value/RemoteCacheRequest.java   (contents, props changed)
      - copied, changed from r724518, jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/http/value/RemoteHttpCacheRequest.java
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/value/RemoteCacheResponse.java   (contents, props changed)
      - copied, changed from r724518, jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/http/value/RemoteHttpCacheResponse.java
    jakarta/jcs/trunk/src/test-conf/TestRemoteHttpCache.ccf
    jakarta/jcs/trunk/src/test/org/apache/jcs/auxiliary/remote/http/client/MockRemoteCacheDispatcher.java
    jakarta/jcs/trunk/src/test/org/apache/jcs/auxiliary/remote/http/client/RemoteHttpCacheClientUnitTest.java
    jakarta/jcs/trunk/src/test/org/apache/jcs/auxiliary/remote/http/client/RemoteHttpCacheManualTester.java
    jakarta/jcs/trunk/src/test/org/apache/jcs/auxiliary/remote/util/
    jakarta/jcs/trunk/src/test/org/apache/jcs/auxiliary/remote/util/RemoteCacheRequestFactoryUnitTest.java   (contents, props changed)
      - copied, changed from r724518, jakarta/jcs/trunk/src/test/org/apache/jcs/auxiliary/remote/http/client/RemoteHttpClientRequestFactoryUnitTest.java
Removed:
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/http/client/RemoteHttpClientRequestFactory.java
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/http/value/
    jakarta/jcs/trunk/src/test/org/apache/jcs/auxiliary/remote/http/client/RemoteHttpClientRequestFactoryUnitTest.java
Modified:
    jakarta/jcs/trunk/project.xml
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/RemoteCache.java
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/RemoteCacheListener.java
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/RemoteCacheNoWaitFacade.java
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/behavior/IRemoteCacheListener.java
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/behavior/IRemoteCacheService.java
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/http/behavior/IRemoteHttpCacheConstants.java
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/http/server/RemoteCacheServiceAdaptor.java
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/http/server/RemoteHttpCacheServlet.java
    jakarta/jcs/trunk/src/test/org/apache/jcs/auxiliary/remote/RemoteCacheClientTester.java
    jakarta/jcs/trunk/src/test/org/apache/jcs/auxiliary/remote/http/server/RemoteCacheServiceAdaptorUnitTest.java

Modified: jakarta/jcs/trunk/project.xml
URL: http://svn.apache.org/viewvc/jakarta/jcs/trunk/project.xml?rev=726149&r1=726148&r2=726149&view=diff
==============================================================================
--- jakarta/jcs/trunk/project.xml (original)
+++ jakarta/jcs/trunk/project.xml Fri Dec 12 15:37:22 2008
@@ -225,12 +225,17 @@
 			<type>jar</type>
 		</dependency>
 
-		<!-- LGPL! -->
-		<!--
-			<dependency> <groupId>jgroups</groupId>
-			<artifactId>jgroups-all</artifactId> <version>2.2.8</version>
-			<url></url> <type>jar</type> </dependency>
-		-->
+		<!--  For the HTTP Remote Cache -->
+		<dependency>
+			<groupId>commons-httpclient</groupId>
+			<artifactId>commons-httpclient</artifactId>
+			<version>3.0-rc4</version>
+		</dependency>
+		<dependency>
+			<groupId>commons-codec</groupId>
+			<artifactId>commons-codec</artifactId>
+			<version>1.2</version>
+		</dependency>
 		<dependency>
 			<groupId>tomcat</groupId>
 			<artifactId>tomcat-util</artifactId>

Added: jakarta/jcs/trunk/src/conf/cacheRHTTP.ccf
URL: http://svn.apache.org/viewvc/jakarta/jcs/trunk/src/conf/cacheRHTTP.ccf?rev=726149&view=auto
==============================================================================
--- jakarta/jcs/trunk/src/conf/cacheRHTTP.ccf (added)
+++ jakarta/jcs/trunk/src/conf/cacheRHTTP.ccf Fri Dec 12 15:37:22 2008
@@ -0,0 +1,39 @@
+# 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.
+# #############################################################
+# ################# DEFAULT CACHE REGION  #####################
+# sets the default aux value for any non configured caches
+jcs.default=RC
+jcs.default.cacheattributes=org.apache.jcs.engine.CompositeCacheAttributes
+jcs.default.cacheattributes.MaxObjects=0
+jcs.default.cacheattributes.MemoryCacheName=org.apache.jcs.engine.memory.lru.LRUMemoryCache
+jcs.default.cacheattributes.UseMemoryShrinker=true
+jcs.default.cacheattributes.MaxMemoryIdleTimeSeconds=3600
+jcs.default.cacheattributes.ShrinkerIntervalSeconds=60
+jcs.default.elementattributes=org.apache.jcs.engine.ElementAttributes
+jcs.default.elementattributes.IsEternal=false
+jcs.default.elementattributes.MaxLifeSeconds=700
+jcs.default.elementattributes.IdleTime=1800
+jcs.default.elementattributes.IsSpool=true
+jcs.default.elementattributes.IsRemote=true
+jcs.default.elementattributes.IsLateral=true
+
+
+## The Http Remote Cache Client
+jcs.auxiliary.RC=org.apache.jcs.auxiliary.remote.http.client.RemoteHttpCacheFactory
+jcs.auxiliary.RC.attributes=org.apache.jcs.auxiliary.remote.http.client.RemoteHttpCacheAttributes
+jcs.auxiliary.RC.attributes.url=http://localhost:8000/jcs-app/RemoteCache

Added: jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/AbsractRemoteCacheListener.java
URL: http://svn.apache.org/viewvc/jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/AbsractRemoteCacheListener.java?rev=726149&view=auto
==============================================================================
--- jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/AbsractRemoteCacheListener.java (added)
+++ jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/AbsractRemoteCacheListener.java Fri Dec 12 15:37:22 2008
@@ -0,0 +1,317 @@
+package org.apache.jcs.auxiliary.remote;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.net.UnknownHostException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.jcs.auxiliary.remote.behavior.IRemoteCacheAttributes;
+import org.apache.jcs.auxiliary.remote.behavior.IRemoteCacheListener;
+import org.apache.jcs.engine.behavior.ICacheElement;
+import org.apache.jcs.engine.behavior.ICacheElementSerialized;
+import org.apache.jcs.engine.behavior.ICompositeCacheManager;
+import org.apache.jcs.engine.behavior.IElementSerializer;
+import org.apache.jcs.engine.control.CompositeCache;
+import org.apache.jcs.engine.control.CompositeCacheManager;
+import org.apache.jcs.utils.net.HostNameUtil;
+import org.apache.jcs.utils.serialization.SerializationConversionUtil;
+import org.apache.jcs.utils.serialization.StandardSerializer;
+
+/** Shared listener base. */
+public abstract class AbsractRemoteCacheListener
+    implements IRemoteCacheListener
+{
+    /** Don't change */
+    private static final long serialVersionUID = 1L;
+
+    /** The logger */
+    private final static Log log = LogFactory.getLog( AbsractRemoteCacheListener.class );
+
+    /** The cached name of the local host. The remote server gets this for logging purposes. */
+    private static String localHostName = null;
+
+    /** Has this client been shutdown. */
+    boolean disposed = false;
+
+    /**
+     * The cache manager used to put items in different regions. This is set lazily and should not
+     * be sent to the remote server.
+     */
+    protected transient ICompositeCacheManager cacheMgr;
+
+    /** The remote cache configuration object. */
+    protected IRemoteCacheAttributes irca;
+
+    /** Number of put requests received. For debugging only. */
+    protected int puts = 0;
+
+    /** Number of remove requests received. For debugging only. */
+    protected int removes = 0;
+
+    /** This is set by the remote cache server. */
+    protected long listenerId = 0;
+
+    /** Custom serializer. Standard by default. */
+    private transient IElementSerializer elementSerializer = new StandardSerializer();
+
+    /**
+     * Only need one since it does work for all regions, just reference by multiple region names.
+     * <p>
+     * The constructor exports this object, making it available to receive incoming calls. The
+     * callback port is anonymous unless a local port value was specified in the configuration.
+     * <p>
+     * @param irca
+     * @param cacheMgr
+     */
+    public AbsractRemoteCacheListener( IRemoteCacheAttributes irca, ICompositeCacheManager cacheMgr )
+    {
+        this.irca = irca;
+        this.cacheMgr = cacheMgr;
+    }
+
+    /**
+     * Let the remote cache set a listener_id. Since there is only one listerenr for all the regions
+     * and every region gets registered? the id shouldn't be set if it isn't zero. If it is we
+     * assume that it is a reconnect.
+     * <p>
+     * @param id The new listenerId value
+     * @throws IOException
+     */
+    public void setListenerId( long id )
+        throws IOException
+    {
+        listenerId = id;
+        if ( log.isDebugEnabled() )
+        {
+            log.debug( "set listenerId = [" + id + "]" );
+        }
+    }
+
+    /**
+     * Gets the listenerId attribute of the RemoteCacheListener object. This is stored in the
+     * object. The RemoteCache object contains a reference to the listener and get the id this way.
+     * <p>
+     * @return The listenerId value
+     * @throws IOException
+     */
+    public long getListenerId()
+        throws IOException
+    {
+        if ( log.isDebugEnabled() )
+        {
+            log.debug( "get listenerId = [" + listenerId + "]" );
+        }
+        return listenerId;
+
+    }
+
+    /**
+     * Gets the remoteType attribute of the RemoteCacheListener object <p.
+     * @return The remoteType value
+     * @throws IOException
+     */
+    public int getRemoteType()
+        throws IOException
+    {
+        if ( log.isDebugEnabled() )
+        {
+            log.debug( "getRemoteType = [" + irca.getRemoteType() + "]" );
+        }
+        return irca.getRemoteType();
+    }
+
+    /**
+     * If this is configured to remove on put, then remove the element since it has been updated
+     * elsewhere. cd should be incomplete for faster transmission. We don't want to pass data only
+     * invalidation. The next time it is used the local cache will get the new version from the
+     * remote store.
+     * <p>
+     * If remove on put is not configured, then update the item.
+     * @param cb
+     * @throws IOException
+     */
+    public void handlePut( ICacheElement cb )
+        throws IOException
+    {
+        if ( irca.getRemoveUponRemotePut() )
+        {
+            if ( log.isDebugEnabled() )
+            {
+                log.debug( "PUTTING ELEMENT FROM REMOTE, (  invalidating ) " );
+            }
+            handleRemove( cb.getCacheName(), cb.getKey() );
+        }
+        else
+        {
+            puts++;
+            if ( log.isDebugEnabled() )
+            {
+                log.debug( "PUTTING ELEMENT FROM REMOTE, ( updating ) " );
+                log.debug( "cb = " + cb );
+
+                if ( puts % 100 == 0 )
+                {
+                    log.debug( "puts = " + puts );
+                }
+            }
+
+            ensureCacheManager();
+            CompositeCache cache = cacheMgr.getCache( cb.getCacheName() );
+
+            // Eventually the instance of will not be necessary.
+            if ( cb != null && cb instanceof ICacheElementSerialized )
+            {
+                if ( log.isDebugEnabled() )
+                {
+                    log.debug( "Object needs to be deserialized." );
+                }
+                try
+                {
+                    cb = SerializationConversionUtil.getDeSerializedCacheElement( (ICacheElementSerialized) cb,
+                                                                                  this.elementSerializer );
+                    if ( log.isDebugEnabled() )
+                    {
+                        log.debug( "Deserialized result = " + cb );
+                    }
+                }
+                catch ( IOException e )
+                {
+                    throw e;
+                }
+                catch ( ClassNotFoundException e )
+                {
+                    log.error( "Received a serialized version of a class that we don't know about.", e );
+                }
+            }
+
+            cache.localUpdate( cb );
+        }
+
+        return;
+    }
+
+    /**
+     * Calls localRemove on the CompositeCache.
+     * <p>
+     * @param cacheName
+     * @param key
+     * @throws IOException
+     */
+    public void handleRemove( String cacheName, Serializable key )
+        throws IOException
+    {
+        removes++;
+        if ( log.isDebugEnabled() )
+        {
+            if ( removes % 100 == 0 )
+            {
+                log.debug( "removes = " + removes );
+            }
+
+            log.debug( "handleRemove> cacheName=" + cacheName + ", key=" + key );
+        }
+
+        ensureCacheManager();
+        CompositeCache cache = cacheMgr.getCache( cacheName );
+
+        cache.localRemove( key );
+    }
+
+    /**
+     * Calls localRemoveAll on the CompositeCache.
+     * <p>
+     * @param cacheName
+     * @throws IOException
+     */
+    public void handleRemoveAll( String cacheName )
+        throws IOException
+    {
+        if ( log.isDebugEnabled() )
+        {
+            log.debug( "handleRemoveAll> cacheName=" + cacheName );
+        }
+        ensureCacheManager();
+        CompositeCache cache = cacheMgr.getCache( cacheName );
+        cache.localRemoveAll();
+    }
+
+    /**
+     * @param cacheName
+     * @throws IOException
+     */
+    public void handleDispose( String cacheName )
+        throws IOException
+    {
+        if ( log.isDebugEnabled() )
+        {
+            log.debug( "handleDispose> cacheName=" + cacheName );
+        }
+        // TODO consider what to do here, we really don't want to
+        // dispose, we just want to disconnect.
+        // just allow the cache to go into error recovery mode.
+        // getCacheManager().freeCache( cacheName, true );
+    }
+
+    /**
+     * Gets the cacheManager attribute of the RemoteCacheListener object. This is one of the few
+     * places that force the cache to be a singleton.
+     */
+    protected void ensureCacheManager()
+    {
+        if ( cacheMgr == null )
+        {
+            cacheMgr = CompositeCacheManager.getInstance();
+            log.debug( "had to get cacheMgr" );
+            if ( log.isDebugEnabled() )
+            {
+                log.debug( "cacheMgr = " + cacheMgr );
+            }
+        }
+        else
+        {
+            if ( log.isDebugEnabled() )
+            {
+                log.debug( "already got cacheMgr = " + cacheMgr );
+            }
+        }
+    }
+
+    /**
+     * This is for debugging. It allows the remote server to log the address of clients.
+     * <p>
+     * @return String
+     * @throws IOException
+     */
+    public synchronized String getLocalHostAddress()
+        throws IOException
+    {
+        if ( localHostName == null )
+        {
+            try
+            {
+                localHostName = HostNameUtil.getLocalHostAddress();
+            }
+            catch ( UnknownHostException uhe )
+            {
+                localHostName = "unknown";
+            }
+        }
+        return localHostName;
+    }
+
+    /**
+     * For easier debugging.
+     * <p>
+     * @return Basic info on this listener.
+     */
+    public String toString()
+    {
+        StringBuffer buf = new StringBuffer();
+        buf.append( "\n AbstractRemoteCacheListener: " );
+        buf.append( "\n RemoteHost = " + irca.getRemoteHost() );
+        buf.append( "\n RemotePort = " + irca.getRemotePort() );
+        buf.append( "\n ListenerId = " + listenerId );
+        return buf.toString();
+    }
+}

Added: jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/AbstractRemoteAuxiliaryCache.java
URL: http://svn.apache.org/viewvc/jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/AbstractRemoteAuxiliaryCache.java?rev=726149&view=auto
==============================================================================
--- jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/AbstractRemoteAuxiliaryCache.java (added)
+++ jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/AbstractRemoteAuxiliaryCache.java Fri Dec 12 15:37:22 2008
@@ -0,0 +1,713 @@
+package org.apache.jcs.auxiliary.remote;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.jcs.auxiliary.AbstractAuxiliaryCacheEventLogging;
+import org.apache.jcs.auxiliary.AuxiliaryCacheAttributes;
+import org.apache.jcs.auxiliary.remote.behavior.IRemoteCacheAttributes;
+import org.apache.jcs.auxiliary.remote.behavior.IRemoteCacheClient;
+import org.apache.jcs.auxiliary.remote.behavior.IRemoteCacheListener;
+import org.apache.jcs.auxiliary.remote.behavior.IRemoteCacheService;
+import org.apache.jcs.engine.CacheConstants;
+import org.apache.jcs.engine.behavior.ICacheElement;
+import org.apache.jcs.engine.behavior.ICacheElementSerialized;
+import org.apache.jcs.engine.behavior.IZombie;
+import org.apache.jcs.engine.logging.behavior.ICacheEventLogger;
+import org.apache.jcs.engine.stats.StatElement;
+import org.apache.jcs.engine.stats.Stats;
+import org.apache.jcs.engine.stats.behavior.IStatElement;
+import org.apache.jcs.engine.stats.behavior.IStats;
+import org.apache.jcs.utils.serialization.SerializationConversionUtil;
+import org.apache.jcs.utils.threadpool.ThreadPool;
+import org.apache.jcs.utils.threadpool.ThreadPoolManager;
+
+import EDU.oswego.cs.dl.util.concurrent.Callable;
+import EDU.oswego.cs.dl.util.concurrent.FutureResult;
+import EDU.oswego.cs.dl.util.concurrent.TimeoutException;
+
+/** Abstract base for remote caches. I'm trying to break out and reuse common functionality. */
+public abstract class AbstractRemoteAuxiliaryCache
+    extends AbstractAuxiliaryCacheEventLogging
+    implements IRemoteCacheClient
+{
+    /** Don't change. */
+    private static final long serialVersionUID = -5329231850422826461L;
+
+    /** The logger. */
+    private final static Log log = LogFactory.getLog( AbstractRemoteAuxiliaryCache.class );
+
+    /**
+     * This does the work. In an RMI instances, it will be a remote reference. In an http remote
+     * cache it will be an http client. In zombie mode it is replaced with a balking facade.
+     */
+    private IRemoteCacheService remoteCacheService;
+
+    /** The cacheName */
+    protected final String cacheName;
+
+    /** The listener. This can be null. */
+    private IRemoteCacheListener remoteCacheListener;
+
+    /** The configuration values. TODO, we'll need a base here. */
+    private IRemoteCacheAttributes remoteCacheAttributes;
+
+    /** A thread pool for gets if configured. */
+    private ThreadPool pool = null;
+
+    /** Should we get asynchronously using a pool. */
+    private boolean usePoolForGet = false;
+
+    /**
+     * Creates the base.
+     * <p>
+     * @param cattr
+     * @param remote
+     * @param listener
+     */
+    public AbstractRemoteAuxiliaryCache( IRemoteCacheAttributes cattr, IRemoteCacheService remote,
+                                         IRemoteCacheListener listener )
+    {
+        this.setRemoteCacheAttributes( cattr );
+        this.cacheName = cattr.getCacheName();
+        this.setRemoteCacheService( remote );
+        this.setRemoteCacheListener( listener );
+
+        if ( log.isDebugEnabled() )
+        {
+            log.debug( "Construct> cacheName=" + cattr.getCacheName() );
+            log.debug( "irca = " + getRemoteCacheAttributes() );
+            log.debug( "remote = " + remote );
+            log.debug( "listener = " + listener );
+        }
+
+        // use a pool if it is greater than 0
+        if ( log.isDebugEnabled() )
+        {
+            log.debug( "GetTimeoutMillis() = " + getRemoteCacheAttributes().getGetTimeoutMillis() );
+        }
+
+        if ( getRemoteCacheAttributes().getGetTimeoutMillis() > 0 )
+        {
+            pool = ThreadPoolManager.getInstance().getPool( getRemoteCacheAttributes().getThreadPoolName() );
+            if ( log.isDebugEnabled() )
+            {
+                log.debug( "Thread Pool = " + pool );
+            }
+            if ( pool != null )
+            {
+                usePoolForGet = true;
+            }
+        }
+    }
+
+    /**
+     * Synchronously dispose the remote cache; if failed, replace the remote handle with a zombie.
+     * <p>
+     * @throws IOException
+     */
+    protected void processDispose()
+        throws IOException
+    {
+        if ( log.isInfoEnabled() )
+        {
+            log.info( "Disposing of remote cache." );
+        }
+        try
+        {
+            if ( getRemoteCacheListener() != null )
+            {
+                getRemoteCacheListener().dispose();
+            }
+        }
+        catch ( Exception ex )
+        {
+            log.error( "Couldn't dispose", ex );
+            handleException( ex, "Failed to dispose [" + cacheName + "]", ICacheEventLogger.DISPOSE_EVENT );
+        }
+    }
+
+    /**
+     * Synchronously get from the remote cache; if failed, replace the remote handle with a zombie.
+     * <p>
+     * Use threadpool to timeout if a value is set for GetTimeoutMillis
+     * <p>
+     * If we are a cluster client, we need to leave the Element in its serialized form. Cluster
+     * clients cannot deserialize objects. Cluster clients get ICacheElementSerialized objects from
+     * other remote servers.
+     * <p>
+     * @param key
+     * @return ICacheElement, a wrapper around the key, value, and attributes
+     * @throws IOException
+     */
+    protected ICacheElement processGet( Serializable key )
+        throws IOException
+    {
+        ICacheElement retVal = null;
+        try
+        {
+            if ( usePoolForGet )
+            {
+                retVal = getUsingPool( key );
+            }
+            else
+            {
+                retVal = getRemoteCacheService().get( cacheName, key, getListenerId() );
+            }
+
+            // Eventually the instance of will not be necessary.
+            if ( retVal != null && retVal instanceof ICacheElementSerialized )
+            {
+                // Never try to deserialize if you are a cluster client. Cluster
+                // clients are merely intra-remote cache communicators. Remote caches are assumed
+                // to have no ability to deserialze the objects.
+                if ( this.getRemoteCacheAttributes().getRemoteType() != IRemoteCacheAttributes.CLUSTER )
+                {
+                    retVal = SerializationConversionUtil.getDeSerializedCacheElement( (ICacheElementSerialized) retVal,
+                                                                                      this.elementSerializer );
+                }
+            }
+        }
+        catch ( Exception ex )
+        {
+            handleException( ex, "Failed to get [" + key + "] from [" + cacheName + "]", ICacheEventLogger.GET_EVENT );
+        }
+        return retVal;
+    }
+
+    /**
+     * This allows gets to timeout in case of remote server machine shutdown.
+     * <p>
+     * @param key
+     * @return ICacheElement
+     * @throws IOException
+     */
+    public ICacheElement getUsingPool( final Serializable key )
+        throws IOException
+    {
+        int timeout = getRemoteCacheAttributes().getGetTimeoutMillis();
+
+        try
+        {
+            FutureResult future = new FutureResult();
+            Runnable command = future.setter( new Callable()
+            {
+                public Object call()
+                    throws IOException
+                {
+                    return getRemoteCacheService().get( cacheName, key, getListenerId() );
+                }
+            } );
+
+            // execute using the pool
+            pool.execute( command );
+
+            // used timed get in order to timeout
+            ICacheElement ice = (ICacheElement) future.timedGet( timeout );
+            if ( log.isDebugEnabled() )
+            {
+                if ( ice == null )
+                {
+                    log.debug( "nothing found in remote cache" );
+                }
+                else
+                {
+                    log.debug( "found item in remote cache" );
+                }
+            }
+            return ice;
+        }
+        catch ( TimeoutException te )
+        {
+            log.warn( "TimeoutException, Get Request timed out after " + timeout );
+            throw new IOException( "Get Request timed out after " + timeout );
+        }
+        catch ( InterruptedException ex )
+        {
+            log.warn( "InterruptedException, Get Request timed out after " + timeout );
+            throw new IOException( "Get Request timed out after " + timeout );
+        }
+        catch ( InvocationTargetException ex )
+        {
+            // assume that this is an IOException thrown by the callable.
+            log.error( "InvocationTargetException, Assuming an IO exception thrown in the background.", ex );
+            throw new IOException( "Get Request timed out after " + timeout );
+        }
+    }
+
+    /**
+     * Calls get matching on the server. Each entry in the result is unwrapped.
+     * <p>
+     * @param pattern
+     * @return Map
+     * @throws IOException
+     */
+    public Map processGetMatching( String pattern )
+        throws IOException
+    {
+        Map results = new HashMap();
+        try
+        {
+            Map rawResults = getRemoteCacheService().getMatching( cacheName, pattern, getListenerId() );
+
+            // Eventually the instance of will not be necessary.
+            if ( rawResults != null )
+            {
+                Set entrySet = rawResults.entrySet();
+                Iterator it = entrySet.iterator();
+                while ( it.hasNext() )
+                {
+                    Map.Entry entry = (Map.Entry) it.next();
+                    ICacheElement unwrappedResult = null;
+                    if ( entry.getValue() instanceof ICacheElementSerialized )
+                    {
+                        // Never try to deserialize if you are a cluster client. Cluster
+                        // clients are merely intra-remote cache communicators. Remote caches are assumed
+                        // to have no ability to deserialze the objects.
+                        if ( this.getRemoteCacheAttributes().getRemoteType() != IRemoteCacheAttributes.CLUSTER )
+                        {
+                            unwrappedResult = SerializationConversionUtil
+                                .getDeSerializedCacheElement( (ICacheElementSerialized) entry.getValue(),
+                                                              this.elementSerializer );
+                        }
+                    }
+                    else
+                    {
+                        unwrappedResult = (ICacheElement) entry.getValue();
+                    }
+                    results.put( entry.getKey(), unwrappedResult );
+                }
+            }
+        }
+        catch ( Exception ex )
+        {
+            handleException( ex, "Failed to getMatching [" + pattern + "] from [" + cacheName + "]",
+                             ICacheEventLogger.GET_EVENT );
+        }
+        return results;
+    }
+
+    /**
+     * Gets multiple items from the cache based on the given set of keys.
+     * <p>
+     * @param keys
+     * @return a map of Serializable key to ICacheElement element, or an empty map if there is no
+     *         data in cache for any of these keys
+     * @throws IOException
+     */
+    protected Map processGetMultiple( Set keys )
+        throws IOException
+    {
+        Map elements = new HashMap();
+        if ( keys != null && !keys.isEmpty() )
+        {
+            Iterator iterator = keys.iterator();
+
+            while ( iterator.hasNext() )
+            {
+                Serializable key = (Serializable) iterator.next();
+
+                ICacheElement element = get( key );
+
+                if ( element != null )
+                {
+                    elements.put( key, element );
+                }
+            }
+        }
+        return elements;
+    }
+
+    /**
+     * Synchronously remove from the remote cache; if failed, replace the remote handle with a
+     * zombie.
+     * <p>
+     * @param key
+     * @return boolean, whether or not the item was removed
+     * @throws IOException
+     */
+    protected boolean processRemove( Serializable key )
+        throws IOException
+    {
+        if ( !this.getRemoteCacheAttributes().getGetOnly() )
+        {
+            if ( log.isDebugEnabled() )
+            {
+                log.debug( "remove> key=" + key );
+            }
+            try
+            {
+                getRemoteCacheService().remove( cacheName, key, getListenerId() );
+            }
+            catch ( Exception ex )
+            {
+                handleException( ex, "Failed to remove " + key + " from " + cacheName, ICacheEventLogger.REMOVE_EVENT );
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Synchronously removeAll from the remote cache; if failed, replace the remote handle with a
+     * zombie.
+     * <p>
+     * @throws IOException
+     */
+    protected void processRemoveAll()
+        throws IOException
+    {
+        if ( !this.getRemoteCacheAttributes().getGetOnly() )
+        {
+            try
+            {
+                getRemoteCacheService().removeAll( cacheName, getListenerId() );
+            }
+            catch ( Exception ex )
+            {
+                handleException( ex, "Failed to remove all from " + cacheName, ICacheEventLogger.REMOVEALL_EVENT );
+            }
+        }
+    }
+
+    /**
+     * Serializes the object and then calls update on the remote server with the byte array. The
+     * byte array is wrapped in a ICacheElementSerialized. This allows the remote server to operate
+     * without any knowledge of caches classes.
+     * <p>
+     * @param ce
+     * @throws IOException
+     */
+    protected void processUpdate( ICacheElement ce )
+        throws IOException
+    {
+        if ( !getRemoteCacheAttributes().getGetOnly() )
+        {
+            ICacheElementSerialized serialized = null;
+            try
+            {
+                if ( log.isDebugEnabled() )
+                {
+                    log.debug( "sending item to remote server" );
+                }
+
+                // convert so we don't have to know about the object on the
+                // other end.
+                serialized = SerializationConversionUtil.getSerializedCacheElement( ce, this.elementSerializer );
+
+                remoteCacheService.update( serialized, getListenerId() );
+            }
+            catch ( NullPointerException npe )
+            {
+                log.error( "npe for ce = " + ce + "ce.attr = " + ce.getElementAttributes(), npe );
+            }
+            catch ( Exception ex )
+            {
+                // event queue will wait and retry
+                handleException( ex, "Failed to put [" + ce.getKey() + "] to " + ce.getCacheName(),
+                                 ICacheEventLogger.UPDATE_EVENT );
+            }
+        }
+        else
+        {
+            if ( log.isDebugEnabled() )
+            {
+                log.debug( "get only mode, not sending to remote server" );
+            }
+        }
+    }
+
+    /**
+     * Returns all the keys for a group.
+     * <p>
+     * @param groupName
+     * @return Set
+     * @throws java.rmi.RemoteException
+     * @throws IOException 
+     */
+    public Set getGroupKeys( String groupName )
+        throws java.rmi.RemoteException, IOException
+    {
+        return getRemoteCacheService().getGroupKeys( cacheName, groupName );
+    }
+
+    /**
+     * Allows other member of this package to access the listerner. This is mainly needed for
+     * deregistering a listener.
+     * <p>
+     * @return IRemoteCacheListener, the listener for this remote server
+     */
+    public IRemoteCacheListener getListener()
+    {
+        return getRemoteCacheListener();
+    }
+
+    /**
+     * let the remote cache set a listener_id. Since there is only one listener for all the regions
+     * and every region gets registered? the id shouldn't be set if it isn't zero. If it is we
+     * assume that it is a reconnect.
+     * <p>
+     * @param id The new listenerId value
+     */
+    public void setListenerId( long id )
+    {
+        if ( getRemoteCacheListener() != null )
+        {
+            try
+            {
+                getRemoteCacheListener().setListenerId( id );
+
+                if ( log.isDebugEnabled() )
+                {
+                    log.debug( "set listenerId = " + id );
+                }
+            }
+            catch ( Exception e )
+            {
+                log.error( "Problem setting listenerId", e );
+            }
+        }
+    }
+
+    /**
+     * Gets the listenerId attribute of the RemoteCacheListener object
+     * <p>
+     * @return The listenerId value
+     */
+    public long getListenerId()
+    {
+        if ( getRemoteCacheListener() != null )
+        {
+            try
+            {
+                if ( log.isDebugEnabled() )
+                {
+                    log.debug( "get listenerId = " + getRemoteCacheListener().getListenerId() );
+                }
+                return getRemoteCacheListener().getListenerId();
+            }
+            catch ( Exception e )
+            {
+                log.error( "Problem getting listenerId", e );
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Returns the current cache size.
+     * @return The size value
+     */
+    public int getSize()
+    {
+        return 0;
+    }
+
+    /**
+     * Custom exception handling some children.  This should be used to initiate failover.
+     * <p>
+     * @param ex
+     * @param msg
+     * @param eventName
+     * @throws IOException
+     */
+    protected abstract void handleException( Exception ex, String msg, String eventName )
+        throws IOException;
+
+    /**
+     * Gets the stats attribute of the RemoteCache object.
+     * <p>
+     * @return The stats value
+     */
+    public String getStats()
+    {
+        return getStatistics().toString();
+    }
+    
+    /**
+     * @return IStats object
+     */
+    public IStats getStatistics()
+    {
+        IStats stats = new Stats();
+        stats.setTypeName( "AbstractRemoteAuxiliaryCache" );
+
+        ArrayList elems = new ArrayList();
+
+        IStatElement se = null;
+
+        se = new StatElement();
+        se.setName( "Remote Type" );
+        se.setData( this.getRemoteCacheAttributes().getRemoteTypeName() + "" );
+        elems.add( se );
+
+        if ( this.getRemoteCacheAttributes().getRemoteType() == IRemoteCacheAttributes.CLUSTER )
+        {
+            // something cluster specific
+        }
+
+        // no data gathered here
+
+        se = new StatElement();
+        se.setName( "UsePoolForGet" );
+        se.setData( "" + usePoolForGet );
+        elems.add( se );
+
+        if ( pool != null )
+        {
+            se = new StatElement();
+            se.setName( "Pool Size" );
+            se.setData( "" + pool.getPool().getPoolSize() );
+            elems.add( se );
+
+            se = new StatElement();
+            se.setName( "Maximum Pool Size" );
+            se.setData( "" + pool.getPool().getMaximumPoolSize() );
+            elems.add( se );
+        }
+
+        if ( getRemoteCacheService() instanceof ZombieRemoteCacheService )
+        {
+            se = new StatElement();
+            se.setName( "Zombie Queue Size" );
+            se.setData( "" + ( (ZombieRemoteCacheService) getRemoteCacheService() ).getQueueSize() );
+            elems.add( se );
+        }
+
+        // get an array and put them in the Stats object
+        IStatElement[] ses = (IStatElement[]) elems.toArray( new StatElement[0] );
+        stats.setStatElements( ses );
+
+        return stats;
+    }
+
+    /**
+     * Returns the cache status. An error status indicates the remote connection is not available.
+     * <p>
+     * @return The status value
+     */
+    public int getStatus()
+    {
+        return getRemoteCacheService() instanceof IZombie ? CacheConstants.STATUS_ERROR : CacheConstants.STATUS_ALIVE;
+    }
+
+    /**
+     * Replaces the current remote cache service handle with the given handle. If the current remote
+     * is a Zombie, then it propagates any events that are queued to the restored service.
+     * <p>
+     * @param restoredRemote IRemoteCacheService -- the remote server or proxy to the remote server
+     */
+    public void fixCache( IRemoteCacheService restoredRemote )
+    {
+        if ( getRemoteCacheService() != null && getRemoteCacheService() instanceof ZombieRemoteCacheService )
+        {
+            ZombieRemoteCacheService zombie = (ZombieRemoteCacheService) getRemoteCacheService();
+            setRemoteCacheService( restoredRemote );
+            try
+            {
+                zombie.propagateEvents( restoredRemote );
+            }
+            catch ( Exception e )
+            {
+                try
+                {
+                    handleException( e, "Problem propagating events from Zombie Queue to new Remote Service.",
+                                     "fixCache" );
+                }
+                catch ( IOException e1 )
+                {
+                    // swallow, since this is just expected kick back.  Handle always throws
+                }
+            }
+        }
+        else
+        {
+            setRemoteCacheService( restoredRemote );
+        }
+        return;
+    }
+
+    
+    /**
+     * Gets the cacheType attribute of the RemoteCache object
+     * @return The cacheType value
+     */
+    public int getCacheType()
+    {
+        return REMOTE_CACHE;
+    }
+
+    /**
+     * Gets the cacheName attribute of the RemoteCache object.
+     * <p>
+     * @return The cacheName value
+     */
+    public String getCacheName()
+    {
+        return cacheName;
+    }
+
+    /**
+     * @param remote the remote to set
+     */
+    protected void setRemoteCacheService( IRemoteCacheService remote )
+    {
+        this.remoteCacheService = remote;
+    }
+
+    /**
+     * @return the remote
+     */
+    protected IRemoteCacheService getRemoteCacheService()
+    {
+        return remoteCacheService;
+    }
+
+    /**
+     * @return Returns the AuxiliaryCacheAttributes.
+     */
+    public AuxiliaryCacheAttributes getAuxiliaryCacheAttributes()
+    {
+        return getRemoteCacheAttributes();
+    }
+
+    /**
+     * @param remoteCacheAttributes the remoteCacheAttributes to set
+     */
+    protected void setRemoteCacheAttributes( IRemoteCacheAttributes remoteCacheAttributes )
+    {
+        this.remoteCacheAttributes = remoteCacheAttributes;
+    }
+
+    /**
+     * @return the remoteCacheAttributes
+     */
+    protected IRemoteCacheAttributes getRemoteCacheAttributes()
+    {
+        return remoteCacheAttributes;
+    }
+
+    /**
+     * @param remoteCacheListener the remoteCacheListener to set
+     */
+    protected void setRemoteCacheListener( IRemoteCacheListener remoteCacheListener )
+    {
+        this.remoteCacheListener = remoteCacheListener;
+    }
+
+    /**
+     * @return the remoteCacheListener
+     */
+    protected IRemoteCacheListener getRemoteCacheListener()
+    {
+        return remoteCacheListener;
+    }
+}

Added: jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/AbstractRemoteCacheNoWaitFacade.java
URL: http://svn.apache.org/viewvc/jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/AbstractRemoteCacheNoWaitFacade.java?rev=726149&view=auto
==============================================================================
--- jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/AbstractRemoteCacheNoWaitFacade.java (added)
+++ jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/AbstractRemoteCacheNoWaitFacade.java Fri Dec 12 15:37:22 2008
@@ -0,0 +1,453 @@
+package org.apache.jcs.auxiliary.remote;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.jcs.auxiliary.AbstractAuxiliaryCache;
+import org.apache.jcs.auxiliary.AuxiliaryCache;
+import org.apache.jcs.auxiliary.AuxiliaryCacheAttributes;
+import org.apache.jcs.auxiliary.remote.behavior.IRemoteCacheAttributes;
+import org.apache.jcs.engine.CacheConstants;
+import org.apache.jcs.engine.behavior.ICacheElement;
+import org.apache.jcs.engine.behavior.ICacheType;
+import org.apache.jcs.engine.behavior.ICompositeCacheManager;
+import org.apache.jcs.engine.behavior.IElementSerializer;
+import org.apache.jcs.engine.logging.behavior.ICacheEventLogger;
+import org.apache.jcs.engine.stats.StatElement;
+import org.apache.jcs.engine.stats.Stats;
+import org.apache.jcs.engine.stats.behavior.IStatElement;
+import org.apache.jcs.engine.stats.behavior.IStats;
+
+/** An abstract base for the No Wait Facade.  Different implmentations will failover differently. */
+public abstract class AbstractRemoteCacheNoWaitFacade
+    extends AbstractAuxiliaryCache
+{
+    /** For serialization. Don't change. */
+    private static final long serialVersionUID = -4529970797620747110L;
+
+    /** log instance */
+    private final static Log log = LogFactory.getLog( AbstractRemoteCacheNoWaitFacade.class );
+
+    /** The connection to a remote server, or a zombie. */
+    public RemoteCacheNoWait[] noWaits;
+
+    /** The cache name */
+    private String cacheName;
+
+    /** holds failover and cluster information */
+    protected IRemoteCacheAttributes remoteCacheAttributes;
+
+    /** A cache manager */
+    private ICompositeCacheManager compositeCacheManager;
+
+    /**
+     * Constructs with the given remote cache, and fires events to any listeners.
+     * <p>
+     * @param noWaits
+     * @param rca
+     * @param cacheMgr
+     * @param cacheEventLogger
+     * @param elementSerializer
+     */
+    public AbstractRemoteCacheNoWaitFacade( RemoteCacheNoWait[] noWaits, RemoteCacheAttributes rca,
+                                    ICompositeCacheManager cacheMgr, ICacheEventLogger cacheEventLogger,
+                                    IElementSerializer elementSerializer )
+    {
+        if ( log.isDebugEnabled() )
+        {
+            log.debug( "CONSTRUCTING NO WAIT FACADE" );
+        }
+        this.noWaits = noWaits;
+        this.remoteCacheAttributes = rca;
+        this.cacheName = rca.getCacheName();
+        setCompositeCacheManager( cacheMgr );
+        this.cacheEventLogger = cacheEventLogger;
+        this.elementSerializer = elementSerializer;
+    }
+
+    /**
+     * Put an element in the cache.
+     * <p>
+     * @param ce
+     * @throws IOException
+     */
+    public void update( ICacheElement ce )
+        throws IOException
+    {
+        if ( log.isDebugEnabled() )
+        {
+            log.debug( "updating through cache facade, noWaits.length = " + noWaits.length );
+        }
+        int i = 0;
+        try
+        {
+            for ( ; i < noWaits.length; i++ )
+            {
+                noWaits[i].update( ce );
+                // an initial move into a zombie will lock this to primary
+                // recovery. will not discover other servers until primary
+                // reconnect
+                // and subsequent error
+            }
+        }
+        catch ( Exception ex )
+        {
+            String message = "Problem updating no wait.  Will initiate failover if the noWait is in error.";
+            log.error( message, ex );
+
+            if ( getCacheEventLogger() != null )
+            {
+                getCacheEventLogger().logError(
+                                                "RemoteCacheNoWaitFacade",
+                                                ICacheEventLogger.UPDATE_EVENT,
+                                                message + ":" + ex.getMessage() + " REGION: " + ce.getCacheName()
+                                                    + " ELEMENT: " + ce );
+            }
+
+            // can handle failover here? Is it safe to try the others?
+            // check to see it the noWait is now a zombie
+            // if it is a zombie, then move to the next in the failover list
+            // will need to keep them in order or a count
+            failover( i );
+            // should start a failover thread
+            // should probably only failover if there is only one in the noWait
+            // list
+            // Should start a background thread to restore the original primary if we are in failover state.
+        }
+    }
+
+    /**
+     * Synchronously reads from the remote cache.
+     * <p>
+     * @param key
+     * @return Either an ICacheElement or null if it is not found.
+     */
+    public ICacheElement get( Serializable key )
+    {
+        for ( int i = 0; i < noWaits.length; i++ )
+        {
+            try
+            {
+                Object obj = noWaits[i].get( key );
+                if ( obj != null )
+                {
+                    return (ICacheElement) obj;
+                }
+            }
+            catch ( Exception ex )
+            {
+                log.debug( "Failed to get." );
+                return null;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Synchronously read from the remote cache.
+     * <p>
+     * @param pattern
+     * @return map
+     * @throws IOException
+     */
+    public Map getMatching( String pattern )
+        throws IOException
+    {
+        for ( int i = 0; i < noWaits.length; i++ )
+        {
+            try
+            {
+                return noWaits[i].getMatching( pattern );
+            }
+            catch ( Exception ex )
+            {
+                log.debug( "Failed to getMatching." );
+                return Collections.EMPTY_MAP;
+            }
+        }
+        return Collections.EMPTY_MAP;
+    }
+
+    /**
+     * Gets multiple items from the cache based on the given set of keys.
+     * <p>
+     * @param keys
+     * @return a map of Serializable key to ICacheElement element, or an empty map if there is no
+     *         data in cache for any of these keys
+     */
+    public Map getMultiple( Set keys )
+    {
+        if ( keys != null && !keys.isEmpty() )
+        {
+            for ( int i = 0; i < noWaits.length; i++ )
+            {
+                try
+                {
+                    return noWaits[i].getMultiple( keys );
+                }
+                catch ( Exception ex )
+                {
+                    log.debug( "Failed to get." );
+                    return Collections.EMPTY_MAP;
+                }
+            }
+        }
+        return new HashMap();
+    }
+
+    /**
+     * Gets the set of keys of objects currently in the group.
+     * <p>
+     * @param group
+     * @return the set of keys of objects currently in the group
+     * @throws IOException
+     */
+    public Set getGroupKeys( String group )
+        throws IOException
+    {
+        HashSet allKeys = new HashSet();
+        for ( int i = 0; i < noWaits.length; i++ )
+        {
+            AuxiliaryCache aux = noWaits[i];
+            if ( aux != null )
+            {
+                allKeys.addAll( aux.getGroupKeys( group ) );
+            }
+        }
+        return allKeys;
+    }
+
+    /**
+     * Adds a remove request to the remote cache.
+     * <p>
+     * @param key
+     * @return whether or not it was removed, right now it return false.
+     */
+    public boolean remove( Serializable key )
+    {
+        try
+        {
+            for ( int i = 0; i < noWaits.length; i++ )
+            {
+                noWaits[i].remove( key );
+            }
+        }
+        catch ( Exception ex )
+        {
+            log.error( ex );
+        }
+        return false;
+    }
+
+    /**
+     * Adds a removeAll request to the remote cache.
+     */
+    public void removeAll()
+    {
+        try
+        {
+            for ( int i = 0; i < noWaits.length; i++ )
+            {
+                noWaits[i].removeAll();
+            }
+        }
+        catch ( Exception ex )
+        {
+            log.error( ex );
+        }
+    }
+
+    /** Adds a dispose request to the remote cache. */
+    public void dispose()
+    {
+        try
+        {
+            for ( int i = 0; i < noWaits.length; i++ )
+            {
+                noWaits[i].dispose();
+            }
+        }
+        catch ( Exception ex )
+        {
+            log.error( "Problem in dispose.", ex );
+        }
+    }
+
+    /**
+     * No remote invocation.
+     * <p>
+     * @return The size value
+     */
+    public int getSize()
+    {
+        return 0;
+        // cache.getSize();
+    }
+
+    /**
+     * Gets the cacheType attribute of the RemoteCacheNoWaitFacade object.
+     * <p>
+     * @return The cacheType value
+     */
+    public int getCacheType()
+    {
+        return ICacheType.REMOTE_CACHE;
+    }
+
+    /**
+     * Gets the cacheName attribute of the RemoteCacheNoWaitFacade object.
+     * <p>
+     * @return The cacheName value
+     */
+    public String getCacheName()
+    {
+        return remoteCacheAttributes.getCacheName();
+    }
+
+    /**
+     * Gets the status attribute of the RemoteCacheNoWaitFacade object
+     * <p>
+     * Return ALIVE if any are alive.
+     * <p>
+     * @return The status value
+     */
+    public int getStatus()
+    {
+        for ( int i = 0; i < noWaits.length; i++ )
+        {
+            if ( noWaits[i].getStatus() == CacheConstants.STATUS_ALIVE )
+            {
+                return CacheConstants.STATUS_ALIVE;
+            }
+        }
+        return 0;
+    }
+
+    /**
+     * String form of some of the configuration information for the remote cache.
+     * <p>
+     * @return Some info for logging.
+     */
+    public String toString()
+    {
+        return "RemoteCacheNoWaitFacade: " + cacheName + ", rca = " + remoteCacheAttributes;
+    }
+
+    /**
+     * Begin the failover process if this is a local cache. Clustered remote caches do not failover.
+     * <p>
+     * @param i The no wait in error.
+     */
+    abstract void failover( int i );
+    
+
+    /**
+     * @return Returns the AuxiliaryCacheAttributes.
+     */
+    public AuxiliaryCacheAttributes getAuxiliaryCacheAttributes()
+    {
+        return this.remoteCacheAttributes;
+    }
+
+    /**
+     * getStats
+     * @return String
+     */
+    public String getStats()
+    {
+        return getStatistics().toString();
+    }
+
+    /**
+     * @return statistics about the cache region
+     */
+    public IStats getStatistics()
+    {
+        IStats stats = new Stats();
+        stats.setTypeName( "Remote Cache No Wait Facade" );
+
+        ArrayList elems = new ArrayList();
+
+        IStatElement se = null;
+
+        if ( noWaits != null )
+        {
+            se = new StatElement();
+            se.setName( "Number of No Waits" );
+            se.setData( "" + noWaits.length );
+            elems.add( se );
+
+            for ( int i = 0; i < noWaits.length; i++ )
+            {
+                // get the stats from the super too
+                // get as array, convert to list, add list to our outer list
+                IStats sStats = noWaits[i].getStatistics();
+                IStatElement[] sSEs = sStats.getStatElements();
+                List sL = Arrays.asList( sSEs );
+                elems.addAll( sL );
+            }
+        }
+
+        // get an array and put them in the Stats object
+        IStatElement[] ses = (IStatElement[]) elems.toArray( new StatElement[0] );
+        stats.setStatElements( ses );
+
+        return stats;
+    }
+
+    /**
+     * This typically returns end point info .
+     * <p>
+     * @return the name
+     */
+    public String getEventLoggingExtraInfo()
+    {
+        return "Remote Cache No Wait Facade";
+    }
+    
+    /**
+     * Gets the remoteCacheAttributes attribute of the RemoteCacheNoWaitFacade object
+     * <p>
+     * @return The remoteCacheAttributes value
+     */
+    public IRemoteCacheAttributes getRemoteCacheAttributes()
+    {
+        return remoteCacheAttributes;
+    }
+
+    /**
+     * Sets the remoteCacheAttributes attribute of the RemoteCacheNoWaitFacade object.
+     * <p>
+     * @param rca The new remoteCacheAttributes value
+     */
+    public void setRemoteCacheAttributes( IRemoteCacheAttributes rca )
+    {
+        this.remoteCacheAttributes = rca;
+    }
+
+    /**
+     * @param compositeCacheManager the compositeCacheManager to set
+     */
+    protected void setCompositeCacheManager( ICompositeCacheManager compositeCacheManager )
+    {
+        this.compositeCacheManager = compositeCacheManager;
+    }
+
+    /**
+     * @return the compositeCacheManager
+     */
+    protected ICompositeCacheManager getCompositeCacheManager()
+    {
+        return compositeCacheManager;
+    }
+}

Modified: jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/RemoteCache.java
URL: http://svn.apache.org/viewvc/jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/RemoteCache.java?rev=726149&r1=726148&r2=726149&view=diff
==============================================================================
--- jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/RemoteCache.java (original)
+++ jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/remote/RemoteCache.java Fri Dec 12 15:37:22 2008
@@ -20,40 +20,19 @@
  */
 
 import java.io.IOException;
-import java.io.Serializable;
-import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
+import java.util.Arrays;
+import java.util.List;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.jcs.auxiliary.AbstractAuxiliaryCacheEventLogging;
-import org.apache.jcs.auxiliary.AuxiliaryCacheAttributes;
 import org.apache.jcs.auxiliary.remote.behavior.IRemoteCacheAttributes;
-import org.apache.jcs.auxiliary.remote.behavior.IRemoteCacheClient;
 import org.apache.jcs.auxiliary.remote.behavior.IRemoteCacheListener;
 import org.apache.jcs.auxiliary.remote.behavior.IRemoteCacheService;
-import org.apache.jcs.engine.CacheConstants;
-import org.apache.jcs.engine.behavior.ICacheElement;
-import org.apache.jcs.engine.behavior.ICacheElementSerialized;
-import org.apache.jcs.engine.behavior.IElementAttributes;
-import org.apache.jcs.engine.behavior.IElementSerializer;
-import org.apache.jcs.engine.behavior.IZombie;
-import org.apache.jcs.engine.logging.behavior.ICacheEventLogger;
 import org.apache.jcs.engine.stats.StatElement;
 import org.apache.jcs.engine.stats.Stats;
 import org.apache.jcs.engine.stats.behavior.IStatElement;
 import org.apache.jcs.engine.stats.behavior.IStats;
-import org.apache.jcs.utils.serialization.SerializationConversionUtil;
-import org.apache.jcs.utils.threadpool.ThreadPool;
-import org.apache.jcs.utils.threadpool.ThreadPoolManager;
-
-import EDU.oswego.cs.dl.util.concurrent.Callable;
-import EDU.oswego.cs.dl.util.concurrent.FutureResult;
-import EDU.oswego.cs.dl.util.concurrent.TimeoutException;
 
 /**
  * Client proxy for an RMI remote cache.
@@ -62,8 +41,7 @@
  * encountered.
  */
 public class RemoteCache
-    extends AbstractAuxiliaryCacheEventLogging
-    implements IRemoteCacheClient
+    extends AbstractRemoteAuxiliaryCache
 {
     /** Don't change. */
     private static final long serialVersionUID = -5329231850422826460L;
@@ -71,27 +49,6 @@
     /** The logger. */
     private final static Log log = LogFactory.getLog( RemoteCache.class );
 
-    /** The cacheName */
-    final String cacheName;
-
-    /** The configuration values. */
-    private IRemoteCacheAttributes irca;
-
-    /** This is a handle on the remote server. In zombie mode it is replaced with a balking facade. */
-    private IRemoteCacheService remote;
-
-    /** The listener */
-    private IRemoteCacheListener listener;
-
-    /** Default element attributes */
-    private IElementAttributes attr = null;
-
-    /** A thread pool for gets if configured. */
-    private ThreadPool pool = null;
-
-    /** Should we get asynchronously using a pool. */
-    private boolean usePoolForGet = false;
-
     /**
      * Constructor for the RemoteCache object. This object communicates with a remote cache server.
      * One of these exists for each region. This also holds a reference to a listener. The same
@@ -104,408 +61,9 @@
      */
     public RemoteCache( IRemoteCacheAttributes cattr, IRemoteCacheService remote, IRemoteCacheListener listener )
     {
-        this.irca = cattr;
-        this.cacheName = cattr.getCacheName();
-        this.remote = remote;
-        this.listener = listener;
-
-        if ( log.isDebugEnabled() )
-        {
-            log.debug( "Construct> cacheName=" + cattr.getCacheName() );
-            log.debug( "irca = " + irca );
-            log.debug( "remote = " + remote );
-            log.debug( "listener = " + listener );
-        }
-
-        // use a pool if it is greater than 0
-        if ( log.isDebugEnabled() )
-        {
-            log.debug( "GetTimeoutMillis() = " + irca.getGetTimeoutMillis() );
-        }
-
-        if ( irca.getGetTimeoutMillis() > 0 )
-        {
-            pool = ThreadPoolManager.getInstance().getPool( irca.getThreadPoolName() );
-            if ( log.isDebugEnabled() )
-            {
-                log.debug( "Thread Pool = " + pool );
-            }
-            if ( pool != null )
-            {
-                usePoolForGet = true;
-            }
-        }
-
-        RemoteUtils.configureGlobalCustomSocketFactory( irca.getRmiSocketFactoryTimeoutMillis() );
-    }
-
-    /**
-     * Sets the attributes attribute of the RemoteCache object.
-     * <p>
-     * @param attr The new attributes value
-     */
-    public void setElementAttributes( IElementAttributes attr )
-    {
-        this.attr = attr;
-    }
-
-    /**
-     * Gets the attributes attribute of the RemoteCache object.
-     * <p>
-     * @return The attributes value
-     */
-    public IElementAttributes getElementAttributes()
-    {
-        return this.attr;
-    }
-
-    /**
-     * Serializes the object and then calls update on the remote server with the byte array. The
-     * byte array is wrapped in a ICacheElementSerialized. This allows the remote server to operate
-     * without any knowledge of caches classes.
-     * <p>
-     * @param ce
-     * @throws IOException
-     */
-    protected void processUpdate( ICacheElement ce )
-        throws IOException
-    {
-        if ( !this.irca.getGetOnly() )
-        {
-            ICacheElementSerialized serialized = null;
-            try
-            {
-                if ( log.isDebugEnabled() )
-                {
-                    log.debug( "sending item to remote server" );
-                }
-
-                // convert so we don't have to know about the object on the
-                // other end.
-                serialized = SerializationConversionUtil.getSerializedCacheElement( ce, this.elementSerializer );
-
-                remote.update( serialized, getListenerId() );
-            }
-            catch ( NullPointerException npe )
-            {
-                log.error( "npe for ce = " + ce + "ce.attr = " + ce.getElementAttributes(), npe );
-            }
-            catch ( Exception ex )
-            {
-                // event queue will wait and retry
-                handleException( ex, "Failed to put [" + ce.getKey() + "] to " + ce.getCacheName(),
-                                 ICacheEventLogger.UPDATE_EVENT );
-            }
-        }
-        else
-        {
-            if ( log.isDebugEnabled() )
-            {
-                log.debug( "get only mode, not sending to remote server" );
-            }
-        }
-    }
-
-    /**
-     * Synchronously get from the remote cache; if failed, replace the remote handle with a zombie.
-     * <p>
-     * Use threadpool to timeout if a value is set for GetTimeoutMillis
-     * <p>
-     * If we are a cluster client, we need to leave the Element in its serialized form. Cluster
-     * clients cannot deserialize objects. Cluster clients get ICacheElementSerialized objects from
-     * other remote servers.
-     * <p>
-     * @param key
-     * @return ICacheElement, a wrapper around the key, value, and attributes
-     * @throws IOException
-     */
-    protected ICacheElement processGet( Serializable key )
-        throws IOException
-    {
-        ICacheElement retVal = null;
-        try
-        {
-            if ( usePoolForGet )
-            {
-                retVal = getUsingPool( key );
-            }
-            else
-            {
-                retVal = remote.get( cacheName, key, getListenerId() );
-            }
-
-            // Eventually the instance of will not be necessary.
-            if ( retVal != null && retVal instanceof ICacheElementSerialized )
-            {
-                // Never try to deserialize if you are a cluster client. Cluster
-                // clients are merely intra-remote cache communicators. Remote caches are assumed
-                // to have no ability to deserialze the objects.
-                if ( this.irca.getRemoteType() != IRemoteCacheAttributes.CLUSTER )
-                {
-                    retVal = SerializationConversionUtil.getDeSerializedCacheElement( (ICacheElementSerialized) retVal,
-                                                                                      this.elementSerializer );
-                }
-            }
-        }
-        catch ( Exception ex )
-        {
-            handleException( ex, "Failed to get [" + key + "] from [" + cacheName + "]", ICacheEventLogger.GET_EVENT );
-        }
-        return retVal;
-    }
-
-    /**
-     * Calls get matching on the server. Each entry in the result is unwrapped.
-     * <p>
-     * @param pattern
-     * @return Map
-     * @throws IOException
-     */
-    public Map processGetMatching( String pattern )
-        throws IOException
-    {
-        Map results = new HashMap();
-        try
-        {
-            Map rawResults = remote.getMatching( cacheName, pattern, getListenerId() );
-
-            // Eventually the instance of will not be necessary.
-            if ( rawResults != null )
-            {
-                Set entrySet = rawResults.entrySet();
-                Iterator it = entrySet.iterator();
-                while ( it.hasNext() )
-                {
-                    Map.Entry entry = (Map.Entry) it.next();
-                    ICacheElement unwrappedResult = null;
-                    if ( entry.getValue() instanceof ICacheElementSerialized )
-                    {
-                        // Never try to deserialize if you are a cluster client. Cluster
-                        // clients are merely intra-remote cache communicators. Remote caches are assumed
-                        // to have no ability to deserialze the objects.
-                        if ( this.irca.getRemoteType() != IRemoteCacheAttributes.CLUSTER )
-                        {
-                            unwrappedResult = SerializationConversionUtil
-                                .getDeSerializedCacheElement( (ICacheElementSerialized) entry.getValue(),
-                                                              this.elementSerializer );
-                        }
-                    }
-                    else
-                    {
-                        unwrappedResult = (ICacheElement) entry.getValue();
-                    }
-                    results.put( entry.getKey(), unwrappedResult );
-                }
-            }
-        }
-        catch ( Exception ex )
-        {
-            handleException( ex, "Failed to getMatching [" + pattern + "] from [" + cacheName + "]",
-                             ICacheEventLogger.GET_EVENT );
-        }
-        return results;
-    }
-
-    /**
-     * Gets multiple items from the cache based on the given set of keys.
-     * <p>
-     * @param keys
-     * @return a map of Serializable key to ICacheElement element, or an empty map if there is no
-     *         data in cache for any of these keys
-     * @throws IOException
-     */
-    protected Map processGetMultiple( Set keys )
-        throws IOException
-    {
-        Map elements = new HashMap();
-        if ( keys != null && !keys.isEmpty() )
-        {
-            Iterator iterator = keys.iterator();
-
-            while ( iterator.hasNext() )
-            {
-                Serializable key = (Serializable) iterator.next();
-
-                ICacheElement element = get( key );
-
-                if ( element != null )
-                {
-                    elements.put( key, element );
-                }
-            }
-        }
-        return elements;
-    }
-
-    /**
-     * This allows gets to timeout in case of remote server machine shutdown.
-     * <p>
-     * @param key
-     * @return ICacheElement
-     * @throws IOException
-     */
-    public ICacheElement getUsingPool( final Serializable key )
-        throws IOException
-    {
-        int timeout = irca.getGetTimeoutMillis();
-
-        try
-        {
-            FutureResult future = new FutureResult();
-            Runnable command = future.setter( new Callable()
-            {
-                public Object call()
-                    throws IOException
-                {
-                    return remote.get( cacheName, key, getListenerId() );
-                }
-            } );
-
-            // execute using the pool
-            pool.execute( command );
-
-            // used timed get in order to timeout
-            ICacheElement ice = (ICacheElement) future.timedGet( timeout );
-            if ( log.isDebugEnabled() )
-            {
-                if ( ice == null )
-                {
-                    log.debug( "nothing found in remote cache" );
-                }
-                else
-                {
-                    log.debug( "found item in remote cache" );
-                }
-            }
-            return ice;
-        }
-        catch ( TimeoutException te )
-        {
-            log.warn( "TimeoutException, Get Request timed out after " + timeout );
-            throw new IOException( "Get Request timed out after " + timeout );
-        }
-        catch ( InterruptedException ex )
-        {
-            log.warn( "InterruptedException, Get Request timed out after " + timeout );
-            throw new IOException( "Get Request timed out after " + timeout );
-        }
-        catch ( InvocationTargetException ex )
-        {
-            // assume that this is an IOException thrown by the callable.
-            log.error( "InvocationTargetException, Assuming an IO exception thrown in the background.", ex );
-            throw new IOException( "Get Request timed out after " + timeout );
-        }
-    }
-
-    /**
-     * Returns all the keys for a group.
-     * <p>
-     * @param groupName
-     * @return Set
-     * @throws java.rmi.RemoteException
-     */
-    public Set getGroupKeys( String groupName )
-        throws java.rmi.RemoteException
-    {
-        return remote.getGroupKeys( cacheName, groupName );
-    }
-
-    /**
-     * Synchronously remove from the remote cache; if failed, replace the remote handle with a
-     * zombie.
-     * <p>
-     * @param key
-     * @return boolean, whether or not the item was removed
-     * @throws IOException
-     */
-    protected boolean processRemove( Serializable key )
-        throws IOException
-    {
-        if ( !this.irca.getGetOnly() )
-        {
-            if ( log.isDebugEnabled() )
-            {
-                log.debug( "remove> key=" + key );
-            }
-            try
-            {
-                remote.remove( cacheName, key, getListenerId() );
-            }
-            catch ( Exception ex )
-            {
-                handleException( ex, "Failed to remove " + key + " from " + cacheName, ICacheEventLogger.REMOVE_EVENT );
-            }
-            return true;
-        }
-        return false;
-    }
+        super( cattr, remote, listener );
 
-    /**
-     * Synchronously removeAll from the remote cache; if failed, replace the remote handle with a
-     * zombie.
-     * <p>
-     * @throws IOException
-     */
-    protected void processRemoveAll()
-        throws IOException
-    {
-        if ( !this.irca.getGetOnly() )
-        {
-            try
-            {
-                remote.removeAll( cacheName, getListenerId() );
-            }
-            catch ( Exception ex )
-            {
-                handleException( ex, "Failed to remove all from " + cacheName, ICacheEventLogger.REMOVEALL_EVENT );
-            }
-        }
-    }
-
-    /**
-     * Synchronously dispose the remote cache; if failed, replace the remote handle with a zombie.
-     * <p>
-     * @throws IOException
-     */
-    protected void processDispose()
-        throws IOException
-    {
-        if ( log.isInfoEnabled() )
-        {
-            log.info( "Disposing of remote cache." );
-        }
-        try
-        {
-            if ( listener != null )
-            {
-                listener.dispose();
-            }
-        }
-        catch ( Exception ex )
-        {
-            log.error( "Couldn't dispose", ex );
-            handleException( ex, "Failed to dispose [" + cacheName + "]", ICacheEventLogger.DISPOSE_EVENT );
-        }
-    }
-
-    /**
-     * Returns the cache status. An error status indicates the remote connection is not available.
-     * <p>
-     * @return The status value
-     */
-    public int getStatus()
-    {
-        return remote instanceof IZombie ? CacheConstants.STATUS_ERROR : CacheConstants.STATUS_ALIVE;
-    }
-
-    /**
-     * Gets the stats attribute of the RemoteCache object.
-     * <p>
-     * @return The stats value
-     */
-    public String getStats()
-    {
-        return getStatistics().toString();
+        RemoteUtils.configureGlobalCustomSocketFactory( getRemoteCacheAttributes().getRmiSocketFactoryTimeoutMillis() );
     }
 
     /**
@@ -527,41 +85,20 @@
 
         se = new StatElement();
         se.setName( "Remote Type" );
-        se.setData( this.irca.getRemoteTypeName() + "" );
+        se.setData( this.getRemoteCacheAttributes().getRemoteTypeName() + "" );
         elems.add( se );
 
-        if ( this.irca.getRemoteType() == IRemoteCacheAttributes.CLUSTER )
+        if ( this.getRemoteCacheAttributes().getRemoteType() == IRemoteCacheAttributes.CLUSTER )
         {
             // something cluster specific
         }
 
-        // no data gathered here
-
-        se = new StatElement();
-        se.setName( "UsePoolForGet" );
-        se.setData( "" + usePoolForGet );
-        elems.add( se );
-
-        if ( pool != null )
-        {
-            se = new StatElement();
-            se.setName( "Pool Size" );
-            se.setData( "" + pool.getPool().getPoolSize() );
-            elems.add( se );
-
-            se = new StatElement();
-            se.setName( "Maximum Pool Size" );
-            se.setData( "" + pool.getPool().getMaximumPoolSize() );
-            elems.add( se );
-        }
-
-        if ( remote instanceof ZombieRemoteCacheService )
-        {
-            se = new StatElement();
-            se.setName( "Zombie Queue Size" );
-            se.setData( "" + ( (ZombieRemoteCacheService) remote ).getQueueSize() );
-            elems.add( se );
-        }
+        // get the stats from the super too
+        // get as array, convert to list, add list to our outer list
+        IStats sStats = super.getStatistics();
+        IStatElement[] sSEs = sStats.getStatElements();
+        List sL = Arrays.asList( sSEs );
+        elems.addAll( sL );
 
         // get an array and put them in the Stats object
         IStatElement[] ses = (IStatElement[]) elems.toArray( new StatElement[0] );
@@ -571,70 +108,6 @@
     }
 
     /**
-     * Returns the current cache size.
-     * @return The size value
-     */
-    public int getSize()
-    {
-        return 0;
-    }
-
-    /**
-     * Gets the cacheType attribute of the RemoteCache object
-     * @return The cacheType value
-     */
-    public int getCacheType()
-    {
-        return REMOTE_CACHE;
-    }
-
-    /**
-     * Gets the cacheName attribute of the RemoteCache object.
-     * <p>
-     * @return The cacheName value
-     */
-    public String getCacheName()
-    {
-        return cacheName;
-    }
-
-    /**
-     * Replaces the current remote cache service handle with the given handle. If the current remote
-     * is a Zombie, the propagate teh events that may be queued to the restored service.
-     * <p>
-     * @param restoredRemote IRemoteCacheService -- the remote server or proxy to the remote server
-     */
-    public void fixCache( IRemoteCacheService restoredRemote )
-    {
-        if ( this.remote != null && this.remote instanceof ZombieRemoteCacheService )
-        {
-            ZombieRemoteCacheService zombie = (ZombieRemoteCacheService) this.remote;
-            this.remote = restoredRemote;
-            try
-            {
-                zombie.propagateEvents( restoredRemote );
-            }
-            catch ( Exception e )
-            {
-                try
-                {
-                    handleException( e, "Problem propagating events from Zombie Queue to new Remote Service.",
-                                     "fixCache" );
-                }
-                catch ( IOException e1 )
-                {
-                    // swallow, since this is just expected kick back.  Handle always throws
-                }
-            }
-        }
-        else
-        {
-            this.remote = restoredRemote;
-        }
-        return;
-    }
-
-    /**
      * Handles exception by disabling the remote cache service before re-throwing the exception in
      * the form of an IOException.
      * <p>
@@ -643,7 +116,7 @@
      * @param eventName
      * @throws IOException
      */
-    private void handleException( Exception ex, String msg, String eventName )
+    protected void handleException( Exception ex, String msg, String eventName )
         throws IOException
     {
         String message = "Disabling remote cache due to error: " + msg;
@@ -652,10 +125,10 @@
         log.error( message, ex );
 
         // we should not switch if the existing is a zombie.
-        if ( remote == null || !( remote instanceof ZombieRemoteCacheService ) )
+        if ( getRemoteCacheService() == null || !( getRemoteCacheService() instanceof ZombieRemoteCacheService ) )
         {
             // TODO make configurable
-            remote = new ZombieRemoteCacheService( irca.getZombieQueueMaxSize() );
+            setRemoteCacheService( new ZombieRemoteCacheService( getRemoteCacheAttributes().getZombieQueueMaxSize() ) );
         }
         // may want to flush if region specifies
         // Notify the cache monitor about the error, and kick off the recovery
@@ -664,7 +137,7 @@
 
         // initiate failover if local
         RemoteCacheNoWaitFacade rcnwf = (RemoteCacheNoWaitFacade) RemoteCacheFactory.getFacades()
-            .get( irca.getCacheName() );
+            .get( getRemoteCacheAttributes().getCacheName() );
 
         if ( log.isDebugEnabled() )
         {
@@ -690,111 +163,13 @@
     }
 
     /**
-     * @return Returns the AuxiliaryCacheAttributes.
-     */
-    public AuxiliaryCacheAttributes getAuxiliaryCacheAttributes()
-    {
-        return irca;
-    }
-
-    /**
-     * let the remote cache set a listener_id. Since there is only one listener for all the regions
-     * and every region gets registered? the id shouldn't be set if it isn't zero. If it is we
-     * assume that it is a reconnect.
-     * <p>
-     * @param id The new listenerId value
-     */
-    public void setListenerId( long id )
-    {
-        try
-        {
-            listener.setListenerId( id );
-
-            if ( log.isDebugEnabled() )
-            {
-                log.debug( "set listenerId = " + id );
-            }
-        }
-        catch ( Exception e )
-        {
-            log.error( "Problem setting listenerId", e );
-        }
-    }
-
-    /**
-     * Gets the listenerId attribute of the RemoteCacheListener object
-     * @return The listenerId value
-     */
-    public long getListenerId()
-    {
-        if ( listener != null )
-        {
-            try
-            {
-                if ( log.isDebugEnabled() )
-                {
-                    log.debug( "get listenerId = " + listener.getListenerId() );
-                }
-                return listener.getListenerId();
-            }
-            catch ( Exception e )
-            {
-                log.error( "Problem getting listenerId", e );
-            }
-        }
-        return -1;
-    }
-
-    /**
-     * Allows other member of this package to access the listerner. This is mainly needed for
-     * deregistering a listener.
-     * <p>
-     * @return IRemoteCacheListener, the listener for this remote server
-     */
-    public IRemoteCacheListener getListener()
-    {
-        return listener;
-    }
-
-    /**
-     * Never sets to null;
-     * <p>
-     * @param elementSerializer The elementSerializer to set.
-     */
-    public void setElementSerializer( IElementSerializer elementSerializer )
-    {
-        if ( elementSerializer != null )
-        {
-            this.elementSerializer = elementSerializer;
-        }
-    }
-
-    /**
-     * @return Returns the elementSerializer.
-     */
-    public IElementSerializer getElementSerializer()
-    {
-        return elementSerializer;
-    }
-
-    /**
-     * Allows it to be injected.
-     * <p>
-     * @param cacheEventLogger
-     */
-    public void setCacheEventLogger( ICacheEventLogger cacheEventLogger )
-    {
-        this.cacheEventLogger = cacheEventLogger;
-    }
-
-    /**
      * Debugging info.
      * <p>
      * @return basic info about the RemoteCache
      */
     public String toString()
     {
-        return "RemoteCache: " + cacheName + " attributes = " + irca;
+        return "RemoteCache: " + cacheName + " attributes = " + getRemoteCacheAttributes();
     }
 
     /**
@@ -816,7 +191,8 @@
      */
     protected String getIPAddressForService()
     {
-        String ipAddress = this.irca.getRemoteHost() + ":" + this.irca.getRemotePort();
+        String ipAddress = this.getRemoteCacheAttributes().getRemoteHost() + ":"
+            + this.getRemoteCacheAttributes().getRemotePort();
         return ipAddress;
     }
 }