Refactor functors from inner classes to subpackage

git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/collections/trunk@131368 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Stephen Colebourne 2003-11-23 17:48:20 +00:00
parent 3c81ef8c39
commit c63ea40c90
6 changed files with 570 additions and 274 deletions

View File

@ -1,5 +1,5 @@
/*
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/FactoryUtils.java,v 1.10 2003/11/23 17:01:36 scolebourne Exp $
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/FactoryUtils.java,v 1.11 2003/11/23 17:48:20 scolebourne Exp $
* ====================================================================
*
* The Apache Software License, Version 1.1
@ -57,18 +57,10 @@
*/
package org.apache.commons.collections;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.apache.commons.collections.functors.ConstantFactory;
import org.apache.commons.collections.functors.InstantiateFactory;
import org.apache.commons.collections.functors.ExceptionFactory;
import org.apache.commons.collections.functors.FunctorException;
import org.apache.commons.collections.functors.PrototypeFactory;
/**
* <code>FactoryUtils</code> provides reference implementations and utilities
@ -83,17 +75,12 @@ import org.apache.commons.collections.functors.FunctorException;
* All the supplied factories are Serializable.
*
* @since Commons Collections 3.0
* @version $Revision: 1.10 $ $Date: 2003/11/23 17:01:36 $
* @version $Revision: 1.11 $ $Date: 2003/11/23 17:48:20 $
*
* @author Stephen Colebourne
*/
public class FactoryUtils {
/**
* A factory that always returns null
*/
private static final Factory NULL_FACTORY = new ConstantFactory(null);
/**
* This class is not normally instantiated.
*/
@ -118,7 +105,7 @@ public class FactoryUtils {
* @return the factory
*/
public static Factory nullFactory() {
return NULL_FACTORY;
return ConstantFactory.NULL_INSTANCE;
}
/**
@ -131,7 +118,7 @@ public class FactoryUtils {
* @return the <code>constant</code> factory.
*/
public static Factory constantFactory(Object constantToReturn) {
return new ConstantFactory(constantToReturn);
return ConstantFactory.getInstance(constantToReturn);
}
/**
@ -150,25 +137,7 @@ public class FactoryUtils {
* @throws IllegalArgumentException if the prototype cannot be cloned
*/
public static Factory prototypeFactory(Object prototype) {
if (prototype == null) {
throw new IllegalArgumentException("The prototype must not be null");
}
try {
prototype.getClass().getMethod("clone", null);
return new PrototypeCloneFactory(prototype);
} catch (NoSuchMethodException ex) {
try {
prototype.getClass().getConstructor(new Class[] { prototype.getClass()});
return new ReflectionFactory(prototype.getClass(), new Class[] { prototype.getClass()}, new Object[] { prototype });
} catch (NoSuchMethodException ex2) {
if (prototype instanceof Serializable) {
return new PrototypeSerializationFactory((Serializable) prototype);
}
}
}
throw new IllegalArgumentException("The prototype must be cloneable via a public clone method");
return PrototypeFactory.getInstance(prototype);
}
/**
@ -179,8 +148,8 @@ public class FactoryUtils {
* @return the <code>reflection</code> factory
* @throws IllegalArgumentException if the classToInstantiate is null
*/
public static Factory reflectionFactory(Class classToInstantiate) {
return new ReflectionFactory(classToInstantiate);
public static Factory instantiateFactory(Class classToInstantiate) {
return InstantiateFactory.getInstance(classToInstantiate, null, null);
}
/**
@ -195,228 +164,8 @@ public class FactoryUtils {
* @throws IllegalArgumentException if the paramTypes and args don't match
* @throws IllegalArgumentException if the constructor doesn't exist
*/
public static Factory reflectionFactory(Class classToInstantiate, Class[] paramTypes, Object[] args) {
return new ReflectionFactory(classToInstantiate, paramTypes, args);
}
// ConstantFactory
//----------------------------------------------------------------------------------
/**
* ConstantFactory returns the same instance each time.
*/
private static class ConstantFactory implements Factory, Serializable {
/** The constant to return each time */
private final Object iConstant;
/**
* Constructor to store constant
*/
private ConstantFactory(Object constant) {
super();
iConstant = constant;
}
/**
* Always return constant
*/
public Object create() {
return iConstant;
}
}
// PrototypeCloneFactory
//----------------------------------------------------------------------------------
/**
* PrototypeCloneFactory creates objects by copying a prototype using the clone method.
*/
private static class PrototypeCloneFactory implements Factory, Serializable {
/** The object to clone each time */
private final Object iPrototype;
/** The method used to clone */
private transient Method iCloneMethod;
/**
* Constructor to store prototype
*/
private PrototypeCloneFactory(Object prototype) {
super();
if (prototype == null) {
throw new IllegalArgumentException("PrototypeCloneFactory: The prototype must not be null");
}
iPrototype = prototype;
findCloneMethod();
}
/**
* Find the Clone method for the class specified.
*/
private void findCloneMethod() {
try {
iCloneMethod = iPrototype.getClass().getMethod("clone", null);
} catch (NoSuchMethodException ex) {
throw new IllegalArgumentException("PrototypeCloneFactory: The clone method must exist and be public ");
}
}
/**
* Return clone of prototype
*/
public Object create() {
// needed for post-serialization
if (iCloneMethod == null) {
findCloneMethod();
}
try {
return iCloneMethod.invoke(iPrototype, null);
} catch (IllegalAccessException ex) {
throw new FunctorException("PrototypeCloneFactory: Clone method must be public", ex);
} catch (InvocationTargetException ex) {
throw new FunctorException("PrototypeCloneFactory: Clone method threw an exception", ex);
}
}
}
// PrototypeSerializationFactory
//----------------------------------------------------------------------------------
/**
* PrototypeSerializationFactory creates objects by cloning a prototype using serialization.
*/
private static class PrototypeSerializationFactory implements Factory, Serializable {
/** The object to clone via serialization each time */
private final Serializable iPrototype;
/**
* Constructor to store prototype
*/
private PrototypeSerializationFactory(Serializable prototype) {
super();
if (prototype == null) {
throw new IllegalArgumentException("PrototypeSerializationFactory: The prototype must not be null");
}
iPrototype = prototype;
}
/**
* Return clone of prototype by serialization
*/
public Object create() {
ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
ByteArrayInputStream bais = null;
try {
ObjectOutputStream out = new ObjectOutputStream(baos);
out.writeObject(iPrototype);
bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream in = new ObjectInputStream(bais);
return in.readObject();
} catch (ClassNotFoundException ex) {
throw new FunctorException(ex);
} catch (IOException ex) {
throw new FunctorException(ex);
} finally {
try {
if (bais != null) {
bais.close();
}
} catch (IOException ignored) {}
try {
if (baos != null) {
baos.close();
}
} catch (IOException ignored) {}
}
}
}
// ReflectionFactory
//----------------------------------------------------------------------------------
/**
* ReflectionFactory creates objects using reflection.
*/
private static class ReflectionFactory implements Factory, Serializable {
/** The class to create */
private final Class iClassToInstantiate;
/** The constructor parameter types */
private final Class[] iParamTypes;
/** The constructor arguments */
private final Object[] iArgs;
/** The constructor */
private transient Constructor iConstructor = null;
/**
* Constructor
*/
public ReflectionFactory(Class classToInstantiate) {
this(classToInstantiate, null, null);
}
/* builds the object factory taking all the options needed to provide
* arguments to a constructor.
*/
public ReflectionFactory(Class classToInstantiate, Class[] paramTypes, Object[] args) {
super();
if (classToInstantiate == null) {
throw new IllegalArgumentException("ReflectionFactory: The class to instantiate must not be null");
}
if (((paramTypes == null) && (args != null))
|| ((paramTypes != null) && (args == null))
|| ((paramTypes != null) && (args != null) && (paramTypes.length != args.length))) {
throw new IllegalArgumentException("ReflectionFactory: The parameter types must match the arguments");
}
iClassToInstantiate = classToInstantiate;
if ((paramTypes == null) && (args == null)) {
iParamTypes = null;
iArgs = null;
} else {
iParamTypes = (Class[]) paramTypes.clone();
iArgs = (Object[]) args.clone();
}
findConstructor();
}
/**
* Find the Constructor for the class specified.
*/
private void findConstructor() {
try {
iConstructor = iClassToInstantiate.getConstructor(iParamTypes);
} catch (NoSuchMethodException ex) {
throw new IllegalArgumentException("ReflectionFactory: The constructor must exist and be public ");
}
}
/**
* Create the object using a constructor
*/
public Object create() {
// needed for post-serialization
if (iConstructor == null) {
findConstructor();
}
try {
return iConstructor.newInstance(iArgs);
} catch (InstantiationException ex) {
throw new FunctorException("ReflectionFactory: InstantiationException", ex);
} catch (IllegalAccessException ex) {
throw new FunctorException("ReflectionFactory: Constructor must be public", ex);
} catch (InvocationTargetException ex) {
throw new FunctorException("ReflectionFactory: Constructor threw an exception", ex);
}
}
public static Factory instantiateFactory(Class classToInstantiate, Class[] paramTypes, Object[] args) {
return InstantiateFactory.getInstance(classToInstantiate, paramTypes, args);
}
}

View File

@ -1,5 +1,5 @@
/*
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/TransformerUtils.java,v 1.7 2003/11/23 17:01:36 scolebourne Exp $
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/TransformerUtils.java,v 1.8 2003/11/23 17:48:20 scolebourne Exp $
* ====================================================================
*
* The Apache Software License, Version 1.1
@ -90,7 +90,7 @@ import org.apache.commons.collections.functors.FunctorException;
* All the supplied transformers are Serializable.
*
* @since Commons Collections 3.0
* @version $Revision: 1.7 $ $Date: 2003/11/23 17:01:36 $
* @version $Revision: 1.8 $ $Date: 2003/11/23 17:48:20 $
*
* @author Stephen Colebourne
* @author James Carman
@ -835,7 +835,7 @@ public class TransformerUtils {
"InstantiateTransformer: Input object was not an instanceof Class, it was a "
+ (input == null ? "null object" : input.getClass().getName()));
}
return FactoryUtils.reflectionFactory((Class) input, iParamTypes, iArgs).create();
return FactoryUtils.instantiateFactory((Class) input, iParamTypes, iArgs).create();
} catch (IllegalArgumentException ex) {
throw new FunctorException("InstantiateTransformer", ex);

View File

@ -0,0 +1,118 @@
/*
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/functors/ConstantFactory.java,v 1.1 2003/11/23 17:48:19 scolebourne Exp $
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001-2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowledgement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgement may appear in the software itself,
* if and wherever such third-party acknowledgements normally appear.
*
* 4. The names "The Jakarta Project", "Commons", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.commons.collections.functors;
import java.io.Serializable;
import org.apache.commons.collections.Factory;
/**
* Factory implementation that returns the same constant each time.
* <p>
* No check is made that the object is immutable. In general, only immutable
* objects should use the constant factory. Mutable objects should
* use the prototype factory.
*
* @since Commons Collections 3.0
* @version $Revision: 1.1 $ $Date: 2003/11/23 17:48:19 $
*
* @author Stephen Colebourne
*/
public class ConstantFactory implements Factory, Serializable {
/** Serial version UID */
static final long serialVersionUID = -3520677225766901240L;
/** Returns null each time */
public static final Factory NULL_INSTANCE = new ConstantFactory(null);
/** The closures to call in turn */
private final Object iConstant;
/**
* Factory method that performs validation.
*
* @param constantToReturn the constant object to return each time in the factory
* @return the <code>constant</code> factory.
*/
public static Factory getInstance(Object constantToReturn) {
if (constantToReturn == null) {
return NULL_INSTANCE;
}
return new ConstantFactory(constantToReturn);
}
/**
* Constructor that performs no validation.
* Use <code>getInstance</code> if you want that.
*
* @param constantToReturn the constant to return each time
*/
public ConstantFactory(Object constantToReturn) {
super();
iConstant = constantToReturn;
}
/**
* Always return constant
*/
public Object create() {
return iConstant;
}
}

View File

@ -0,0 +1,178 @@
/*
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/functors/InstantiateFactory.java,v 1.1 2003/11/23 17:48:19 scolebourne Exp $
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001-2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowledgement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgement may appear in the software itself,
* if and wherever such third-party acknowledgements normally appear.
*
* 4. The names "The Jakarta Project", "Commons", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.commons.collections.functors;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import org.apache.commons.collections.Factory;
/**
* Factory implementation that creates a new object instance by reflection.
*
* @since Commons Collections 3.0
* @version $Revision: 1.1 $ $Date: 2003/11/23 17:48:19 $
*
* @author Stephen Colebourne
*/
public class InstantiateFactory implements Factory, Serializable {
/** The serial version */
static final long serialVersionUID = -7732226881069447957L;
/** The class to create */
private final Class iClassToInstantiate;
/** The constructor parameter types */
private final Class[] iParamTypes;
/** The constructor arguments */
private final Object[] iArgs;
/** The constructor */
private transient Constructor iConstructor = null;
/**
* Factory method that performs validation.
*
* @param classToInstantiate the class to instantiate, not null
* @param paramTypes the constructor parameter types
* @param args the constructor arguments
*/
public static Factory getInstance(Class classToInstantiate, Class[] paramTypes, Object[] args) {
if (classToInstantiate == null) {
throw new IllegalArgumentException("Class to instantiate must not be null");
}
if (((paramTypes == null) && (args != null))
|| ((paramTypes != null) && (args == null))
|| ((paramTypes != null) && (args != null) && (paramTypes.length != args.length))) {
throw new IllegalArgumentException("Parameter types must match the arguments");
}
if (paramTypes == null || paramTypes.length == 0) {
paramTypes = null;
args = null;
} else {
paramTypes = (Class[]) paramTypes.clone();
args = (Object[]) args.clone();
}
return new InstantiateFactory(classToInstantiate, paramTypes, args);
}
/**
* Constructor that performs no validation.
* Use <code>getInstance</code> if you want that.
*
* @param classToInstantiate the class to instantiate
*/
public InstantiateFactory(Class classToInstantiate) {
super();
iClassToInstantiate = classToInstantiate;
iParamTypes = null;
iArgs = null;
findConstructor();
}
/**
* Constructor that performs no validation.
* Use <code>getInstance</code> if you want that.
*
* @param classToInstantiate the class to instantiate
* @param paramTypes the constructor parameter types, not cloned
* @param args the constructor arguments, not cloned
*/
public InstantiateFactory(Class classToInstantiate, Class[] paramTypes, Object[] args) {
super();
iClassToInstantiate = classToInstantiate;
iParamTypes = paramTypes;
iArgs = args;
findConstructor();
}
/**
* Find the Constructor for the class specified.
*/
private void findConstructor() {
try {
iConstructor = iClassToInstantiate.getConstructor(iParamTypes);
} catch (NoSuchMethodException ex) {
throw new IllegalArgumentException("InstantiateFactory: The constructor must exist and be public ");
}
}
/**
* Create the object using a constructor
*/
public Object create() {
// needed for post-serialization
if (iConstructor == null) {
findConstructor();
}
try {
return iConstructor.newInstance(iArgs);
} catch (InstantiationException ex) {
throw new FunctorException("InstantiateFactory: InstantiationException", ex);
} catch (IllegalAccessException ex) {
throw new FunctorException("InstantiateFactory: Constructor must be public", ex);
} catch (InvocationTargetException ex) {
throw new FunctorException("InstantiateFactory: Constructor threw an exception", ex);
}
}
}

View File

@ -0,0 +1,251 @@
/*
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/functors/PrototypeFactory.java,v 1.1 2003/11/23 17:48:19 scolebourne Exp $
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001-2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowledgement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgement may appear in the software itself,
* if and wherever such third-party acknowledgements normally appear.
*
* 4. The names "The Jakarta Project", "Commons", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.commons.collections.functors;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.apache.commons.collections.Factory;
/**
* Factory implementation that creates a new instance each time based on a prototype.
*
* @since Commons Collections 3.0
* @version $Revision: 1.1 $ $Date: 2003/11/23 17:48:19 $
*
* @author Stephen Colebourne
*/
public class PrototypeFactory {
/**
* Factory method that performs validation.
* <p>
* Creates a Factory that will return a clone of the same prototype object
* each time the factory is used. The prototype will be cloned using one of these
* techniques (in order):
* <ul>
* <li>public clone method
* <li>public copy constructor
* <li>serialization clone
* <ul>
*
* @param prototype the object to clone each time in the factory
* @return the <code>prototype</code> factory
* @throws IllegalArgumentException if the prototype is null
* @throws IllegalArgumentException if the prototype cannot be cloned
*/
public static Factory getInstance(Object prototype) {
if (prototype == null) {
throw new IllegalArgumentException("The prototype must not be null");
}
try {
prototype.getClass().getMethod("clone", null);
return new PrototypeCloneFactory(prototype);
} catch (NoSuchMethodException ex) {
try {
prototype.getClass().getConstructor(new Class[] { prototype.getClass()});
return new InstantiateFactory(
prototype.getClass(),
new Class[] { prototype.getClass()},
new Object[] { prototype });
} catch (NoSuchMethodException ex2) {
if (prototype instanceof Serializable) {
return new PrototypeSerializationFactory((Serializable) prototype);
}
}
}
throw new IllegalArgumentException("The prototype must be cloneable via a public clone method");
}
/**
* Constructor that performs no validation.
* Use <code>getInstance</code> if you want that.
*
* @param constantToReturn the constant to return each time
*/
private PrototypeFactory() {
}
// PrototypeCloneFactory
//-----------------------------------------------------------------------
/**
* PrototypeCloneFactory creates objects by copying a prototype using the clone method.
*/
static class PrototypeCloneFactory implements Factory, Serializable {
/** The serial version */
static final long serialVersionUID = 5604271422565175555L;
/** The object to clone each time */
private final Object iPrototype;
/** The method used to clone */
private transient Method iCloneMethod;
/**
* Constructor to store prototype
*/
private PrototypeCloneFactory(Object prototype) {
super();
if (prototype == null) {
throw new IllegalArgumentException("PrototypeCloneFactory: The prototype must not be null");
}
iPrototype = prototype;
findCloneMethod();
}
/**
* Find the Clone method for the class specified.
*/
private void findCloneMethod() {
try {
iCloneMethod = iPrototype.getClass().getMethod("clone", null);
} catch (NoSuchMethodException ex) {
throw new IllegalArgumentException("PrototypeCloneFactory: The clone method must exist and be public ");
}
}
/**
* Return clone of prototype
*/
public Object create() {
// needed for post-serialization
if (iCloneMethod == null) {
findCloneMethod();
}
try {
return iCloneMethod.invoke(iPrototype, null);
} catch (IllegalAccessException ex) {
throw new FunctorException("PrototypeCloneFactory: Clone method must be public", ex);
} catch (InvocationTargetException ex) {
throw new FunctorException("PrototypeCloneFactory: Clone method threw an exception", ex);
}
}
}
// PrototypeSerializationFactory
//-----------------------------------------------------------------------
/**
* PrototypeSerializationFactory creates objects by cloning a prototype using serialization.
*/
static class PrototypeSerializationFactory implements Factory, Serializable {
/** The serial version */
static final long serialVersionUID = -8704966966139178833L;
/** The object to clone via serialization each time */
private final Serializable iPrototype;
/**
* Constructor to store prototype
*/
private PrototypeSerializationFactory(Serializable prototype) {
super();
if (prototype == null) {
throw new IllegalArgumentException("PrototypeSerializationFactory: The prototype must not be null");
}
iPrototype = prototype;
}
/**
* Return clone of prototype by serialization
*/
public Object create() {
ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
ByteArrayInputStream bais = null;
try {
ObjectOutputStream out = new ObjectOutputStream(baos);
out.writeObject(iPrototype);
bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream in = new ObjectInputStream(bais);
return in.readObject();
} catch (ClassNotFoundException ex) {
throw new FunctorException(ex);
} catch (IOException ex) {
throw new FunctorException(ex);
} finally {
try {
if (bais != null) {
bais.close();
}
} catch (IOException ignored) {
}
try {
if (baos != null) {
baos.close();
}
} catch (IOException ignored) {
}
}
}
}
}

View File

@ -1,5 +1,5 @@
/*
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/test/org/apache/commons/collections/TestFactoryUtils.java,v 1.6 2003/11/23 14:41:27 scolebourne Exp $
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/test/org/apache/commons/collections/TestFactoryUtils.java,v 1.7 2003/11/23 17:48:19 scolebourne Exp $
* ====================================================================
*
* The Apache Software License, Version 1.1
@ -72,7 +72,7 @@ import junit.textui.TestRunner;
* Tests the org.apache.commons.collections.FactoryUtils class.
*
* @since Commons Collections 3.0
* @version $Revision: 1.6 $ $Date: 2003/11/23 14:41:27 $
* @version $Revision: 1.7 $ $Date: 2003/11/23 17:48:19 $
*
* @author Stephen Colebourne
*/
@ -267,12 +267,12 @@ public class TestFactoryUtils extends junit.framework.TestCase {
}
}
// reflectionFactory
// instantiateFactory
//------------------------------------------------------------------
public void testReflectionFactoryNull() {
try {
Factory factory = FactoryUtils.reflectionFactory(null);
Factory factory = FactoryUtils.instantiateFactory(null);
} catch (IllegalArgumentException ex) {
return;
@ -281,7 +281,7 @@ public class TestFactoryUtils extends junit.framework.TestCase {
}
public void testReflectionFactorySimple() {
Factory factory = FactoryUtils.reflectionFactory(Mock3.class);
Factory factory = FactoryUtils.instantiateFactory(Mock3.class);
assertNotNull(factory);
Object created = factory.create();
assertEquals(0, ((Mock3) created).getValue());
@ -291,7 +291,7 @@ public class TestFactoryUtils extends junit.framework.TestCase {
public void testReflectionFactoryMismatch() {
try {
Factory factory = FactoryUtils.reflectionFactory(Date.class, null, new Object[] {null});
Factory factory = FactoryUtils.instantiateFactory(Date.class, null, new Object[] {null});
} catch (IllegalArgumentException ex) {
return;
@ -301,7 +301,7 @@ public class TestFactoryUtils extends junit.framework.TestCase {
public void testReflectionFactoryNoConstructor() {
try {
Factory factory = FactoryUtils.reflectionFactory(Date.class, new Class[] {Long.class}, new Object[] {null});
Factory factory = FactoryUtils.instantiateFactory(Date.class, new Class[] {Long.class}, new Object[] {null});
} catch (IllegalArgumentException ex) {
return;
@ -312,7 +312,7 @@ public class TestFactoryUtils extends junit.framework.TestCase {
public void testReflectionFactoryComplex() {
TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
// 2nd Jan 1970
Factory factory = FactoryUtils.reflectionFactory(Date.class,
Factory factory = FactoryUtils.instantiateFactory(Date.class,
new Class[] {Integer.TYPE, Integer.TYPE, Integer.TYPE},
new Object[] {new Integer(70), new Integer(0), new Integer(2)});
assertNotNull(factory);