You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@turbine.apache.org by gk...@apache.org on 2021/09/08 13:19:24 UTC

[turbine-fulcrum-factory] 22/49: Add generics and use concurrent collections

This is an automated email from the ASF dual-hosted git repository.

gk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/turbine-fulcrum-factory.git

commit 65055553b6fbb56a1b18e1808550b295f6df5692
Author: Thomas Vandahl <tv...@apache.org>
AuthorDate: Sun Nov 27 11:44:21 2016 +0000

    Add generics and use concurrent collections
    
    git-svn-id: https://svn.apache.org/repos/asf/turbine/fulcrum/trunk/factory@1771565 13f79535-47bb-0310-9956-ffa450edef68
---
 .../fulcrum/factory/DefaultFactoryService.java     | 208 ++++++++++++++-------
 src/java/org/apache/fulcrum/factory/Factory.java   |  23 +--
 .../org/apache/fulcrum/factory/FactoryService.java |  16 +-
 .../factory/utils/ObjectInputStreamForContext.java |   9 +-
 .../apache/fulcrum/factory/FactoryServiceTest.java |   5 +-
 5 files changed, 166 insertions(+), 95 deletions(-)

diff --git a/src/java/org/apache/fulcrum/factory/DefaultFactoryService.java b/src/java/org/apache/fulcrum/factory/DefaultFactoryService.java
index 3034c19..f058372 100644
--- a/src/java/org/apache/fulcrum/factory/DefaultFactoryService.java
+++ b/src/java/org/apache/fulcrum/factory/DefaultFactoryService.java
@@ -21,11 +21,13 @@ package org.apache.fulcrum.factory;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
+import java.io.IOException;
 import java.io.ObjectOutputStream;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.Iterator;
+import java.util.concurrent.ConcurrentHashMap;
 
+import org.apache.avalon.framework.activity.Disposable;
 import org.apache.avalon.framework.activity.Initializable;
 import org.apache.avalon.framework.configuration.Configurable;
 import org.apache.avalon.framework.configuration.Configuration;
@@ -48,7 +50,7 @@ import org.apache.fulcrum.factory.utils.ObjectInputStreamForContext;
  */
 public class DefaultFactoryService
     extends AbstractLogEnabled
-    implements FactoryService, Configurable, Initializable
+    implements FactoryService, Configurable, Initializable, Disposable
 {
     protected boolean initialized = false;
     //private boolean disposed = false;
@@ -67,9 +69,10 @@ public class DefaultFactoryService
     /**
      * Primitive classes for reflection of constructors.
      */
-    private static HashMap primitiveClasses;
+    private static HashMap<String, Class<?>> primitiveClasses;
+
     {
-        primitiveClasses = new HashMap(8);
+        primitiveClasses = new HashMap<String, Class<?>>(8);
         primitiveClasses.put(Boolean.TYPE.toString(), Boolean.TYPE);
         primitiveClasses.put(Character.TYPE.toString(), Character.TYPE);
         primitiveClasses.put(Byte.TYPE.toString(), Byte.TYPE);
@@ -86,20 +89,27 @@ public class DefaultFactoryService
     /**
      * Additional class loaders.
      */
-    private ArrayList classLoaders = new ArrayList();
+    private ArrayList<ClassLoader> classLoaders = new ArrayList<ClassLoader>();
     /**
      * Customized object factories.
      */
-    private HashMap objectFactories = new HashMap();
+    private ConcurrentHashMap<String, Factory<?>> objectFactories =
+            new ConcurrentHashMap<String, Factory<?>>();
+    /**
+     * Customized object factory classes.
+     */
+    private ConcurrentHashMap<String, String> objectFactoryClasses =
+            new ConcurrentHashMap<String, String>();
+
     /**
      * Gets the class of a primitive type.
      *
      * @param type a primitive type.
      * @return the corresponding class, or null.
      */
-    protected static Class getPrimitiveClass(String type)
+    protected static Class<?> getPrimitiveClass(String type)
     {
-        return (Class) primitiveClasses.get(type);
+        return primitiveClasses.get(type);
     }
 
     /**
@@ -109,16 +119,17 @@ public class DefaultFactoryService
      * @return the instance.
      * @throws FactoryException if instantiation fails.
      */
-    public Object getInstance(String className) throws FactoryException
+    @Override
+    public <T> T getInstance(String className) throws FactoryException
     {
         if (className == null)
         {
             throw new FactoryException("Missing String className");
         }
-        Factory factory = getFactory(className);
+        Factory<T> factory = getFactory(className);
         if (factory == null)
         {
-            Class clazz;
+            Class<T> clazz;
             try
             {
                 clazz = loadClass(className);
@@ -145,14 +156,15 @@ public class DefaultFactoryService
      * @return the instance.
      * @throws FactoryException if instantiation fails.
      */
-    public Object getInstance(String className, ClassLoader loader) throws FactoryException
+    @Override
+    public <T> T getInstance(String className, ClassLoader loader) throws FactoryException
     {
-        Factory factory = getFactory(className);
+        Factory<T> factory = getFactory(className);
         if (factory == null)
         {
             if (loader != null)
             {
-                Class clazz;
+                Class<T> clazz;
                 try
                 {
                     clazz = loadClass(className, loader);
@@ -184,12 +196,13 @@ public class DefaultFactoryService
      * @return the instance.
      * @throws FactoryException if instantiation fails.
      */
-    public Object getInstance(String className, Object[] params, String[] signature) throws FactoryException
+    @Override
+    public <T> T getInstance(String className, Object[] params, String[] signature) throws FactoryException
     {
-        Factory factory = getFactory(className);
+        Factory<T> factory = getFactory(className);
         if (factory == null)
         {
-            Class clazz;
+            Class<T> clazz;
             try
             {
                 clazz = loadClass(className);
@@ -220,15 +233,16 @@ public class DefaultFactoryService
      * @return the instance.
      * @throws FactoryException if instantiation fails.
      */
-    public Object getInstance(String className, ClassLoader loader, Object[] params, String[] signature)
+    @Override
+    public <T> T getInstance(String className, ClassLoader loader, Object[] params, String[] signature)
         throws FactoryException
     {
-        Factory factory = getFactory(className);
+        Factory<T> factory = getFactory(className);
         if (factory == null)
         {
             if (loader != null)
             {
-                Class clazz;
+                Class<T> clazz;
                 try
                 {
                     clazz = loadClass(className, loader);
@@ -256,9 +270,10 @@ public class DefaultFactoryService
      * @return true if class loaders are supported, false otherwise.
      * @throws FactoryException if test fails.
      */
+    @Override
     public boolean isLoaderSupported(String className) throws FactoryException
     {
-        Factory factory = getFactory(className);
+        Factory<?> factory = getFactory(className);
         return factory != null ? factory.isLoaderSupported() : true;
     }
     /**
@@ -268,7 +283,8 @@ public class DefaultFactoryService
      * @return the instance.
      * @throws FactoryException if instantiation fails.
      */
-    public Object getInstance(Class clazz) throws FactoryException
+    @Override
+    public <T> T getInstance(Class<T> clazz) throws FactoryException
     {
         try
         {
@@ -290,12 +306,12 @@ public class DefaultFactoryService
      * @return the instance.
      * @throws FactoryException if instantiation fails.
      */
-    protected Object getInstance(Class clazz, Object params[], String signature[]) throws FactoryException
+    protected <T> T getInstance(Class<T> clazz, Object params[], String signature[]) throws FactoryException
     {
         /* Try to construct. */
         try
         {
-            Class[] sign = getSignature(clazz, params, signature);
+            Class<?>[] sign = getSignature(clazz, params, signature);
             return clazz.getConstructor(sign).newInstance(params);
         }
         catch (Exception x)
@@ -314,14 +330,15 @@ public class DefaultFactoryService
      * of a different class loader.
      * @throws ClassNotFoundException if any of the classes is not found.
      */
-    public Class[] getSignature(Class clazz, Object params[], String signature[]) throws ClassNotFoundException
+    @Override
+    public Class<?>[] getSignature(Class<?> clazz, Object params[], String signature[]) throws ClassNotFoundException
     {
         if (signature != null)
         {
             /* We have parameters. */
             ClassLoader tempLoader;
             ClassLoader loader = clazz.getClassLoader();
-            Class[] sign = new Class[signature.length];
+            Class<?>[] sign = new Class[signature.length];
             for (int i = 0; i < signature.length; i++)
             {
                 /* Check primitive types. */
@@ -368,26 +385,44 @@ public class DefaultFactoryService
     protected Object switchObjectContext(Object object, ClassLoader loader)
     {
         ByteArrayOutputStream bout = new ByteArrayOutputStream();
+
         try
         {
             ObjectOutputStream out = new ObjectOutputStream(bout);
             out.writeObject(object);
             out.flush();
         }
-        catch (Exception x)
+        catch (IOException x)
         {
             return object;
         }
+
+        ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+        ObjectInputStreamForContext in = null;
+
         try
         {
-            ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
-            ObjectInputStreamForContext in = new ObjectInputStreamForContext(bin, loader);
+            in = new ObjectInputStreamForContext(bin, loader);
             return in.readObject();
         }
         catch (Exception x)
         {
             return object;
         }
+        finally
+        {
+            if (in != null)
+            {
+                try
+                {
+                    in.close();
+                }
+                catch (IOException e)
+                {
+                    // close quietly
+                }
+            }
+        }
     }
     /**
      * Loads the named class using the default class loader.
@@ -396,21 +431,33 @@ public class DefaultFactoryService
      * @return the loaded class.
      * @throws ClassNotFoundException if the class was not found.
      */
-    protected Class loadClass(String className) throws ClassNotFoundException
+    @SuppressWarnings("unchecked")
+    protected <T> Class<T> loadClass(String className) throws ClassNotFoundException
     {
         ClassLoader loader = this.getClass().getClassLoader();
         try
         {
-            return loader != null ? loader.loadClass(className) : Class.forName(className);
+            Class<T> clazz;
+
+            if (loader != null)
+            {
+                clazz = (Class<T>) loader.loadClass(className);
+            }
+            else
+            {
+                clazz = (Class<T>) Class.forName(className);
+            }
+
+            return clazz;
         }
         catch (ClassNotFoundException x)
         {
             /* Go through additional loaders. */
-            for (Iterator i = classLoaders.iterator(); i.hasNext();)
+            for (ClassLoader l : classLoaders)
             {
                 try
                 {
-                    return ((ClassLoader) i.next()).loadClass(className);
+                    return (Class<T>) l.loadClass(className);
                 }
                 catch (ClassNotFoundException xx)
                 {
@@ -429,9 +476,17 @@ public class DefaultFactoryService
      * @return the loaded class.
      * @throws ClassNotFoundException if the class was not found.
      */
-    protected Class loadClass(String className, ClassLoader loader) throws ClassNotFoundException
+    @SuppressWarnings("unchecked")
+    protected <T> Class<T> loadClass(String className, ClassLoader loader) throws ClassNotFoundException
     {
-        return loader != null ? loader.loadClass(className) : loadClass(className);
+        if (loader != null)
+        {
+            return (Class<T>) loader.loadClass(className);
+        }
+        else
+        {
+            return loadClass(className);
+        }
     }
     /**
      * Gets a customized factory for a named class. If no class-specific
@@ -442,49 +497,54 @@ public class DefaultFactoryService
      * @return the factory, or null if not specified and no default.
      * @throws FactoryException if instantiation of the factory fails.
      */
-    protected Factory getFactory(String className) throws FactoryException
+    @SuppressWarnings("unchecked")
+    protected <T> Factory<T> getFactory(String className) throws FactoryException
     {
-        HashMap factories = objectFactories;
-        Object factory = factories.get(className);
+        Factory<T> factory = (Factory<T>) objectFactories.get(className);
         if (factory == null)
         {
             //No named factory for this; try the default, if one
             //exists.
-            factory = factories.get(DEFAULT_FACTORY);
+            factory = (Factory<T>) objectFactories.get(DEFAULT_FACTORY);
         }
-        if (factory != null)
+        if (factory == null)
         {
-            if (factory instanceof String)
+            /* Not yet instantiated... */
+            String factoryClass = objectFactoryClasses.get(className);
+            if (factoryClass == null)
             {
-                /* Not yet instantiated... */
-                try
-                {
-                    factory = (Factory) getInstance((String) factory);
-                    ((Factory) factory).init(className);
-                }
-                catch (FactoryException x)
-                {
-                    throw x;
-                }
-                catch (ClassCastException x)
-                {
-                    throw new FactoryException("Incorrect factory " + (String) factory + " for class " + className, x);
-                }
-                factories = (HashMap) factories.clone();
-                factories.put(className, factory);
-                objectFactories = factories;
+                factoryClass = objectFactoryClasses.get(DEFAULT_FACTORY);
+            }
+            if (factoryClass == null)
+            {
+                return null;
+            }
+
+            try
+            {
+                factory = getInstance(factoryClass);
+                factory.init(className);
+            }
+            catch (ClassCastException x)
+            {
+                throw new FactoryException("Incorrect factory " + factoryClass + " for class " + className, x);
+            }
+            Factory<T> _factory = (Factory<T>) objectFactories.putIfAbsent(className, factory);
+            if (_factory != null)
+            {
+                // Already created - take first instance
+                factory = _factory;
             }
-            return (Factory) factory;
-        }
-        else
-        {
-            return null;
         }
+
+        return factory;
     }
+
     // ---------------- Avalon Lifecycle Methods ---------------------
     /**
      * Avalon component lifecycle method
      */
+    @Override
     public void configure(Configuration conf) throws ConfigurationException
     {
         final Configuration[] loaders = conf.getChildren(CLASS_LOADER);
@@ -506,10 +566,11 @@ public class DefaultFactoryService
                 String factory = nameVal[i].getValue();
                 // Store the factory to the table as a string and
                 // instantiate it by using the service when needed.
-                objectFactories.put(key, factory);
+                objectFactoryClasses.put(key, factory);
             }
         }
     }
+
     /**
      * Avalon component lifecycle method
      * Initializes the service by loading default class loaders
@@ -517,6 +578,7 @@ public class DefaultFactoryService
      *
      * @throws InitializationException if initialization fails.
      */
+    @Override
     public void initialize() throws Exception
     {
         if (loaderNames != null)
@@ -525,16 +587,28 @@ public class DefaultFactoryService
             {
                 try
                 {
-                    classLoaders.add(loadClass(loaderNames[i]).newInstance());
+                    ClassLoader loader = (ClassLoader) loadClass(loaderNames[i]).newInstance();
+                    classLoaders.add(loader);
                 }
                 catch (Exception x)
                 {
                     throw new Exception(
-                        "No such class loader '" + loaderNames[i] + "' for DefaultFactoryService",
-                        x);
+                        "No such class loader '" + loaderNames[i] + "' for DefaultFactoryService", x);
                 }
             }
             loaderNames = null;
         }
     }
+
+    /**
+     * Avalon component lifecycle method
+     * Clear lists and maps
+     */
+    @Override
+    public void dispose()
+    {
+        objectFactories.clear();
+        objectFactoryClasses.clear();
+        classLoaders.clear();
+    }
 }
diff --git a/src/java/org/apache/fulcrum/factory/Factory.java b/src/java/org/apache/fulcrum/factory/Factory.java
index 841d30c..bb7e7b4 100644
--- a/src/java/org/apache/fulcrum/factory/Factory.java
+++ b/src/java/org/apache/fulcrum/factory/Factory.java
@@ -1,6 +1,5 @@
 package org.apache.fulcrum.factory;
 
-
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -20,8 +19,6 @@ package org.apache.fulcrum.factory;
  * under the License.
  */
 
-
-
 /**
  * Factory is an interface for object factories. Object factories
  * can be registered with the Factory Service to support customized
@@ -34,7 +31,7 @@ package org.apache.fulcrum.factory;
  * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
  * @version $Id$
  */
-public interface Factory
+public interface Factory<T>
 {
     /**
      * Initializes the factory. This method is called by
@@ -43,8 +40,7 @@ public interface Factory
      * @param className the name of the production class
      * @throws FactoryException if initialization fails.
      */
-    public void init(String className)
-        throws FactoryException;
+    void init(String className) throws FactoryException;
 
     /**
      * Gets an instance of a class.
@@ -52,8 +48,7 @@ public interface Factory
      * @return the instance.
      * @throws FactoryException if instantiation fails.
      */
-    public Object getInstance()
-        throws FactoryException;
+    T getInstance() throws FactoryException;
 
     /**
      * Gets an instance of a class using a specified class loader.
@@ -65,8 +60,7 @@ public interface Factory
      * @return the instance.
      * @throws FactoryException if instantiation fails.
      */
-    public Object getInstance(ClassLoader loader)
-        throws FactoryException;
+    T getInstance(ClassLoader loader) throws FactoryException;
 
     /**
      * Gets an instance of a named class.
@@ -78,8 +72,7 @@ public interface Factory
      * @return the instance.
      * @throws FactoryException if instantiation fails.
      */
-    public Object getInstance(Object[] params,
-                              String[] signature)
+    T getInstance(Object[] params, String[] signature)
         throws FactoryException;
 
     /**
@@ -96,9 +89,7 @@ public interface Factory
      * @return the instance.
      * @throws FactoryException if instantiation fails.
      */
-    public Object getInstance(ClassLoader loader,
-                              Object[] params,
-                              String[] signature)
+    T getInstance(ClassLoader loader, Object[] params, String[] signature)
         throws FactoryException;
 
     /**
@@ -106,5 +97,5 @@ public interface Factory
      *
      * @return true if class loaders are supported, false otherwise.
      */
-    public boolean isLoaderSupported();
+    boolean isLoaderSupported();
 }
diff --git a/src/java/org/apache/fulcrum/factory/FactoryService.java b/src/java/org/apache/fulcrum/factory/FactoryService.java
index e4e2f5f..9c42e19 100644
--- a/src/java/org/apache/fulcrum/factory/FactoryService.java
+++ b/src/java/org/apache/fulcrum/factory/FactoryService.java
@@ -1,5 +1,7 @@
 package org.apache.fulcrum.factory;
 
+import org.apache.avalon.framework.service.ServiceException;
+
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -47,7 +49,7 @@ public interface FactoryService
 	* @return the instance.
 	* @throws ServiceException if instantiation fails.
 	*/
-   public Object getInstance(Class clazz)
+   <T> T getInstance(Class<T> clazz)
 	   throws FactoryException;
 
     /**
@@ -57,7 +59,7 @@ public interface FactoryService
      * @return the instance.
      * @throws ServiceException if instantiation fails.
      */
-    public Object getInstance(String className)
+    <T> T getInstance(String className)
         throws FactoryException;
 
     /**
@@ -71,7 +73,7 @@ public interface FactoryService
      * @return the instance.
      * @throws ServiceException if instantiation fails.
      */
-    public Object getInstance(String className,
+    <T> T getInstance(String className,
                               ClassLoader loader)
         throws FactoryException;
 
@@ -86,7 +88,7 @@ public interface FactoryService
      * @return the instance.
      * @throws ServiceException if instantiation fails.
      */
-    public Object getInstance(String className,
+    <T> T getInstance(String className,
                               Object[] params,
                               String[] signature)
         throws FactoryException;
@@ -106,7 +108,7 @@ public interface FactoryService
      * @return the instance.
      * @throws ServiceException if instantiation fails.
      */
-    public Object getInstance(String className,
+    <T> T getInstance(String className,
                               ClassLoader loader,
                               Object[] params,
                               String[] signature)
@@ -119,7 +121,7 @@ public interface FactoryService
      * @return true if class loaders are supported, false otherwise.
      * @throws ServiceException if test fails.
      */
-    public boolean isLoaderSupported(String className)
+    boolean isLoaderSupported(String className)
         throws FactoryException;
 
     /**
@@ -133,7 +135,7 @@ public interface FactoryService
      * of a different class loader.
      * @throws ClassNotFoundException if any of the classes is not found.
      */
-    Class[] getSignature(Class clazz,
+    Class<?>[] getSignature(Class<?> clazz,
             Object params[],
             String signature[])
             throws ClassNotFoundException;
diff --git a/src/java/org/apache/fulcrum/factory/utils/ObjectInputStreamForContext.java b/src/java/org/apache/fulcrum/factory/utils/ObjectInputStreamForContext.java
index a0fb934..513448f 100644
--- a/src/java/org/apache/fulcrum/factory/utils/ObjectInputStreamForContext.java
+++ b/src/java/org/apache/fulcrum/factory/utils/ObjectInputStreamForContext.java
@@ -1,5 +1,6 @@
 package org.apache.fulcrum.factory.utils;
 
+import java.io.IOException;
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -20,11 +21,9 @@ package org.apache.fulcrum.factory.utils;
  * under the License.
  */
 
-
 import java.io.InputStream;
 import java.io.ObjectInputStream;
 import java.io.ObjectStreamClass;
-import java.io.IOException;
 
 /**
  * A deserialization stream for a specific class loader context.
@@ -60,7 +59,11 @@ public class ObjectInputStreamForContext extends ObjectInputStream
         classLoader = loader;
     }
 
-    protected Class resolveClass(ObjectStreamClass v)
+    /**
+     * @see java.io.ObjectInputStream#resolveClass()
+     */
+    @Override
+    protected Class<?> resolveClass(ObjectStreamClass v)
                                  throws IOException,
                                  ClassNotFoundException
     {
diff --git a/src/test/org/apache/fulcrum/factory/FactoryServiceTest.java b/src/test/org/apache/fulcrum/factory/FactoryServiceTest.java
index eb97a08..f82256d 100644
--- a/src/test/org/apache/fulcrum/factory/FactoryServiceTest.java
+++ b/src/test/org/apache/fulcrum/factory/FactoryServiceTest.java
@@ -21,6 +21,7 @@ package org.apache.fulcrum.factory;
 
 
 import java.util.ArrayList;
+
 import org.apache.fulcrum.testcontainer.BaseUnitTest;
 
 /**
@@ -43,6 +44,7 @@ public class FactoryServiceTest extends BaseUnitTest
         super(name);
     }
 
+    @Override
     public void setUp() throws Exception
     {
         super.setUp();
@@ -116,7 +118,7 @@ public class FactoryServiceTest extends BaseUnitTest
         params[0] = sourceValu;
         String signature[] = new String[1];
         signature[0] = "java.lang.String";
-        Class[] results = factoryService.getSignature(StringBuffer.class, params, signature);
+        Class<?>[] results = factoryService.getSignature(StringBuffer.class, params, signature);
         assertEquals(1, results.length);
         assertTrue(results[0].equals(String.class));
 
@@ -126,6 +128,5 @@ public class FactoryServiceTest extends BaseUnitTest
         results = factoryService.getSignature(ArrayList.class, params, signature);
         assertEquals(1, results.length);
         assertTrue("Result:" + results[0].getName(),results[0].equals(Integer.class));
-
     }
 }