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 <[email protected]> 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:[email protected]">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)); - } }
