You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wink.apache.org by el...@apache.org on 2009/08/30 11:48:47 UTC
svn commit: r809287 - in
/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal:
providers/header/ registry/ utils/
Author: elman
Date: Sun Aug 30 09:48:46 2009
New Revision: 809287
URL: http://svn.apache.org/viewvc?rev=809287&view=rev
Log:
Cache parsed Accept header content where possible
See [WINK-114]
Added:
incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/SimpleConcurrentMap.java (with props)
incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/SimpleMap.java (with props)
incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/SoftConcurrentMap.java (with props)
Modified:
incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/header/AcceptHeaderDelegate.java
incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/header/MediaTypeHeaderDelegate.java
incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/registry/ProvidersRegistry.java
Modified: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/header/AcceptHeaderDelegate.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/header/AcceptHeaderDelegate.java?rev=809287&r1=809286&r2=809287&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/header/AcceptHeaderDelegate.java (original)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/header/AcceptHeaderDelegate.java Sun Aug 30 09:48:46 2009
@@ -27,11 +27,19 @@
import javax.ws.rs.ext.RuntimeDelegate.HeaderDelegate;
import org.apache.wink.common.internal.http.Accept;
+import org.apache.wink.common.internal.utils.SoftConcurrentMap;
import org.apache.wink.common.internal.utils.StringUtils;
public class AcceptHeaderDelegate implements HeaderDelegate<Accept> {
+ private static final SoftConcurrentMap<String, Accept> cache = new SoftConcurrentMap<String, Accept>();
+
public Accept fromString(String value) throws IllegalArgumentException {
+ Accept cached = cache.get(value);
+ if (cached != null) {
+ return cached;
+ }
+
// if there is no Accept header it means that all media types are
// acceptable
if (value == null) {
@@ -46,7 +54,7 @@
}
list.add(MediaType.valueOf(mediaRange));
}
- return new Accept(list);
+ return cache.put(value, new Accept(list));
}
public String toString(Accept value) {
Modified: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/header/MediaTypeHeaderDelegate.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/header/MediaTypeHeaderDelegate.java?rev=809287&r1=809286&r2=809287&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/header/MediaTypeHeaderDelegate.java (original)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/header/MediaTypeHeaderDelegate.java Sun Aug 30 09:48:46 2009
@@ -27,21 +27,31 @@
import javax.ws.rs.ext.RuntimeDelegate.HeaderDelegate;
import org.apache.wink.common.internal.i18n.Messages;
+import org.apache.wink.common.internal.utils.SoftConcurrentMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MediaTypeHeaderDelegate implements HeaderDelegate<MediaType> {
- private static final Logger logger = LoggerFactory.getLogger(MediaTypeHeaderDelegate.class);
- private static final Pattern EQUALS = Pattern.compile("=");
- private static final Pattern SEMICOLON = Pattern.compile(";");
- private static final Pattern SLASH = Pattern.compile("/");
+ private static final Logger logger =
+ LoggerFactory
+ .getLogger(MediaTypeHeaderDelegate.class);
+ private static final Pattern EQUALS = Pattern.compile("=");
+ private static final Pattern SEMICOLON = Pattern.compile(";");
+ private static final Pattern SLASH = Pattern.compile("/");
+ private static final SoftConcurrentMap<String, MediaType> cache =
+ new SoftConcurrentMap<String, MediaType>();
public MediaType fromString(String value) throws IllegalArgumentException {
if (value == null) {
throw new IllegalArgumentException("MediaType header is null");
}
-
+
+ MediaType cached = cache.get(value);
+ if (cached != null) {
+ return cached;
+ }
+
String type = "*";
String subType = "*";
Map<String, String> paramsMap = null;
@@ -68,7 +78,7 @@
throw new IllegalArgumentException(errMsg, e);
}
- return new MediaType(type, subType, paramsMap);
+ return cache.put(value, new MediaType(type, subType, paramsMap));
}
public String toString(MediaType value) {
Modified: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/registry/ProvidersRegistry.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/registry/ProvidersRegistry.java?rev=809287&r1=809286&r2=809287&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/registry/ProvidersRegistry.java (original)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/registry/ProvidersRegistry.java Sun Aug 30 09:48:46 2009
@@ -35,8 +35,6 @@
import java.util.Set;
import java.util.TreeSet;
import java.util.Map.Entry;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -56,6 +54,8 @@
import org.apache.wink.common.internal.lifecycle.LifecycleManagersRegistry;
import org.apache.wink.common.internal.lifecycle.ObjectFactory;
import org.apache.wink.common.internal.utils.GenericsUtils;
+import org.apache.wink.common.internal.utils.SimpleConcurrentMap;
+import org.apache.wink.common.internal.utils.SimpleMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -395,12 +395,12 @@
private abstract class MediaTypeMap<T> {
- private final Map<MediaType, Set<ObjectFactory<T>>> data =
- new LinkedHashMap<MediaType, Set<ObjectFactory<T>>>();
- private final Class<?> rawType;
+ private final Map<MediaType, Set<ObjectFactory<T>>> data =
+ new LinkedHashMap<MediaType, Set<ObjectFactory<T>>>();
+ private final Class<?> rawType;
- private Map<Class<?>, SoftReference<ConcurrentMap<MediaType, List<ObjectFactory<T>>>>> providersCache =
- new ConcurrentHashMap<Class<?>, SoftReference<ConcurrentMap<MediaType, List<ObjectFactory<T>>>>>();
+ private final SimpleMap<Class<?>, SoftReference<SimpleMap<MediaType, List<ObjectFactory<T>>>>> providersCache =
+ new SimpleConcurrentMap<Class<?>, SoftReference<SimpleMap<MediaType, List<ObjectFactory<T>>>>>(); ;
public MediaTypeMap(Class<?> rawType) {
super();
@@ -421,19 +421,19 @@
mediaType = new MediaType(type, subtype);
}
- SoftReference<ConcurrentMap<MediaType, List<ObjectFactory<T>>>> mediaTypeToProvidersCacheRef =
+ SoftReference<SimpleMap<MediaType, List<ObjectFactory<T>>>> mediaTypeToProvidersCacheRef =
providersCache.get(cls);
- ConcurrentMap<MediaType, List<ObjectFactory<T>>> mediaTypeToProvidersCache = null;
+ SimpleMap<MediaType, List<ObjectFactory<T>>> mediaTypeToProvidersCache = null;
if (mediaTypeToProvidersCacheRef != null) {
mediaTypeToProvidersCache = mediaTypeToProvidersCacheRef.get();
}
if (mediaTypeToProvidersCache == null) {
mediaTypeToProvidersCache =
- new ConcurrentHashMap<MediaType, List<ObjectFactory<T>>>();
+ new SimpleConcurrentMap<MediaType, List<ObjectFactory<T>>>();
providersCache
.put(cls,
- new SoftReference<ConcurrentMap<MediaType, List<ObjectFactory<T>>>>(
- mediaTypeToProvidersCache));
+ new SoftReference<SimpleMap<MediaType, List<ObjectFactory<T>>>>(
+ mediaTypeToProvidersCache));
}
List<ObjectFactory<T>> list = mediaTypeToProvidersCache.get(mediaType);
Added: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/SimpleConcurrentMap.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/SimpleConcurrentMap.java?rev=809287&view=auto
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/SimpleConcurrentMap.java (added)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/SimpleConcurrentMap.java Sun Aug 30 09:48:46 2009
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * 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.wink.common.internal.utils;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+/**
+ * <p>
+ * Concurrent implementation of the SimpleMap interface. The idea behind this
+ * implementation that get is called more frequently than put or clear,
+ * therefore ReentrantReadWriteLock is used: get is read operation, while put
+ * and clear are write operations.
+ *
+ * @param <K>
+ * @param <V>
+ * @see java.util.concurrent.locks.ReentrantReadWriteLock
+ */
+public class SimpleConcurrentMap<K, V> implements SimpleMap<K, V> {
+
+ private final Lock readersLock;
+ private final Lock writersLock;
+ private final Map<K, V> map;
+
+ public SimpleConcurrentMap() {
+ this(new HashMap<K, V>());
+ }
+
+ /**
+ * Provides the map implementation. Pay attention that get method is
+ * synchronized using the read lock, therefore it must not change the
+ * entire collection.
+ *
+ * @param map
+ */
+ public SimpleConcurrentMap(Map<K, V> map) {
+ this.map = map;
+ ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
+ readersLock = readWriteLock.readLock();
+ writersLock = readWriteLock.writeLock();
+ }
+
+ public V get(K key) {
+ readersLock.lock();
+ try {
+ return map.get(key);
+ } finally {
+ readersLock.unlock();
+ }
+ }
+
+ public V put(K key, V val) {
+ writersLock.lock();
+ try {
+ return map.put(key, val);
+ } finally {
+ writersLock.unlock();
+ }
+ }
+
+ public void clear() {
+ writersLock.lock();
+ try {
+ map.clear();
+ } finally {
+ writersLock.unlock();
+ }
+ }
+}
Propchange: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/SimpleConcurrentMap.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/SimpleMap.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/SimpleMap.java?rev=809287&view=auto
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/SimpleMap.java (added)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/SimpleMap.java Sun Aug 30 09:48:46 2009
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * 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.wink.common.internal.utils;
+
+/**
+ * Simplified definition of the Map with only three operations: get, put and
+ * clear.
+ * <p>
+ * Pay attention that the method may behave slightly differently from the
+ * methods define by the Map interface, therefore it's recommended you always
+ * check the javadoc of the implementing class.
+ */
+public interface SimpleMap<K, V> {
+
+ /**
+ * Returns the value to which this map maps the specified key. Returns
+ * <tt>null</tt> if the map contains no mapping for this key. A return value
+ * of <tt>null</tt> does not <i>necessarily</i> indicate that the map
+ * contains no mapping for the key; it's also possible that the map
+ * explicitly maps the key to <tt>null</tt>.
+ */
+ V get(K key);
+
+ /**
+ * Associates the specified value with the specified key in this map. If the
+ * map previously contained a mapping for this key, the old value is
+ * replaced by the specified value.
+ */
+ V put(K key, V value);
+
+ /**
+ * Removes all mappings from this map (optional operation).
+ */
+ void clear();
+}
Propchange: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/SimpleMap.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/SoftConcurrentMap.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/SoftConcurrentMap.java?rev=809287&view=auto
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/SoftConcurrentMap.java (added)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/SoftConcurrentMap.java Sun Aug 30 09:48:46 2009
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * 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.wink.common.internal.utils;
+
+import java.lang.ref.SoftReference;
+import java.util.Map;
+import java.util.WeakHashMap;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+/**
+ * Concurrent implementation of the SimpleMap interface. This implementation is
+ * intend to be used by soft caches, therefore the keys are kept in WeakHashMap,
+ * while the value is kept using the SoftReference.
+ * <p>
+ * Pay attention that put value always returns the current value and not the
+ * original value. It was done to allow the following code pattern:
+ * <pre>
+ * SoftConcurrentMap<K, V> cache = new SoftConcurrentMap<K, V>();
+ * V cached = cache.get(key);
+ * return cached =! null ? cached : cache.put(createValue());
+ * </pre>
+ * @param <K>
+ * @param <V>
+ */
+public class SoftConcurrentMap<K, V> implements SimpleMap<K, V> {
+
+ private final Lock readersLock;
+ private final Lock writersLock;
+ private final Map<K, SoftReference<V>> map;
+
+ /**
+ * Provides the map implementation. Pay attention that get method is
+ * synchronized using the read lock, therefore it must not change the entire
+ * collection.
+ *
+ * @param map
+ */
+ public SoftConcurrentMap() {
+ this.map = new WeakHashMap<K, SoftReference<V>>();
+ ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
+ readersLock = readWriteLock.readLock();
+ writersLock = readWriteLock.writeLock();
+ }
+
+ public V get(K key) {
+ readersLock.lock();
+ try {
+ SoftReference<V> softReference = map.get(key);
+ return softReference != null ? softReference.get() : null;
+ } finally {
+ readersLock.unlock();
+ }
+ }
+
+ /**
+ * Associates the specified value with the specified key in this map. If the
+ * map previously contained a mapping for this key, the old value is
+ * replaced by the specified value.
+ * <p>
+ * Unlike the regular Map.put method, this method returns the current value
+ * and not the previous value.
+ *
+ * @return val - the current value.
+ */
+ public V put(K key, V val) {
+ writersLock.lock();
+ try {
+ map.put(key, new SoftReference<V>(val));
+ return val;
+ } finally {
+ writersLock.unlock();
+ }
+ }
+
+ public void clear() {
+ writersLock.lock();
+ try {
+ map.clear();
+ } finally {
+ writersLock.unlock();
+ }
+ }
+
+}
Propchange: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/SoftConcurrentMap.java
------------------------------------------------------------------------------
svn:eol-style = native