This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-commons-cache-impl.git
commit 014d71c02ef7606f60c9ccb8bdf47b8bba1a39e7 Author: Ian Boston <[email protected]> AuthorDate: Fri Nov 9 05:22:15 2012 +0000 SLING-2555 moving into the right place this time, sorry. git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1407364 13f79535-47bb-0310-9956-ffa450edef68 --- README.txt | 12 ++ pom.xml | 69 ++++++++ .../cache/impl/AbstractCacheManagerService.java | 194 +++++++++++++++++++++ .../sling/commons/cache/impl/MapCacheImpl.java | 119 +++++++++++++ .../sling/commons/cache/impl/MapDeligate.java | 87 +++++++++ .../commons/cache/impl/ThreadLocalCacheMap.java | 43 +++++ 6 files changed, 524 insertions(+) diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..4664850 --- /dev/null +++ b/README.txt @@ -0,0 +1,12 @@ +Support Jar for implementations of CacheManagerService. + +This is support jar for implementing Cache services. It contains an abstract implementation of all the in +memory versions of cache that the cache service has to supply leaving instance, cluster invalidated and cluster +replicated caches upto the supporting cache library. + + +Acknowledgments + +This code was based on a module from Sparse Content Map 29 September 2012 (git:sha1:a222df1937434ad3f07bf6c4f60b19524a158bcb), which itself was based on a snapshot of a +module in Sakai Nakamura 27 Jan 2011 (git:sha1:b9d8e65b733ec7c35a3d194c9a5dc12acf13cb34). All know contributors to code in this module have been +contacted for permission to grant license to the Apache Foundation. \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..5acbc20 --- /dev/null +++ b/pom.xml @@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.sling</groupId> + <artifactId>sling</artifactId> + <version>13</version> + <relativePath>../../../parent/pom.xml</relativePath> + </parent> + + <artifactId>org.apache.sling.commons.cache.impl</artifactId> + <version>0.1-SNAPSHOT</version> + <packaging>jar</packaging> + + <name>Apache Sling Cache API Implementation support library</name> + <description> + This bundle provides an implementation support for Cache implementations. It is a utility jar that should be embedded. + </description> + + <scm> + <connection>scm:svn:http://svn.apache.org/repos/asf/sling/whiteboard/ieb/cache/impl</connection> + <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/whiteboard/ieb/cache/impl</developerConnection> + <url>http://svn.apache.org/viewvc/sling/whiteboard/ieb/cache/impl</url> + </scm> + + + <dependencies> + <dependency> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.commons.cache.api</artifactId> + <version>0.1-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + <version>1.4</version> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + </dependency> + + </dependencies> +</project> diff --git a/src/main/java/org/apache/sling/commons/cache/impl/AbstractCacheManagerService.java b/src/main/java/org/apache/sling/commons/cache/impl/AbstractCacheManagerService.java new file mode 100644 index 0000000..c5542f1 --- /dev/null +++ b/src/main/java/org/apache/sling/commons/cache/impl/AbstractCacheManagerService.java @@ -0,0 +1,194 @@ +/* + * 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.sling.commons.cache.impl; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; + +import org.apache.commons.io.IOUtils; +import org.apache.sling.commons.cache.api.Cache; +import org.apache.sling.commons.cache.api.CacheManagerService; +import org.apache.sling.commons.cache.api.CacheScope; + +/** + * The <code>AbstractCacheManagerService</code> + */ +public abstract class AbstractCacheManagerService implements CacheManagerService { + + + private ThreadLocalCacheMap requestCacheMapHolder = new ThreadLocalCacheMap(); + private ThreadLocalCacheMap threadCacheMapHolder = new ThreadLocalCacheMap(); + + public AbstractCacheManagerService() throws IOException { + } + + + + /** + * {@inheritDoc} + * + * @see org.apache.sling.commons.cache.api.CacheManagerService#getCache(java.lang.String) + */ + public <V> Cache<V> getCache(String name, CacheScope scope) { + switch (scope) { + case INSTANCE: + return getInstanceCache(name); + case CLUSTERINVALIDATED: + return getInstanceCache(name); + case CLUSTERREPLICATED: + return getInstanceCache(name); + case REQUEST: + return getRequestCache(name); + case THREAD: + return getThreadCache(name); + default: + return getInstanceCache(name); + } + } + + + + /** + * Generate a cache bound to the thread. + * + * @param name + * @return + */ + @SuppressWarnings("unchecked") + protected <V> Cache<V> getThreadCache(String name) { + Map<String, Cache<?>> threadCacheMap = threadCacheMapHolder.get(); + Cache<V> threadCache = (Cache<V>) threadCacheMap.get(name); + if (threadCache == null) { + threadCache = new MapCacheImpl<V>(); + threadCacheMap.put(name, threadCache); + } + return threadCache; + } + + /** + * Generate a cache bound to the request + * + * @param name + * @return + */ + @SuppressWarnings("unchecked") + protected <V> Cache<V> getRequestCache(String name) { + Map<String, Cache<?>> requestCacheMap = requestCacheMapHolder.get(); + Cache<V> requestCache = (Cache<V>) requestCacheMap.get(name); + if (requestCache == null) { + requestCache = new MapCacheImpl<V>(); + requestCacheMap.put(name, requestCache); + } + return requestCache; + } + + /** + * @param name + * @return + */ + protected abstract <V> Cache<V> getInstanceCache(String name); + + /** + * {@inheritDoc} + * + * @see org.apache.sling.commons.cache.api.CacheManagerService#unbind(org.apache.sling.commons.cache.api.CacheScope) + */ + public void unbind(CacheScope scope) { + switch (scope) { + case REQUEST: + unbindRequest(); + break; + case THREAD: + unbindThread(); + break; + default: + break; + } + } + + /** + * + */ + private void unbindThread() { + Map<String, Cache<?>> threadCache = threadCacheMapHolder.get(); + for (Cache<?> cache : threadCache.values()) { + cache.clear(); + } + threadCacheMapHolder.remove(); + } + + /** + * + */ + private void unbindRequest() { + Map<String, Cache<?>> requestCache = requestCacheMapHolder.get(); + for (Cache<?> cache : requestCache.values()) { + cache.clear(); + } + requestCacheMapHolder.remove(); + } + + + protected String toString(Object object, String defaultValue) { + if (object == null) { + return defaultValue; + } + return String.valueOf(object); + } + + + protected InputStream processConfig(InputStream in, + Map<String, Object> properties) throws IOException { + if (in == null) { + return null; + } + StringBuilder config = new StringBuilder(IOUtils.toString(in, "UTF-8")); + in.close(); + int pos = 0; + for (;;) { + int start = config.indexOf("${", pos); + if (start < 0) { + break; + } + int end = config.indexOf("}", start); + if (end < 0) { + throw new IllegalArgumentException( + "Config file malformed, unterminated variable " + + config.substring(start, + Math.min(start + 10, config.length()))); + } + String key = config.substring(start + 2, end); + if (properties.containsKey(key)) { + String replacement = (String) properties.get(key); + config.replace(start, end + 1, replacement); + pos = start + replacement.length(); + } else { + throw new IllegalArgumentException( + "Missing replacement property " + key); + } + } + return new ByteArrayInputStream(config.toString().getBytes("UTF-8")); + + } + + +} diff --git a/src/main/java/org/apache/sling/commons/cache/impl/MapCacheImpl.java b/src/main/java/org/apache/sling/commons/cache/impl/MapCacheImpl.java new file mode 100644 index 0000000..51f8c29 --- /dev/null +++ b/src/main/java/org/apache/sling/commons/cache/impl/MapCacheImpl.java @@ -0,0 +1,119 @@ +/* + * 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.sling.commons.cache.impl; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Set; + +import org.apache.sling.commons.cache.api.Cache; +import org.apache.sling.commons.cache.api.ThreadBound; + +/** + * + */ +public class MapCacheImpl<V> extends HashMap<String, V> implements Cache<V> { + + /** + * + */ + private static final long serialVersionUID = -5400056532743570231L; + + /** + * {@inheritDoc} + * + * @see org.apache.sling.commons.cache.api.Cache#containsKey(java.lang.String) + */ + public boolean containsKey(String key) { + return super.containsKey(key); + } + + /** + * {@inheritDoc} + * + * @see org.apache.sling.commons.cache.api.Cache#get(java.lang.String) + */ + public V get(String key) { + return super.get(key); + } + + /** + * {@inheritDoc} + * + * @see org.apache.sling.commons.cache.api.Cache#remove(java.lang.String) + */ + public boolean remove(String key) { + V o = super.remove(key); + if (o instanceof ThreadBound) { + ((ThreadBound) o).unbind(); + } + return ( o != null ); + } + + /** + * {@inheritDoc} + * + * @see java.util.HashMap#clear() + */ + @Override + public void clear() { + for (String k : super.keySet()) { + Object o = get(k); + if (o instanceof ThreadBound) { + ((ThreadBound) o).unbind(); + } + } + super.clear(); + } + + /** + * {@inheritDoc} + * + * @see org.apache.sling.commons.cache.api.Cache#removeChildren(java.lang.String) + */ + public void removeChildren(String key) { + super.remove(key); + if (!key.endsWith("/")) { + key = key + "/"; + } + Set<String> keys = super.keySet(); + for (String k : keys) { + if ((k).startsWith(key)) { + super.remove(k); + } + } + } + + /** + * {@inheritDoc} + * + * @see org.apache.sling.commons.cache.api.Cache#list() + */ + public Collection<V> values() { + return super.values(); + } + + public Collection<String> keys() { + return super.keySet(); + } + +} diff --git a/src/main/java/org/apache/sling/commons/cache/impl/MapDeligate.java b/src/main/java/org/apache/sling/commons/cache/impl/MapDeligate.java new file mode 100644 index 0000000..a54b030 --- /dev/null +++ b/src/main/java/org/apache/sling/commons/cache/impl/MapDeligate.java @@ -0,0 +1,87 @@ +/* + * 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.sling.commons.cache.impl; + +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +import org.apache.sling.commons.cache.api.Cache; + +public class MapDeligate<K, V> implements Map<K, V> { + + private Cache<V> cache; + + public MapDeligate(Cache<V> cache) { + this.cache = cache; + } + + public void clear() { + cache.clear(); + } + + public boolean containsKey(Object key) { + return cache.containsKey((java.lang.String) key); + } + + public boolean containsValue(Object value) { + throw new UnsupportedOperationException("This map is lookup only."); + } + + public Set<Entry<K, V>> entrySet() { + throw new UnsupportedOperationException("This map is lookup only."); + } + + public V get(Object key) { + return cache.get((String) key); + } + + public boolean isEmpty() { + return false; + } + + public Set<K> keySet() { + throw new UnsupportedOperationException("This map is lookup only."); + } + + public V put(K key, V value) { + return cache.put((String) key, value); + } + + public void putAll(Map<? extends K, ? extends V> m) { + throw new UnsupportedOperationException( + "This map is singly add only, use an iterator or loop."); + } + + public int size() { + throw new UnsupportedOperationException("This map is lookup only."); + } + + public V remove(Object key) { + V value = cache.get((String) key); + cache.remove((String) key); + return value; + } + + public Collection<V> values() { + throw new UnsupportedOperationException("This map is lookup only."); + } + +} diff --git a/src/main/java/org/apache/sling/commons/cache/impl/ThreadLocalCacheMap.java b/src/main/java/org/apache/sling/commons/cache/impl/ThreadLocalCacheMap.java new file mode 100644 index 0000000..8d70c77 --- /dev/null +++ b/src/main/java/org/apache/sling/commons/cache/impl/ThreadLocalCacheMap.java @@ -0,0 +1,43 @@ +/* + * 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.sling.commons.cache.impl; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.sling.commons.cache.api.Cache; + +/** + * Represents a Cache stored on the thread, used in the request thread and in + * other threads. When used in Threads there is a potential for memory leaks as + * perm space is not cleaned up. This will be caused by references to + * classloaders being in the Map, and keeping the classloaders open. + */ +public class ThreadLocalCacheMap extends ThreadLocal<Map<String, Cache<?>>> { + /** + * {@inheritDoc} + * + * @see java.lang.ThreadLocal#initialValue() + */ + @Override + protected Map<String, Cache<?>> initialValue() { + return new HashMap<String, Cache<?>>(); + } +} -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
