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