[jboss-svn-commits] JBoss Common SVN: r2517 - in common-core/trunk/src/main/java/org/jboss/util: builder and 1 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Tue Aug 28 06:52:18 EDT 2007


Author: adrian at jboss.org
Date: 2007-08-28 06:52:18 -0400 (Tue, 28 Aug 2007)
New Revision: 2517

Added:
   common-core/trunk/src/main/java/org/jboss/util/builder/
   common-core/trunk/src/main/java/org/jboss/util/builder/AbstractBuilder.java
   common-core/trunk/src/main/java/org/jboss/util/collection/WeakTypeCache.java
Modified:
   common-core/trunk/src/main/java/org/jboss/util/collection/WeakValueHashMap.java
Log:
[JBCOMMON-31] - Collections from the Microcontainer project

Added: common-core/trunk/src/main/java/org/jboss/util/builder/AbstractBuilder.java
===================================================================
--- common-core/trunk/src/main/java/org/jboss/util/builder/AbstractBuilder.java	                        (rev 0)
+++ common-core/trunk/src/main/java/org/jboss/util/builder/AbstractBuilder.java	2007-08-28 10:52:18 UTC (rev 2517)
@@ -0,0 +1,72 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2007, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.util.builder;
+
+import java.security.PrivilegedAction;
+
+/**
+ * AbstractBuilder.
+ * 
+ * @param <T> the type to be built
+ * @author <a href="adrian at jboss.org">Adrian Brock</a>
+ * @version $Revision: 1.1 $
+ */
+public class AbstractBuilder<T> implements PrivilegedAction<T>
+{
+   /** The factory class */
+   private Class<T> factoryClass;
+   
+   /** The default factory */
+   private String defaultFactory;
+   
+   /**
+    * Create a new AbstractBuilder.
+    * 
+    * @param factoryClass the factory class
+    * @param defaultFactory the default factory
+    * @throws IllegalArgumentException for a null parameter
+    */
+   public AbstractBuilder(Class<T> factoryClass, String defaultFactory)
+   {
+      if (factoryClass == null)
+         throw new IllegalArgumentException("Null factory class");
+      if (defaultFactory == null)
+         throw new IllegalArgumentException("Null default factory");
+      this.factoryClass = factoryClass;
+      this.defaultFactory = defaultFactory;
+   }
+   
+   public T run()
+   {
+      try
+      {
+         String className = System.getProperty(factoryClass.getName(), defaultFactory);
+         Class<?> clazz = Thread.currentThread().getContextClassLoader().loadClass(className);
+         Object object = clazz.newInstance();
+         return factoryClass.cast(object);
+      }
+      catch (Throwable t)
+      {
+         throw new RuntimeException("Error constructing " + factoryClass.getName(), t);
+      }
+   }
+}

Added: common-core/trunk/src/main/java/org/jboss/util/collection/WeakTypeCache.java
===================================================================
--- common-core/trunk/src/main/java/org/jboss/util/collection/WeakTypeCache.java	                        (rev 0)
+++ common-core/trunk/src/main/java/org/jboss/util/collection/WeakTypeCache.java	2007-08-28 10:52:18 UTC (rev 2517)
@@ -0,0 +1,301 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.util.collection;
+
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.GenericDeclaration;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.lang.reflect.WildcardType;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+/**
+ * A weak class cache that instantiates does not a hold a
+ * strong reference to either the classloader or class.<p>
+ * 
+ * It creates the class specific data in two stages
+ * to avoid recursion.<p>
+ * 
+ * instantiate - creates the data<br>
+ * generate - fills in the details
+ *
+ * @param <T> the cached type
+ * @author <a href="mailto:adrian at jboss.org">Adrian Brock</a>
+ */
+public abstract class WeakTypeCache<T>
+{
+   /** The cache */
+   private Map<ClassLoader, Map<String, T>> cache = new WeakHashMap<ClassLoader, Map<String, T>>(); 
+   
+   /**
+    * Get the information for a type
+    * 
+    * @param type the type
+    * @return the info
+    */
+   @SuppressWarnings("unchecked")
+   public T get(Type type)
+   {
+      if (type == null)
+         throw new IllegalArgumentException("Null type");
+
+      if (type instanceof ParameterizedType)
+         return getParameterizedType((ParameterizedType) type);
+      else if (type instanceof Class)
+         return getClass((Class<?>) type);
+      else if (type instanceof TypeVariable)
+         return getTypeVariable((TypeVariable) type);
+      else if (type instanceof GenericArrayType)
+         return getGenericArrayType((GenericArrayType) type);
+      else if (type instanceof WildcardType)
+         return getWildcardType((WildcardType) type);
+      else
+         throw new UnsupportedOperationException("Unknown type: " + type + " class=" + type.getClass());
+   }
+   
+   /**
+    * Get the information for a class
+    * 
+    * @param name the name
+    * @param cl the classloader
+    * @return the info
+    * @throws ClassNotFoundException when the class cannot be found
+    */
+   public T get(String name, ClassLoader cl) throws ClassNotFoundException
+   {
+      if (name == null)
+         throw new IllegalArgumentException("Null name");
+      if (cl == null)
+         throw new IllegalArgumentException("Null classloader");
+
+      Class<?> clazz = cl.loadClass(name);
+      return get(clazz);
+   }
+   
+   /**
+    * Instantiate for a class
+    * 
+    * @param clazz the class
+    * @return the result
+    */
+   protected abstract T instantiate(Class<?> clazz);
+   
+   /**
+    * Fill in the result
+    * 
+    * @param clazz the class
+    * @param result the result
+    */
+   protected abstract void generate(Class<?> clazz, T result);
+   
+   /**
+    * Instantiate for a parameterized type
+    * 
+    * @param type the parameterized type
+    * @return the result
+    */
+   protected abstract T instantiate(ParameterizedType type);
+   
+   /**
+    * Fill in the result
+    * 
+    * @param type the parameterized type
+    * @param result the result
+    */
+   protected abstract void generate(ParameterizedType type, T result);
+
+   /**
+    * Get the information for a parameterized type
+    * 
+    * @param type the paremeterized type
+    * @return the info
+    */
+   private T getParameterizedType(ParameterizedType type)
+   {
+      // First check if we already have it
+      T result = peek(type);
+      if (result != null)
+         return result;
+      
+      // Instantiate
+      result = instantiate(type);
+
+      // Put the perlimanary result into the cache
+      put(type, result);
+
+      // Generate the details
+      generate(type, result);
+      
+      return result;
+   }
+
+   /**
+    * Get the information for a wildcard type
+    * 
+    * @param type the paremeterized type
+    * @return the info
+    */
+   private T getWildcardType(WildcardType type)
+   {
+      // TODO JBMICROCONT-131 improve this
+      return get(type.getUpperBounds()[0]);
+   }
+
+   /**
+    * Get the information for a type variable
+    * 
+    * @param <D> the declaration
+    * @param type the type variable
+    * @return the info
+    */
+   private <D extends GenericDeclaration> T getTypeVariable(TypeVariable<D> type)
+   {
+      // TODO JBMICROCONT-131 improve this
+      return get(type.getBounds()[0]);
+   }
+
+   /**
+    * Get the information for an array type
+    * 
+    * @param type the array type
+    * @return the info
+    */
+   private T getGenericArrayType(GenericArrayType type)
+   {
+      // TODO JBMICROCONT-131 this needs implementing properly
+      return get(Object[].class);
+   }
+
+   /**
+    * Peek into the cache
+    * 
+    * @param type the type
+    * @return the value
+    */
+   private T peek(ParameterizedType type)
+   {
+      Class<?> rawType = (Class<?>) type.getRawType();
+      Map<String, T> classLoaderCache = getClassLoaderCache(rawType.getClassLoader());
+      
+      synchronized (classLoaderCache)
+      {
+         return classLoaderCache.get(type.toString());
+      }
+   }
+
+   /**
+    * Put a result into the cache
+    * 
+    * @param type the type
+    * @param result the value
+    */
+   private void put(ParameterizedType type, T result)
+   {
+      Class<?> rawType = (Class<?>) type.getRawType();
+      Map<String, T> classLoaderCache = getClassLoaderCache(rawType.getClassLoader());
+
+      synchronized (classLoaderCache)
+      {
+         // TODO JBMICROCONT-131 something better than toString()?
+         classLoaderCache.put(type.toString(), result);
+      }
+   }
+
+   /**
+    * Get the information for a class
+    * 
+    * @param clazz the class
+    * @return the info
+    */
+   private T getClass(Class<?> clazz)
+   {
+      // First check if we already have it
+      T result = peek(clazz);
+      if (result != null)
+         return result;
+
+      // Instantiate
+      result = instantiate(clazz);
+
+      // Put the perlimanary result into the cache
+      put(clazz, result);
+
+      // Generate the details
+      generate(clazz, result);
+      
+      return result;
+   }
+
+   /**
+    * Peek into the cache
+    * 
+    * @param clazz the class
+    * @return the value
+    */
+   private T peek(Class<?> clazz)
+   {
+      Map<String, T> classLoaderCache = getClassLoaderCache(clazz.getClassLoader());
+
+      synchronized (classLoaderCache)
+      {
+         return classLoaderCache.get(clazz.getName());
+      }
+   }
+
+   /**
+    * Put a result into the cache
+    * 
+    * @param clazz the class
+    * @param result the value
+    */
+   private void put(Class<?> clazz, T result)
+   {
+      Map<String, T> classLoaderCache = getClassLoaderCache(clazz.getClassLoader());
+
+      synchronized (classLoaderCache)
+      {
+         classLoaderCache.put(clazz.getName(), result);
+      }
+   }
+   
+   /**
+    * Get the cache for the classloader
+    * 
+    * @param cl the classloader
+    * @return the map
+    */
+   private Map<String, T> getClassLoaderCache(ClassLoader cl)
+   {
+      synchronized (cache)
+      {
+         Map<String, T> result = cache.get(cl);
+         if (result == null)
+         {
+            result = new WeakValueHashMap<String, T>();
+            cache.put(cl, result);
+         }
+         return result;
+      }
+   }
+}

Modified: common-core/trunk/src/main/java/org/jboss/util/collection/WeakValueHashMap.java
===================================================================
--- common-core/trunk/src/main/java/org/jboss/util/collection/WeakValueHashMap.java	2007-08-28 10:43:34 UTC (rev 2516)
+++ common-core/trunk/src/main/java/org/jboss/util/collection/WeakValueHashMap.java	2007-08-28 10:52:18 UTC (rev 2517)
@@ -21,73 +21,34 @@
   */
 package org.jboss.util.collection;
 
-import java.util.Map;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
 import java.util.AbstractMap;
+import java.util.AbstractSet;
 import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
 import java.util.Set;
 
-import java.lang.ref.WeakReference;
-import java.lang.ref.ReferenceQueue;
 
-
 /**
  * This Map will remove entries when the value in the map has been
  * cleaned from garbage collection
  *
+ * @param <K> the key type
+ * @param <V> the value type
+ * @author  <a href="mailto:bill at jboss.org">Bill Burke</a>
+ * @author  <a href="mailto:adrian at jboss.org">Adrian Brock</a>
  * @version <tt>$Revision$</tt>
- * @author  <a href="mailto:bill at jboss.org">Bill Burke</a>
  */
-public class WeakValueHashMap
-   extends AbstractMap
-   implements Map 
+public class WeakValueHashMap<K, V> extends AbstractMap<K, V> 
 {
-   private static class WeakValueRef extends WeakReference
-   {
-      public Object key;
+   /** Hash table mapping keys to weak values */
+   private Map<K, WeakValueRef<K, V>> hash;
 
-      private WeakValueRef(Object key, Object val, ReferenceQueue q)
-      {
-         super(val, q);
-         this.key = key;
-      }
-      
-      private static WeakValueRef create(Object key, Object val, ReferenceQueue q)
-      {
-         if (val == null) return null;
-         else return new WeakValueRef(key, val, q);
-      }
-      
-   }
-   public Set entrySet() 
-   { 
-      processQueue();
-      return hash.entrySet();
-   }
+   /** Reference queue for cleared WeakKeys */
+   private ReferenceQueue<V> queue = new ReferenceQueue<V>();
 
-   /* Hash table mapping WeakKeys to values */
-   private Map hash;
-
-   /* Reference queue for cleared WeakKeys */
-   private ReferenceQueue queue = new ReferenceQueue();
-   
-   /* Remove all invalidated entries from the map, that is, remove all entries
-      whose values have been discarded.  
-    */
-   private void processQueue()
-   {
-      WeakValueRef ref;
-      while ((ref = (WeakValueRef)queue.poll()) != null) {
-         if (ref == (WeakValueRef) hash.get(ref.key)) {
-            // only remove if it is the *exact* same WeakValueRef
-            //
-            hash.remove(ref.key);
-         }
-      }
-   }
-
-
-   /* -- Constructors -- */
-
    /**
     * Constructs a new, empty <code>WeakHashMap</code> with the given
     * initial capacity and the given load factor.
@@ -103,7 +64,7 @@
     */
    public WeakValueHashMap(int initialCapacity, float loadFactor)
    {
-      hash = new HashMap(initialCapacity, loadFactor);
+      hash = new HashMap<K, WeakValueRef<K, V>>(initialCapacity, loadFactor);
    }
 
    /**
@@ -119,7 +80,7 @@
     */
    public WeakValueHashMap(int initialCapacity)
    {
-      hash = new HashMap(initialCapacity);
+      hash = new HashMap<K, WeakValueRef<K, V>>(initialCapacity);
    }
 
    /**
@@ -129,7 +90,7 @@
     */
    public WeakValueHashMap()
    {
-      hash = new HashMap();
+      hash = new HashMap<K, WeakValueRef<K, V>>();
    }
 
    /**
@@ -140,109 +101,198 @@
     * <tt>0.75</tt>.
     *
     * @param   t the map whose mappings are to be placed in this map.
-    * @since	1.3
+    * @since    1.3
     */
-   public WeakValueHashMap(Map t)
+   public WeakValueHashMap(Map<K, V> t)
    {
       this(Math.max(2*t.size(), 11), 0.75f);
       putAll(t);
    }
 
-   /* -- Simple queries -- */
-
-   /**
-    * Returns the number of key-value mappings in this map.
-    * <strong>Note:</strong> <em>In contrast with most implementations of the
-    * <code>Map</code> interface, the time required by this operation is
-    * linear in the size of the map.</em>
-    */
+   @Override
    public int size()
    {
       processQueue();
       return hash.size();
    }
 
-   /**
-    * Returns <code>true</code> if this map contains no key-value mappings.
-    */
-   public boolean isEmpty()
+   @Override
+   public boolean containsKey(Object key)
    {
       processQueue();
-      return hash.isEmpty();
+      return hash.containsKey(key);
    }
 
-   /**
-    * Returns <code>true</code> if this map contains a mapping for the
-    * specified key.
-    *
-    * @param   key   The key whose presence in this map is to be tested
-    */
-   public boolean containsKey(Object key)
+   @Override
+   public V get(Object key)
    {
       processQueue();
-      return hash.containsKey(key);
+      WeakValueRef<K, V> ref = hash.get(key);
+      if (ref != null)
+         return ref.get();
+      return null;
    }
 
-   /* -- Lookup and modification operations -- */
+   @Override
+   public V put(K key, V value) 
+   {
+      processQueue();
+      WeakValueRef<K, V> ref = WeakValueRef.create(key, value, queue);
+      WeakValueRef<K, V> result = hash.put(key, ref);
+      if (result != null)
+         return result.get();
+      return null;
+   }
 
-   /**
-    * Returns the value to which this map maps the specified <code>key</code>.
-    * If this map does not contain a value for this key, then return
-    * <code>null</code>.
-    *
-    * @param  key  The key whose associated value, if any, is to be returned
-    */
-   public Object get(Object key)
+   @Override
+   public V remove(Object key) 
    {
       processQueue();
-      WeakReference ref = (WeakReference)hash.get(key);
-      if (ref != null) return ref.get();
+      WeakValueRef<K, V> result = hash.remove(key);
+      if (result != null)
+         return result.get();
       return null;
    }
+   
+   @Override
+   public Set<Entry<K,V>> entrySet() 
+   { 
+      processQueue();
+      return new EntrySet();
+   }
 
+   @Override
+   public void clear()
+   {
+      processQueue();
+      hash.clear();
+   }
+   
    /**
-    * Updates this map so that the given <code>key</code> maps to the given
-    * <code>value</code>.  If the map previously contained a mapping for
-    * <code>key</code> then that mapping is replaced and the previous value is
-    * returned.
-    *
-    * @param  key    The key that is to be mapped to the given
-    *                <code>value</code> 
-    * @param  value  The value to which the given <code>key</code> is to be
-    *                mapped
-    *
-    * @return  The previous value to which this key was mapped, or
-    *          <code>null</code> if if there was no mapping for the key
+    * Remove all entries whose values have been discarded.  
     */
-   public Object put(Object key, Object value) 
+   @SuppressWarnings("unchecked")
+   private void processQueue()
    {
-      processQueue();
-      Object rtn = hash.put(key, WeakValueRef.create(key, value, queue));
-      if (rtn != null) rtn = ((WeakReference)rtn).get();
-      return rtn;
+      WeakValueRef<K, V> ref = (WeakValueRef<K, V>) queue.poll();
+      while (ref != null)
+      {
+         // only remove if it is the *exact* same WeakValueRef
+         if (ref == hash.get(ref.key))
+            hash.remove(ref.key);
+         
+         ref = (WeakValueRef<K, V>) queue.poll();
+      }
    }
+   
+   /**
+    * EntrySet.
+    */
+   private class EntrySet extends AbstractSet<Entry<K, V>>
+   {
+      @Override
+      public Iterator<Entry<K, V>> iterator()
+      {
+         return new EntrySetIterator(hash.entrySet().iterator());
+      }
 
+      @Override
+      public int size()
+      {
+         return WeakValueHashMap.this.size();
+      }
+   }
+   
    /**
-    * Removes the mapping for the given <code>key</code> from this map, if
-    * present.
-    *
-    * @param  key  The key whose mapping is to be removed
-    *
-    * @return  The value to which this key was mapped, or <code>null</code> if
-    *          there was no mapping for the key
+    * EntrySet iterator
     */
-   public Object remove(Object key) 
+   private class EntrySetIterator implements Iterator<Entry<K, V>>
    {
-      processQueue();
-      return hash.remove(key);
+      /** The delegate */
+      private Iterator<Entry<K, WeakValueRef<K, V>>> delegate;
+      
+      /**
+       * Create a new EntrySetIterator.
+       * 
+       * @param delegate the delegate
+       */
+      public EntrySetIterator(Iterator<Entry<K, WeakValueRef<K, V>>> delegate)
+      {
+         this.delegate = delegate;
+      }
+
+      public boolean hasNext()
+      {
+         return delegate.hasNext();
+      }
+
+      public Entry<K, V> next()
+      {
+         Entry<K, WeakValueRef<K, V>> next = delegate.next();
+         return next.getValue();
+      }
+
+      public void remove()
+      {
+         throw new UnsupportedOperationException("remove");
+      }
    }
-
+   
    /**
-    * Removes all mappings from this map.
+    * WeakValueRef.
+    * 
+    * @param <K> the key type
+    * @param <V> the value type
     */
-   public void clear()
+   private static class WeakValueRef<K, V> extends WeakReference<V> implements Map.Entry<K, V>
    {
-      processQueue();
-      hash.clear();
+      /** The key */
+      public K key;
+
+      /**
+       * Safely create a new WeakValueRef
+       * 
+       * @param <K> the key type
+       * @param <V> the value type
+       * @param key the key
+       * @param val the value
+       * @param q the reference queue
+       * @return the reference or null if the value is null
+       */
+      private static <K, V> WeakValueRef<K, V> create(K key, V val, ReferenceQueue<V> q)
+      {
+         if (val == null)
+            return null;
+         else 
+            return new WeakValueRef<K, V>(key, val, q);
+      }
+
+      /**
+       * Create a new WeakValueRef.
+       * 
+       * @param key the key
+       * @param val the value
+       * @param q the reference queue
+       */
+      private WeakValueRef(K key, V val, ReferenceQueue<V> q)
+      {
+         super(val, q);
+         this.key = key;
+      }
+
+      public K getKey()
+      {
+         return key;
+      }
+
+      public V getValue()
+      {
+         return get();
+      }
+
+      public V setValue(V value)
+      {
+         throw new UnsupportedOperationException("setValue");
+      }
    }
 }




More information about the jboss-svn-commits mailing list