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); + } }
