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 a9c563a583570e11571d634bf76f06c2cabaad6a
Author: Jeffery Painter <[email protected]>
AuthorDate: Thu Dec 13 21:50:53 2018 +0000

    Code cleanup, more Java 8 syntax, cleared all Findbugs and PMD reports, 
update changes.xml
    
    git-svn-id: 
https://svn.apache.org/repos/asf/turbine/fulcrum/trunk/factory@1848903 
13f79535-47bb-0310-9956-ffa450edef68
---
 src/changes/changes.xml                            |    9 +
 .../fulcrum/factory/DefaultFactoryService.java     | 1048 +++++++++-----------
 .../apache/fulcrum/factory/FactoryException.java   |   76 +-
 3 files changed, 519 insertions(+), 614 deletions(-)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index c471df9..f55c121 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -25,6 +25,15 @@
 
   <body>
     <release version="1.1.1" date="in SVN">
+               <action dev="painter" type="update">
+                       Addressed all PMD static code analyzer issues and 
corrected where appropriate
+               </action>
+               <action dev="painter" type="update">
+                       Derive from Turbine parent POM 5
+               </action>
+               <action dev="painter" type="update">
+                       Require Java 8
+               </action>
     </release>
     <release version="1.1.0" date="2016-11-27">
       <action dev="tv" type="add">
diff --git a/src/java/org/apache/fulcrum/factory/DefaultFactoryService.java 
b/src/java/org/apache/fulcrum/factory/DefaultFactoryService.java
index 15df0f5..0e6d599 100644
--- a/src/java/org/apache/fulcrum/factory/DefaultFactoryService.java
+++ b/src/java/org/apache/fulcrum/factory/DefaultFactoryService.java
@@ -36,585 +36,485 @@ import 
org.apache.avalon.framework.logger.AbstractLogEnabled;
 import org.apache.fulcrum.factory.utils.ObjectInputStreamForContext;
 
 /**
- * The Factory Service instantiates objects using specified
- * class loaders. If none is specified, the default one
- * will be used.
+ * The Factory Service instantiates objects using specified class loaders. If
+ * none is specified, the default one will be used.
  * 
- * avalon.component name="factory" lifestyle="singleton"
- * avalon.service   type="org.apache.fulcrum.factory.FactoryService"
+ * avalon.component name="factory" lifestyle="singleton" avalon.service
+ * type="org.apache.fulcrum.factory.FactoryService"
  *
  * @author <a href="mailto:[email protected]";>Eric Pugh</a>
  * @author <a href="mailto:[email protected]";>Ilkka Priha</a>
  * @author <a href="mailto:[email protected]";>Stephen McConnell</a>
- * @version $Id$
+ * @version $Id: DefaultFactoryService.java 1844842 2018-10-25 15:33:42Z 
painter
+ *          $
  *
  */
-public class DefaultFactoryService
-    extends AbstractLogEnabled
-    implements FactoryService, Configurable, Initializable, Disposable
-{
-    protected boolean initialized = false;
-
-    /**
-     * The property specifying a set of additional class loaders.
-     */
-    private static final String CLASS_LOADER = "classloader";
-    
-    /**
-     * The property prefix specifying additional object factories.
-     */
-    private static final String OBJECT_FACTORY = "object-factory";
-    
-    /**
-     * The name of the default factory.
-     */
-    protected static final String DEFAULT_FACTORY = "default";
-    
-    /**
-     * Primitive classes for reflection of constructors.
-     */
-    private static HashMap<String, Class<?>> 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);
-        primitiveClasses.put(Short.TYPE.toString(), Short.TYPE);
-        primitiveClasses.put(Integer.TYPE.toString(), Integer.TYPE);
-        primitiveClasses.put(Long.TYPE.toString(), Long.TYPE);
-        primitiveClasses.put(Float.TYPE.toString(), Float.TYPE);
-        primitiveClasses.put(Double.TYPE.toString(), Double.TYPE);
-    }
-
-    /**
-     * temporary storage of class names between configure and initialize
-     */
-    private String[] loaderNames;
-    /**
-     * Additional class loaders.
-     */
-    private ArrayList<ClassLoader> classLoaders = new ArrayList<ClassLoader>();
-    /**
-     * Customized object factories.
-     */
-    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)
-    {
-        return primitiveClasses.get(type);
-    }
-
-    /**
-     * Gets an instance of a named class.
-     *
-     * @param className the name of the class.
-     * @return the instance.
-     * @throws FactoryException if instantiation fails.
-     */
-    @Override
-    public <T> T getInstance(String className) throws FactoryException
-    {
-        if (className == null)
-        {
-            throw new FactoryException("Missing String className");
-        }
-        Factory<T> factory = getFactory(className);
-        if (factory == null)
-        {
-            Class<T> clazz;
-            try
-            {
-                clazz = loadClass(className);
-            }
-            catch (ClassNotFoundException x)
-            {
-                throw new FactoryException("Instantiation failed for class " + 
className, x);
-            }
-            return getInstance(clazz);
-        }
-        else
-        {
-            return factory.getInstance();
-        }
-    }
-    /**
-     * Gets an instance of a named class using a specified class loader.
-     *
-     * <p>Class loaders are supported only if the isLoaderSupported
-     * method returns true. Otherwise the loader parameter is ignored.
-     *
-     * @param className the name of the class.
-     * @param loader the class loader.
-     * @return the instance.
-     * @throws FactoryException if instantiation fails.
-     */
-    @Override
-    public <T> T getInstance(String className, ClassLoader loader) throws 
FactoryException
-    {
-        Factory<T> factory = getFactory(className);
-        if (factory == null)
-        {
-            if (loader != null)
-            {
-                Class<T> clazz;
-                try
-                {
-                    clazz = loadClass(className, loader);
-                }
-                catch (ClassNotFoundException x)
-                {
-                    throw new FactoryException("Instantiation failed for class 
" + className, x);
-                }
-                return getInstance(clazz);
-            }
-            else
-            {
-                return getInstance(className);
-            }
-        }
-        else
-        {
-            return factory.getInstance(loader);
-        }
-    }
-    /**
-     * Gets an instance of a named class.
-     * Parameters for its constructor are given as an array of objects,
-     * primitive types must be wrapped with a corresponding class.
-     *
-     * @param className the name of the class.
-     * @param params an array containing the parameters of the constructor.
-     * @param signature an array containing the signature of the constructor.
-     * @return the instance.
-     * @throws FactoryException if instantiation fails.
-     */
-    @Override
-    public <T> T getInstance(String className, Object[] params, String[] 
signature) throws FactoryException
-    {
-        Factory<T> factory = getFactory(className);
-        if (factory == null)
-        {
-            Class<T> clazz;
-            try
-            {
-                clazz = loadClass(className);
-            }
-            catch (ClassNotFoundException x)
-            {
-                throw new FactoryException("Instantiation failed for class " + 
className, x);
-            }
-            return getInstance(clazz, params, signature);
-        }
-        else
-        {
-            return factory.getInstance(params, signature);
-        }
-    }
-    /**
-     * Gets an instance of a named class using a specified class loader.
-     * Parameters for its constructor are given as an array of objects,
-     * primitive types must be wrapped with a corresponding class.
-     *
-     * <p>Class loaders are supported only if the isLoaderSupported
-     * method returns true. Otherwise the loader parameter is ignored.
-     *
-     * @param className the name of the class.
-     * @param loader the class loader.
-     * @param params an array containing the parameters of the constructor.
-     * @param signature an array containing the signature of the constructor.
-     * @return the instance.
-     * @throws FactoryException if instantiation fails.
-     */
-    @Override
-    public <T> T getInstance(String className, ClassLoader loader, Object[] 
params, String[] signature)
-        throws FactoryException
-    {
-        Factory<T> factory = getFactory(className);
-        if (factory == null)
-        {
-            if (loader != null)
-            {
-                Class<T> clazz;
-                try
-                {
-                    clazz = loadClass(className, loader);
-                }
-                catch (ClassNotFoundException x)
-                {
-                    throw new FactoryException("Instantiation failed for class 
" + className, x);
-                }
-                return getInstance(clazz, params, signature);
-            }
-            else
-            {
-                return getInstance(className, params, signature);
-            }
-        }
-        else
-        {
-            return factory.getInstance(loader, params, signature);
-        }
-    }
-    /**
-     * Tests if specified class loaders are supported for a named class.
-     *
-     * @param className the name of the class.
-     * @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);
-        return factory != null ? factory.isLoaderSupported() : true;
-    }
-    /**
-     * Gets an instance of a specified class.
-     *
-     * @param clazz the class.
-     * @return the instance.
-     * @throws FactoryException if instantiation fails.
-     */
-    @Override
-    public <T> T getInstance(Class<T> clazz) throws FactoryException
-    {
-        try
-        {
-            return clazz.newInstance();
-        }
-        catch (Exception x)
-        {
-            throw new FactoryException("Instantiation failed for " + 
clazz.getName(), x);
-        }
-    }
-    /**
-     * Gets an instance of a specified class.
-     * Parameters for its constructor are given as an array of objects,
-     * primitive types must be wrapped with a corresponding class.
-     *
-     * @param clazz the class.
-     * @param params an array containing the parameters of the constructor.
-     * @param signature an array containing the signature of the constructor.
-     * @return the instance.
-     * @throws FactoryException if instantiation fails.
-     */
-    protected <T> T getInstance(Class<T> clazz, Object params[], String 
signature[]) throws FactoryException
-    {
-        /* Try to construct. */
-        try
-        {
-            Class<?>[] sign = getSignature(clazz, params, signature);
-            return clazz.getConstructor(sign).newInstance(params);
-        }
-        catch (Exception x)
-        {
-            throw new FactoryException("Instantiation failed for " + 
clazz.getName(), x);
-        }
-    }
-    /**
-     * Gets the signature classes for parameters of a method of a class.
-     *
-     * @param clazz the class.
-     * @param params an array containing the parameters of the method.
-     * @param signature an array containing the signature of the method.
-     * @return an array of signature classes. Note that in some cases
-     * objects in the parameter array can be switched to the context
-     * of a different class loader.
-     * @throws ClassNotFoundException if any of the classes is not found.
-     */
-    @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];
-            for (int i = 0; i < signature.length; i++)
-            {
-                /* Check primitive types. */
-                sign[i] = getPrimitiveClass(signature[i]);
-                if (sign[i] == null)
-                {
-                    /* Not a primitive one, continue building. */
-                    if (loader != null)
-                    {
-                        /* Use the class loader of the target object. */
-                        sign[i] = loader.loadClass(signature[i]);
-                        tempLoader = sign[i].getClassLoader();
-                        if ((params[i] != null)
-                            && (tempLoader != null)
-                            && 
!tempLoader.equals(params[i].getClass().getClassLoader()))
-                        {
-                            /*
-                             * The class uses a different class loader,
-                             * switch the parameter.
-                             */
-                            params[i] = switchObjectContext(params[i], loader);
-                        }
-                    }
-                    else
-                    {
-                        /* Use the default class loader. */
-                        sign[i] = loadClass(signature[i]);
-                    }
-                }
-            }
-            return sign;
-        }
-        else
-        {
-            return null;
-        }
-    }
-    /**
-     * Switches an object into the context of a different class loader.
-     *
-     * @param object an object to switch.
-     * @param loader the ClassLoader to use
-     * @param loader the loader of the new context.
-     * @return the object
-     */
-    protected Object switchObjectContext(Object object, ClassLoader loader)
-    {
-        ByteArrayOutputStream bout = new ByteArrayOutputStream();
-
-        try
-        {
-            ObjectOutputStream out = new ObjectOutputStream(bout);
-            out.writeObject(object);
-            out.flush();
-        }
-        catch (IOException x)
-        {
-            return object;
-        }
-
-        ByteArrayInputStream bin = new 
ByteArrayInputStream(bout.toByteArray());
-        ObjectInputStreamForContext in = null;
-
-        try
-        {
-            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.
-     *
-     * @param className the name of the class to load.
-     * @return {@inheritDoc} the loaded class.
-     * @throws ClassNotFoundException if the class was not found.
-     */
-    @SuppressWarnings("unchecked")
-    protected <T> Class<T> loadClass(String className) throws 
ClassNotFoundException
-    {
-        ClassLoader loader = this.getClass().getClassLoader();
-        try
-        {
-            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 (ClassLoader l : classLoaders)
-            {
-                try
-                {
-                    return (Class<T>) l.loadClass(className);
-                }
-                catch (ClassNotFoundException xx)
-                {
-                    // continue
-                }
-            }
-            /* Give up. */
-            throw x;
-        }
-    }
-    /**
-     * Loads the named class using a specified class loader.
-     *
-     * @param className the name of the class to load.
-     * @param loader the loader to use.
-     * @return {@inheritDoc} the loaded class.
-     * @throws ClassNotFoundException if the class was not found.
-     */
-    @SuppressWarnings("unchecked")
-    protected <T> Class<T> loadClass(String className, ClassLoader loader) 
throws ClassNotFoundException
-    {
-        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
-     * factory is specified but a default factory is, will use the default
-     * factory.
-     *
-     * @param className the name of the class to load.
-     * @return {@inheritDoc} the factory, or null if not specified and no 
default.
-     * @throws FactoryException if instantiation of the factory fails.
-     */
-    @SuppressWarnings("unchecked")
-    protected <T> Factory<T> getFactory(String className) throws 
FactoryException
-    {
-        Factory<T> factory = (Factory<T>) objectFactories.get(className);
-        if (factory == null)
-        {
-            //No named factory for this; try the default, if one
-            //exists.
-            factory = (Factory<T>) objectFactories.get(DEFAULT_FACTORY);
-        }
-        if (factory == null)
-        {
-            /* Not yet instantiated... */
-            String factoryClass = objectFactoryClasses.get(className);
-            if (factoryClass == null)
-            {
-                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;
-    }
-
-    // ---------------- Avalon Lifecycle Methods ---------------------
-    /**
-     * Avalon component lifecycle method
-     */
-    @Override
-    public void configure(Configuration conf) throws ConfigurationException
-    {
-        final Configuration[] loaders = conf.getChildren(CLASS_LOADER);
-        if (loaders != null)
-        {
-            loaderNames = new String[loaders.length];
-            for (int i = 0; i < loaders.length; i++)
-            {
-                loaderNames[i] = loaders[i].getValue();
-            }
-        }
-        final Configuration factories = conf.getChild(OBJECT_FACTORY, false);
-        if (factories != null)
-        {
-            Configuration[] nameVal = factories.getChildren();
-            for (int i = 0; i < nameVal.length; i++)
-            {
-                String key = nameVal[i].getName();
-                String factory = nameVal[i].getValue();
-                // Store the factory to the table as a string and
-                // instantiate it by using the service when needed.
-                objectFactoryClasses.put(key, factory);
-            }
-        }
-    }
-
-    /**
-     * Avalon component lifecycle method
-     * Initializes the service by loading default class loaders
-     * and customized object factories.
-     *
-     * @throws Exception if initialization fails.
-     */
-    @Override
-    public void initialize() throws Exception
-    {
-        if (loaderNames != null)
-        {
-            for (int i = 0; i < loaderNames.length; i++)
-            {
-                try
-                {
-                    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);
-                }
-            }
-            loaderNames = null;
-        }
-    }
-
-    /**
-     * Avalon component lifecycle method
-     * Clear lists and maps
-     */
-    @Override
-    public void dispose()
-    {
-        objectFactories.clear();
-        objectFactoryClasses.clear();
-        classLoaders.clear();
-    }
+public class DefaultFactoryService extends AbstractLogEnabled
+               implements FactoryService, Configurable, Initializable, 
Disposable {
+
+       /**
+        * The property specifying a set of additional class loaders.
+        */
+       private static final String CLASS_LOADER = "classloader";
+
+       /**
+        * The property prefix specifying additional object factories.
+        */
+       private static final String OBJECT_FACTORY = "object-factory";
+
+       /**
+        * The name of the default factory.
+        */
+       protected static final String DEFAULT_FACTORY = "default";
+
+       /**
+        * Primitive classes for reflection of constructors.
+        */
+       private static HashMap<String, Class<?>> 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);
+               primitiveClasses.put(Short.TYPE.toString(), Short.TYPE);
+               primitiveClasses.put(Integer.TYPE.toString(), Integer.TYPE);
+               primitiveClasses.put(Long.TYPE.toString(), Long.TYPE);
+               primitiveClasses.put(Float.TYPE.toString(), Float.TYPE);
+               primitiveClasses.put(Double.TYPE.toString(), Double.TYPE);
+       }
+
+       /**
+        * temporary storage of class names between configure and initialize
+        */
+       private String[] loaderNames;
+       /**
+        * Additional class loaders.
+        */
+       private ArrayList<ClassLoader> classLoaders = new 
ArrayList<ClassLoader>();
+       /**
+        * Customized object factories.
+        */
+       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) {
+               return primitiveClasses.get(type);
+       }
+
+       /**
+        * Gets an instance of a named class.
+        *
+        * @param className the name of the class.
+        * @return the instance.
+        * @throws FactoryException if instantiation fails.
+        */
+       @Override
+       public <T> T getInstance(String className) throws FactoryException {
+               if (className == null) {
+                       throw new FactoryException("Missing String className");
+               }
+               Factory<T> factory = getFactory(className);
+               if (factory == null) {
+                       Class<T> clazz;
+                       try {
+                               clazz = loadClass(className);
+                       } catch (ClassNotFoundException x) {
+                               throw new FactoryException("Instantiation 
failed for class " + className, x);
+                       }
+                       return getInstance(clazz);
+               } else {
+                       return factory.getInstance();
+               }
+       }
+
+       /**
+        * Gets an instance of a named class using a specified class loader.
+        *
+        * <p>
+        * Class loaders are supported only if the isLoaderSupported method 
returns
+        * true. Otherwise the loader parameter is ignored.
+        *
+        * @param className the name of the class.
+        * @param loader    the class loader.
+        * @return the instance.
+        * @throws FactoryException if instantiation fails.
+        */
+       @Override
+       public <T> T getInstance(String className, ClassLoader loader) throws 
FactoryException {
+               Factory<T> factory = getFactory(className);
+               if (factory == null) {
+                       if (loader != null) {
+                               Class<T> clazz;
+                               try {
+                                       clazz = loadClass(className, loader);
+                               } catch (ClassNotFoundException x) {
+                                       throw new 
FactoryException("Instantiation failed for class " + className, x);
+                               }
+                               return getInstance(clazz);
+                       } else {
+                               return getInstance(className);
+                       }
+               } else {
+                       return factory.getInstance(loader);
+               }
+       }
+
+       /**
+        * Gets an instance of a named class. Parameters for its constructor 
are given
+        * as an array of objects, primitive types must be wrapped with a 
corresponding
+        * class.
+        *
+        * @param className the name of the class.
+        * @param params    an array containing the parameters of the 
constructor.
+        * @param signature an array containing the signature of the 
constructor.
+        * @return the instance.
+        * @throws FactoryException if instantiation fails.
+        */
+       @Override
+       public <T> T getInstance(String className, Object[] params, String[] 
signature) throws FactoryException {
+               Factory<T> factory = getFactory(className);
+               if (factory == null) {
+                       Class<T> clazz;
+                       try {
+                               clazz = loadClass(className);
+                       } catch (ClassNotFoundException x) {
+                               throw new FactoryException("Instantiation 
failed for class " + className, x);
+                       }
+                       return getInstance(clazz, params, signature);
+               } else {
+                       return factory.getInstance(params, signature);
+               }
+       }
+
+       /**
+        * Gets an instance of a named class using a specified class loader. 
Parameters
+        * for its constructor are given as an array of objects, primitive 
types must be
+        * wrapped with a corresponding class.
+        *
+        * <p>
+        * Class loaders are supported only if the isLoaderSupported method 
returns
+        * true. Otherwise the loader parameter is ignored.
+        *
+        * @param className the name of the class.
+        * @param loader    the class loader.
+        * @param params    an array containing the parameters of the 
constructor.
+        * @param signature an array containing the signature of the 
constructor.
+        * @return the instance.
+        * @throws FactoryException if instantiation fails.
+        */
+       @Override
+       public <T> T getInstance(String className, ClassLoader loader, Object[] 
params, String[] signature)
+                       throws FactoryException {
+               Factory<T> factory = getFactory(className);
+               if (factory == null) {
+                       if (loader != null) {
+                               Class<T> clazz;
+                               try {
+                                       clazz = loadClass(className, loader);
+                               } catch (ClassNotFoundException x) {
+                                       throw new 
FactoryException("Instantiation failed for class " + className, x);
+                               }
+                               return getInstance(clazz, params, signature);
+                       } else {
+                               return getInstance(className, params, 
signature);
+                       }
+               } else {
+                       return factory.getInstance(loader, params, signature);
+               }
+       }
+
+       /**
+        * Tests if specified class loaders are supported for a named class.
+        *
+        * @param className the name of the class.
+        * @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);
+               return factory != null ? factory.isLoaderSupported() : true;
+       }
+
+       /**
+        * Gets an instance of a specified class.
+        *
+        * @param clazz the class.
+        * @return the instance.
+        * @throws FactoryException if instantiation fails.
+        */
+       @Override
+       public <T> T getInstance(Class<T> clazz) throws FactoryException {
+               try {
+                       return clazz.newInstance();
+               } catch (Exception x) {
+                       throw new FactoryException("Instantiation failed for " 
+ clazz.getName(), x);
+               }
+       }
+
+       /**
+        * Gets an instance of a specified class. Parameters for its 
constructor are
+        * given as an array of objects, primitive types must be wrapped with a
+        * corresponding class.
+        *
+        * @param           <T> Type of the class
+        * @param clazz     the class
+        * @param params    an array containing the parameters of the 
constructor
+        * @param signature an array containing the signature of the constructor
+        * @return the instance
+        * @throws FactoryException if instantiation fails.
+        */
+       protected <T> T getInstance(Class<T> clazz, Object params[], String 
signature[]) throws FactoryException {
+               /* Try to construct. */
+               try {
+                       Class<?>[] sign = getSignature(clazz, params, 
signature);
+                       return clazz.getConstructor(sign).newInstance(params);
+               } catch (Exception x) {
+                       throw new FactoryException("Instantiation failed for " 
+ clazz.getName(), x);
+               }
+       }
+
+       /**
+        * Gets the signature classes for parameters of a method of a class.
+        *
+        * @param clazz     the class.
+        * @param params    an array containing the parameters of the method.
+        * @param signature an array containing the signature of the method.
+        * @return an array of signature classes. Note that in some cases 
objects in the
+        *         parameter array can be switched to the context of a 
different class
+        *         loader.
+        * @throws ClassNotFoundException if any of the classes is not found.
+        */
+       @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];
+                       for (int i = 0; i < signature.length; i++) {
+                               /* Check primitive types. */
+                               sign[i] = getPrimitiveClass(signature[i]);
+                               if (sign[i] == null) {
+                                       /* Not a primitive one, continue 
building. */
+                                       if (loader != null) {
+                                               /* Use the class loader of the 
target object. */
+                                               sign[i] = 
loader.loadClass(signature[i]);
+                                               tempLoader = 
sign[i].getClassLoader();
+                                               if (params[i] != null && 
tempLoader != null
+                                                               && 
!tempLoader.equals(params[i].getClass().getClassLoader())) {
+                                                       /*
+                                                        * The class uses a 
different class loader, switch the parameter.
+                                                        */
+                                                       params[i] = 
switchObjectContext(params[i], loader);
+                                               }
+                                       } else {
+                                               /* Use the default class 
loader. */
+                                               sign[i] = 
loadClass(signature[i]);
+                                       }
+                               }
+                       }
+                       return sign;
+               } else {
+                       return null;
+               }
+       }
+
+       /**
+        * Switches an object into the context of a different class loader.
+        *
+        * @param object an object to switch.
+        * @param loader the ClassLoader to use
+        * @param loader the loader of the new context.
+        * @return the object
+        */
+       protected Object switchObjectContext(Object object, ClassLoader loader) 
{
+               ByteArrayOutputStream bout = new ByteArrayOutputStream();
+
+               try {
+                       ObjectOutputStream out = new ObjectOutputStream(bout);
+                       out.writeObject(object);
+                       out.flush();
+               } catch (IOException x) {
+                       return object;
+               }
+
+               ByteArrayInputStream bin = new 
ByteArrayInputStream(bout.toByteArray());
+               ObjectInputStreamForContext in = null;
+
+               try {
+                       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.
+        *
+        * @param className the name of the class to load.
+        * @return {@inheritDoc} the loaded class.
+        * @throws ClassNotFoundException if the class was not found.
+        */
+       @SuppressWarnings("unchecked")
+       protected <T> Class<T> loadClass(String className) throws 
ClassNotFoundException {
+               ClassLoader loader = this.getClass().getClassLoader();
+               try {
+                       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 (ClassLoader l : classLoaders) {
+                               try {
+                                       return (Class<T>) 
l.loadClass(className);
+                               } catch (ClassNotFoundException xx) {
+                                       // continue
+                               }
+                       }
+                       /* Give up. */
+                       throw x;
+               }
+       }
+
+       /**
+        * Loads the named class using a specified class loader.
+        *
+        * @param className the name of the class to load.
+        * @param loader    the loader to use.
+        * @return {@inheritDoc} the loaded class.
+        * @throws ClassNotFoundException if the class was not found.
+        */
+       @SuppressWarnings("unchecked")
+       protected <T> Class<T> loadClass(String className, ClassLoader loader) 
throws ClassNotFoundException {
+               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 
factory is
+        * specified but a default factory is, will use the default factory.
+        *
+        * @param className the name of the class to load.
+        * @return {@inheritDoc} the factory, or null if not specified and no 
default.
+        * @throws FactoryException if instantiation of the factory fails.
+        */
+       @SuppressWarnings("unchecked")
+       protected <T> Factory<T> getFactory(String className) throws 
FactoryException {
+               Factory<T> factory = (Factory<T>) 
objectFactories.get(className);
+               if (factory == null) {
+                       // No named factory for this; try the default, if one
+                       // exists.
+                       factory = (Factory<T>) 
objectFactories.get(DEFAULT_FACTORY);
+               }
+               if (factory == null) {
+                       /* Not yet instantiated... */
+                       String factoryClass = 
objectFactoryClasses.get(className);
+                       if (factoryClass == null) {
+                               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;
+       }
+
+       // ---------------- Avalon Lifecycle Methods ---------------------
+
+       /* (non-Javadoc)
+        * Avalon component lifecycle method
+        * @see 
org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
+        */
+       @Override
+       public void configure(Configuration conf) throws ConfigurationException 
{
+               final Configuration[] loaders = conf.getChildren(CLASS_LOADER);
+               if (loaders != null) {
+                       loaderNames = new String[loaders.length];
+                       for (int i = 0; i < loaders.length; i++) {
+                               loaderNames[i] = loaders[i].getValue();
+                       }
+               }
+
+               final Configuration factories = conf.getChild(OBJECT_FACTORY, 
false);
+               if (factories != null) {
+                       // Store the factory to the table as a string and
+                       // instantiate it by using the service when needed.
+                       Configuration[] nameVal = factories.getChildren();
+                       for (Configuration entry : nameVal)
+                               objectFactoryClasses.put(entry.getName(), 
entry.getValue());
+
+               }
+       }
+
+       /**
+        * Avalon component lifecycle method Initializes the service by loading 
default
+        * class loaders and customized object factories.
+        *
+        * @throws Exception if initialization fails.
+        */
+       @Override
+       public void initialize() throws Exception {
+               if (loaderNames != null) {
+                       for (String className : loaderNames) {
+                               try {
+                                       ClassLoader loader = (ClassLoader) 
loadClass(className).newInstance();
+                                       classLoaders.add(loader);
+                               } catch (Exception x) {
+                                       throw new Exception("No such class 
loader '" + className + "' 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/FactoryException.java 
b/src/java/org/apache/fulcrum/factory/FactoryException.java
index ed234ae..1e1cae1 100644
--- a/src/java/org/apache/fulcrum/factory/FactoryException.java
+++ b/src/java/org/apache/fulcrum/factory/FactoryException.java
@@ -19,54 +19,50 @@ package org.apache.fulcrum.factory;
  * under the License.
  */
 
-import java.lang.Exception;
-
 /**
  * Exception thrown when there is a problem with the FactoryService
  *
  * @author <a href="mailto:[email protected]";>Eric Pugh</a>
  * @version $Id$
  */
-public class FactoryException extends Exception
-{
-    /**
-     * Serial number
-     */
-    private static final long serialVersionUID = 8954422192583295720L;
+public class FactoryException extends Exception {
+       /**
+        * Serial number
+        */
+       private static final long serialVersionUID = 8954422192583295720L;
 
-    /**
-     * Default constructor
-     */
-    public FactoryException()
-    {
-        super();
-    }
+       /**
+        * Default constructor
+        */
+       public FactoryException() {
+               super();
+       }
 
-    /**
-     * {@link java.lang.Exception#Exception(String, Throwable)}
-     * @param message the message
-     * @param e the exception
-     */
-    public FactoryException(String message, Throwable e)
-    {
-        super(message, e);
-    }
+       /**
+        * {@link java.lang.Exception#Exception(String, Throwable)}
+        * 
+        * @param message the message
+        * @param e       the exception
+        */
+       public FactoryException(String message, Throwable e) {
+               super(message, e);
+       }
 
-    /**
-     * {@link java.lang.Exception#Exception(Throwable)}
-     * @param e the exception to bubble up
-     */
-    public FactoryException(Throwable e)
-    {
-        super(e);
-    }
+       /**
+        * {@link java.lang.Exception#Exception(Throwable)}
+        * 
+        * @param e the exception to bubble up
+        */
+       public FactoryException(Throwable e) {
+               super(e);
+       }
 
-    /**
-     * {@link java.lang.Exception#Exception(String)}
-     * @param msg the message to bubble up
-     */
-    public FactoryException(String msg)
-    {
-        super(msg);
-    }
+       /**
+        * {@link java.lang.Exception#Exception(String)}
+        * 
+        * @param msg the message to bubble up
+        */
+       public FactoryException(String msg) {
+               super(msg);
+       }
 }

Reply via email to