Merge branch commons-jcs-2.2.x back into trunk
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/jcs/trunk@1840421 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/remote/server/RegistryKeepAliveRunner.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/remote/server/RegistryKeepAliveRunner.java
index fe82a3b..3b8beed 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/remote/server/RegistryKeepAliveRunner.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/remote/server/RegistryKeepAliveRunner.java
@@ -20,6 +20,7 @@
*/
import java.rmi.Naming;
+import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.Registry;
@@ -41,12 +42,18 @@
/** The URL of the service to look for. */
private String namingURL;
+ /** The service name. */
+ private String serviceName;
+
/** the port on which to start the registry */
private int registryPort;
/** An optional event logger */
private ICacheEventLogger cacheEventLogger;
+ /** the registry */
+ private Registry registry;
+
/**
* @param registryHost - Hostname of the registry
* @param registryPort - the port on which to start the registry
@@ -55,6 +62,7 @@
public RegistryKeepAliveRunner( String registryHost, int registryPort, String serviceName )
{
this.namingURL = RemoteUtils.getNamingURL(registryHost, registryPort, serviceName);
+ this.serviceName = serviceName;
this.registryPort = registryPort;
}
@@ -104,41 +112,42 @@
{
cacheEventLogger.logError( "RegistryKeepAliveRunner", "Naming.lookup", message + ":" + ex.getMessage() );
}
- createAndRegister( namingURL );
+ createAndRegister( serviceName );
}
}
/**
* Creates the registry and registers the server.
* <p>
- * @param registry
+ * @param serviceName the service name
*/
- protected void createAndRegister( String registry )
+ protected void createAndRegister( String serviceName )
{
- createReqistry( registry );
- registerServer( registry );
+ createReqistry( serviceName );
+ registerServer( serviceName );
}
/**
* Try to create the registry. Log errors
* <p>
- * @param registry
+ * @param serviceName the service name
*/
- protected void createReqistry( String registry )
+ protected void createReqistry( String serviceName )
{
- Registry reg = RemoteUtils.createRegistry(registryPort);
+ // TODO: Refactor method signature. This is ugly but required to keep the binary API compatibility
+ this.registry = RemoteUtils.createRegistry(registryPort);
if ( cacheEventLogger != null )
{
- if (reg != null)
+ if (this.registry != null)
{
cacheEventLogger.logApplicationEvent( "RegistryKeepAliveRunner", "createRegistry",
- "Successfully created registry [" + registry + "]." );
+ "Successfully created registry [" + serviceName + "]." );
}
else
{
cacheEventLogger.logError( "RegistryKeepAliveRunner", "createRegistry",
- "Could not start registry [" + registry + "]." );
+ "Could not start registry [" + serviceName + "]." );
}
}
}
@@ -146,15 +155,22 @@
/**
* Try to rebind the server.
* <p>
- * @param registry
+ * @param serviceName the service name
*/
- protected void registerServer( String registry )
+ protected void registerServer( String serviceName )
{
try
{
// try to rebind anyway
- RemoteCacheServerFactory.registerServer( registry, RemoteCacheServerFactory.getRemoteCacheServer() );
- String message = "Successfully rebound server to registry [" + registry + "].";
+ Remote server = RemoteCacheServerFactory.getRemoteCacheServer();
+
+ if ( server == null )
+ {
+ throw new RemoteException( "Cannot register the server until it is created." );
+ }
+
+ this.registry.rebind( serviceName, server );
+ String message = "Successfully rebound server to registry [" + serviceName + "].";
if ( cacheEventLogger != null )
{
cacheEventLogger.logApplicationEvent( "RegistryKeepAliveRunner", "registerServer", message );
@@ -166,7 +182,7 @@
}
catch ( RemoteException e )
{
- String message = "Could not rebind server to registry [" + registry + "].";
+ String message = "Could not rebind server to registry [" + serviceName + "].";
log.error( message, e );
if ( cacheEventLogger != null )
{
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/remote/server/RemoteCacheServerAttributes.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/remote/server/RemoteCacheServerAttributes.java
index 351f5ac..45a0a72 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/remote/server/RemoteCacheServerAttributes.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/remote/server/RemoteCacheServerAttributes.java
@@ -143,6 +143,7 @@
* Should we start the registry
* <p>
* @param startRegistry the startRegistry to set
+ * @deprecated Always true, to be removed
*/
@Override
public void setStartRegistry( boolean startRegistry )
@@ -154,6 +155,7 @@
* Should we start the registry
* <p>
* @return the startRegistry
+ * @deprecated Always true, to be removed
*/
@Override
public boolean isStartRegistry()
@@ -201,7 +203,6 @@
buf.append( "\n allowClusterGet = [" + this.isAllowClusterGet() + "]" );
buf.append( "\n configFileName = [" + this.getConfigFileName() + "]" );
buf.append( "\n rmiSocketFactoryTimeoutMillis = [" + this.getRmiSocketFactoryTimeoutMillis() + "]" );
- buf.append( "\n startRegistry = [" + this.isStartRegistry() + "]" );
buf.append( "\n useRegistryKeepAlive = [" + this.isUseRegistryKeepAlive() + "]" );
buf.append( "\n registryKeepAliveDelayMillis = [" + this.getRegistryKeepAliveDelayMillis() + "]" );
buf.append( "\n eventQueueType = [" + this.getEventQueueType() + "]" );
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/remote/server/RemoteCacheServerFactory.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/remote/server/RemoteCacheServerFactory.java
index e0c616e..60a0fa0 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/remote/server/RemoteCacheServerFactory.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/remote/server/RemoteCacheServerFactory.java
@@ -149,13 +149,10 @@
remoteCacheServer.setCacheEventLogger( cacheEventLogger );
// START THE REGISTRY
- if (rcsa.isStartRegistry())
- {
- registry = RemoteUtils.createRegistry(port);
- }
+ registry = RemoteUtils.createRegistry(port);
// REGISTER THE SERVER
- registerServer( RemoteUtils.getNamingURL(host, port, serviceName), remoteCacheServer );
+ registerServer( serviceName, remoteCacheServer );
// KEEP THE REGISTRY ALIVE
if ( rcsa.isUseRegistryKeepAlive() )
@@ -227,11 +224,11 @@
* Registers the server with the registry. I broke this off because we might want to have code
* that will restart a dead registry. It will need to rebind the server.
* <p>
- * @param namingURL
- * @param server
+ * @param serviceName the name of the service
+ * @param server the server object to bind
* @throws RemoteException
*/
- protected static void registerServer( String namingURL, Remote server )
+ protected static void registerServer(String serviceName, Remote server )
throws RemoteException
{
if ( server == null )
@@ -239,20 +236,17 @@
throw new RemoteException( "Cannot register the server until it is created." );
}
- if ( log.isInfoEnabled() )
+ if ( registry == null )
{
- log.info( "Binding server to " + namingURL );
+ throw new RemoteException( "Cannot register the server: Registry is null." );
}
- try
+ if ( log.isInfoEnabled() )
{
- Naming.rebind( namingURL, server );
+ log.info( "Binding server to " + serviceName );
}
- catch ( MalformedURLException ex )
- {
- // impossible case.
- throw new IllegalArgumentException( ex.getMessage() + "; url=" + namingURL );
- }
+
+ registry.rebind( serviceName, server );
}
/**
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/remote/server/behavior/IRemoteCacheServerAttributes.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/remote/server/behavior/IRemoteCacheServerAttributes.java
index 1c8500d..5817e2d 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/remote/server/behavior/IRemoteCacheServerAttributes.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/remote/server/behavior/IRemoteCacheServerAttributes.java
@@ -89,6 +89,7 @@
* Should we start the registry
* <p>
* @param startRegistry the startRegistry to set
+ * @deprecated Always true, to be removed
*/
void setStartRegistry( boolean startRegistry );
@@ -96,6 +97,7 @@
* Should we start the registry
* <p>
* @return the startRegistry
+ * @deprecated Always true, to be removed
*/
boolean isStartRegistry();
diff --git a/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/ExpiryAwareCache.java b/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/ExpiryAwareCache.java
new file mode 100644
index 0000000..d4691ec
--- /dev/null
+++ b/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/ExpiryAwareCache.java
@@ -0,0 +1,61 @@
+/*
+ * 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.commons.jcs.jcache;
+
+import java.util.Arrays;
+import java.util.Map;
+
+import javax.cache.Cache;
+import javax.cache.configuration.CacheEntryListenerConfiguration;
+import javax.cache.event.CacheEntryEvent;
+import javax.cache.event.EventType;
+
+import org.apache.commons.jcs.engine.behavior.ICacheElement;
+import org.apache.commons.jcs.engine.behavior.ICompositeCacheAttributes;
+import org.apache.commons.jcs.engine.behavior.IElementAttributes;
+import org.apache.commons.jcs.engine.control.CompositeCache;
+
+// allows us to plug some lifecycle callbacks on the core cache without impacting too much the core
+public class ExpiryAwareCache<A, B> extends CompositeCache<A, B>
+{
+ private Map<CacheEntryListenerConfiguration<A, B>, JCSListener<A, B>> listeners;
+ private Cache<A, B> cacheRef;
+
+ ExpiryAwareCache(final ICompositeCacheAttributes cattr, final IElementAttributes attr)
+ {
+ super(cattr, attr);
+ }
+
+ @Override
+ protected void doExpires(final ICacheElement<A, B> element)
+ {
+ super.doExpires(element);
+ for (final JCSListener<A, B> listener : listeners.values())
+ {
+ listener.onExpired(Arrays.<CacheEntryEvent<? extends A, ? extends B>> asList(new JCSCacheEntryEvent<A, B>(
+ cacheRef, EventType.REMOVED, null, element.getKey(), element.getVal())));
+ }
+ }
+
+ void init(final Cache<A, B> cache, final Map<CacheEntryListenerConfiguration<A, B>, JCSListener<A, B>> listeners)
+ {
+ this.cacheRef = cache;
+ this.listeners = listeners;
+ }
+}
diff --git a/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/JCSCache.java b/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/JCSCache.java
index f5e13d6..baa1ff5 100644
--- a/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/JCSCache.java
+++ b/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/JCSCache.java
@@ -23,7 +23,6 @@
import org.apache.commons.jcs.engine.behavior.ICacheElement;
import org.apache.commons.jcs.engine.behavior.IElementAttributes;
import org.apache.commons.jcs.engine.behavior.IElementSerializer;
-import org.apache.commons.jcs.engine.control.CompositeCache;
import org.apache.commons.jcs.jcache.jmx.JCSCacheMXBean;
import org.apache.commons.jcs.jcache.jmx.JCSCacheStatisticsMXBean;
import org.apache.commons.jcs.jcache.jmx.JMXs;
@@ -71,7 +70,7 @@
// TODO: configure serializer
public class JCSCache<K, V> implements Cache<K, V>
{
- private final CompositeCache<K, V> delegate;
+ private final ExpiryAwareCache<K, V> delegate;
private final JCSCachingManager manager;
private final JCSConfiguration<K, V> config;
private final CacheLoader<K, V> loader;
@@ -89,7 +88,7 @@
public JCSCache(final ClassLoader classLoader, final JCSCachingManager mgr,
final String cacheName, final JCSConfiguration<K, V> configuration,
- final Properties properties, final CompositeCache<K, V> cache)
+ final Properties properties, final ExpiryAwareCache<K, V> cache)
{
manager = mgr;
@@ -153,6 +152,7 @@
{
listeners.put(listener, new JCSListener<K, V>(listener));
}
+ delegate.init(this, listeners);
statistics.setActive(config.isStatisticsEnabled());
@@ -307,7 +307,7 @@
}
else
{
- expires(key);
+ forceExpires(key);
}
}
}
@@ -401,7 +401,7 @@
{
if (!created)
{
- expires(key);
+ forceExpires(key);
}
}
}
@@ -411,7 +411,7 @@
return duration == null || !duration.isZero();
}
- private void expires(final K cacheKey)
+ private void forceExpires(final K cacheKey)
{
final ICacheElement<K, V> elt = delegate.get(cacheKey);
delegate.remove(cacheKey);
@@ -549,7 +549,7 @@
final Duration expiryForAccess = expiryPolicy.getExpiryForAccess();
if (!isNotZero(expiryForAccess))
{
- expires(key);
+ forceExpires(key);
}
else if (expiryForAccess != null && (!elt.getElementAttributes().getIsEternal() || !expiryForAccess.isEternal()))
{
diff --git a/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/JCSCachingManager.java b/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/JCSCachingManager.java
index 2357005..c764eb3 100644
--- a/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/JCSCachingManager.java
+++ b/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/JCSCachingManager.java
@@ -18,6 +18,10 @@
*/
package org.apache.commons.jcs.jcache;
+import org.apache.commons.jcs.engine.behavior.ICompositeCacheAttributes;
+import org.apache.commons.jcs.engine.behavior.IElementAttributes;
+import org.apache.commons.jcs.engine.control.CompositeCache;
+import org.apache.commons.jcs.engine.control.CompositeCacheConfigurator;
import org.apache.commons.jcs.engine.control.CompositeCacheManager;
import org.apache.commons.jcs.jcache.lang.Subsitutor;
import org.apache.commons.jcs.jcache.proxy.ClassLoaderAwareCache;
@@ -65,6 +69,19 @@
return new InternalManager();
}
+ protected CompositeCacheConfigurator newConfigurator()
+ {
+ return new CompositeCacheConfigurator()
+ {
+ @Override
+ protected <K, V> CompositeCache<K, V> newCache(
+ final ICompositeCacheAttributes cca, final IElementAttributes ea)
+ {
+ return new ExpiryAwareCache<K, V>( cca, ea );
+ }
+ };
+ }
+
@Override // needed to call it from JCSCachingManager
protected void initialize() {
super.initialize();
@@ -197,7 +214,7 @@
loader, this, cacheName,
new JCSConfiguration/*<K, V>*/(configuration, keyType, valueType),
properties,
- delegate.getCache(cacheName)));
+ ExpiryAwareCache.class.cast(delegate.getCache(cacheName))));
caches.putIfAbsent(cacheName, cache);
}
else
diff --git a/commons-jcs-jcache/src/test/java/org/apache/commons/jcs/jcache/ExpiryListenerTest.java b/commons-jcs-jcache/src/test/java/org/apache/commons/jcs/jcache/ExpiryListenerTest.java
new file mode 100644
index 0000000..1ac2cc1
--- /dev/null
+++ b/commons-jcs-jcache/src/test/java/org/apache/commons/jcs/jcache/ExpiryListenerTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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.commons.jcs.jcache;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.concurrent.TimeUnit;
+
+import javax.cache.Cache;
+import javax.cache.CacheManager;
+import javax.cache.Caching;
+import javax.cache.configuration.FactoryBuilder;
+import javax.cache.configuration.MutableCacheEntryListenerConfiguration;
+import javax.cache.configuration.MutableConfiguration;
+import javax.cache.event.CacheEntryEvent;
+import javax.cache.event.CacheEntryExpiredListener;
+import javax.cache.event.CacheEntryListenerException;
+import javax.cache.expiry.CreatedExpiryPolicy;
+import javax.cache.expiry.Duration;
+import javax.cache.expiry.ExpiryPolicy;
+import javax.cache.spi.CachingProvider;
+
+import org.junit.Test;
+
+public class ExpiryListenerTest {
+
+ @Test
+ public void listener() throws InterruptedException {
+ final CachingProvider cachingProvider = Caching.getCachingProvider();
+ final CacheManager cacheManager = cachingProvider.getCacheManager();
+ final CacheEntryExpiredListenerImpl listener = new CacheEntryExpiredListenerImpl();
+ cacheManager.createCache("default", new MutableConfiguration<String, String>()
+ .setExpiryPolicyFactory(new FactoryBuilder.SingletonFactory<ExpiryPolicy>(
+ new CreatedExpiryPolicy(new Duration(TimeUnit.MILLISECONDS, 1))))
+ .addCacheEntryListenerConfiguration(new MutableCacheEntryListenerConfiguration<String, String>(
+ FactoryBuilder.factoryOf(listener),
+ null, false, false
+ )));
+ final Cache<String, String> cache = cacheManager.getCache("default");
+ assertFalse(cache.containsKey("foo"));
+ cache.put("foo", "bar");
+ Thread.sleep(10);
+ assertFalse(cache.containsKey("foo"));
+ cachingProvider.close();
+ assertEquals(1, listener.events.size());
+ }
+
+ private static class CacheEntryExpiredListenerImpl implements CacheEntryExpiredListener<String, String>, Serializable {
+ private final Collection<CacheEntryEvent<? extends String, ? extends String>> events =
+ new ArrayList<CacheEntryEvent<? extends String, ? extends String>>();
+
+ @Override
+ public void onExpired(final Iterable<CacheEntryEvent<? extends String, ? extends String>> cacheEntryEvents)
+ throws CacheEntryListenerException {
+ for (final CacheEntryEvent<? extends String, ? extends String> cacheEntryEvent : cacheEntryEvents) {
+ events.add(cacheEntryEvent);
+ }
+ }
+ }
+}