001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.commons.collections.functors;
018
019 import java.io.Serializable;
020 import java.lang.reflect.Constructor;
021 import java.lang.reflect.InvocationTargetException;
022
023 import org.apache.commons.collections.Factory;
024 import org.apache.commons.collections.FunctorException;
025
026 /**
027 * Factory implementation that creates a new object instance by reflection.
028 *
029 * @since Commons Collections 3.0
030 * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $
031 *
032 * @author Stephen Colebourne
033 */
034 public class InstantiateFactory implements Factory, Serializable {
035
036 /** The serial version */
037 private static final long serialVersionUID = -7732226881069447957L;
038
039 /** The class to create */
040 private final Class iClassToInstantiate;
041 /** The constructor parameter types */
042 private final Class[] iParamTypes;
043 /** The constructor arguments */
044 private final Object[] iArgs;
045 /** The constructor */
046 private transient Constructor iConstructor = null;
047
048 /**
049 * Factory method that performs validation.
050 *
051 * @param classToInstantiate the class to instantiate, not null
052 * @param paramTypes the constructor parameter types
053 * @param args the constructor arguments
054 * @return a new instantiate factory
055 */
056 public static Factory getInstance(Class classToInstantiate, Class[] paramTypes, Object[] args) {
057 if (classToInstantiate == null) {
058 throw new IllegalArgumentException("Class to instantiate must not be null");
059 }
060 if (((paramTypes == null) && (args != null))
061 || ((paramTypes != null) && (args == null))
062 || ((paramTypes != null) && (args != null) && (paramTypes.length != args.length))) {
063 throw new IllegalArgumentException("Parameter types must match the arguments");
064 }
065
066 if (paramTypes == null || paramTypes.length == 0) {
067 return new InstantiateFactory(classToInstantiate);
068 } else {
069 paramTypes = (Class[]) paramTypes.clone();
070 args = (Object[]) args.clone();
071 return new InstantiateFactory(classToInstantiate, paramTypes, args);
072 }
073 }
074
075 /**
076 * Constructor that performs no validation.
077 * Use <code>getInstance</code> if you want that.
078 *
079 * @param classToInstantiate the class to instantiate
080 */
081 public InstantiateFactory(Class classToInstantiate) {
082 super();
083 iClassToInstantiate = classToInstantiate;
084 iParamTypes = null;
085 iArgs = null;
086 findConstructor();
087 }
088
089 /**
090 * Constructor that performs no validation.
091 * Use <code>getInstance</code> if you want that.
092 *
093 * @param classToInstantiate the class to instantiate
094 * @param paramTypes the constructor parameter types, not cloned
095 * @param args the constructor arguments, not cloned
096 */
097 public InstantiateFactory(Class classToInstantiate, Class[] paramTypes, Object[] args) {
098 super();
099 iClassToInstantiate = classToInstantiate;
100 iParamTypes = paramTypes;
101 iArgs = args;
102 findConstructor();
103 }
104
105 /**
106 * Find the Constructor for the class specified.
107 */
108 private void findConstructor() {
109 try {
110 iConstructor = iClassToInstantiate.getConstructor(iParamTypes);
111
112 } catch (NoSuchMethodException ex) {
113 throw new IllegalArgumentException("InstantiateFactory: The constructor must exist and be public ");
114 }
115 }
116
117 /**
118 * Creates an object using the stored constructor.
119 *
120 * @return the new object
121 */
122 public Object create() {
123 // needed for post-serialization
124 if (iConstructor == null) {
125 findConstructor();
126 }
127
128 try {
129 return iConstructor.newInstance(iArgs);
130
131 } catch (InstantiationException ex) {
132 throw new FunctorException("InstantiateFactory: InstantiationException", ex);
133 } catch (IllegalAccessException ex) {
134 throw new FunctorException("InstantiateFactory: Constructor must be public", ex);
135 } catch (InvocationTargetException ex) {
136 throw new FunctorException("InstantiateFactory: Constructor threw an exception", ex);
137 }
138 }
139
140 }