View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.collections.functors;
18  
19  import java.io.Serializable;
20  import java.lang.reflect.Constructor;
21  import java.lang.reflect.InvocationTargetException;
22  
23  import org.apache.commons.collections.Factory;
24  import org.apache.commons.collections.FunctorException;
25  
26  /**
27   * Factory implementation that creates a new object instance by reflection.
28   *
29   * @since 3.0
30   * @version $Id: InstantiateFactory.java 1437018 2013-01-22 16:08:48Z tn $
31   */
32  public class InstantiateFactory<T> implements Factory<T>, Serializable {
33  
34      /** The serial version */
35      private static final long serialVersionUID = -7732226881069447957L;
36  
37      /** The class to create */
38      private final Class<T> iClassToInstantiate;
39      /** The constructor parameter types */
40      private final Class<?>[] iParamTypes;
41      /** The constructor arguments */
42      private final Object[] iArgs;
43      /** The constructor */
44      private transient Constructor<T> iConstructor = null;
45  
46      /**
47       * Factory method that performs validation.
48       * 
49       * @param <T>  the type the factory creates
50       * @param classToInstantiate  the class to instantiate, not null
51       * @param paramTypes  the constructor parameter types, cloned
52       * @param args  the constructor arguments, cloned
53       * @return a new instantiate factory
54       */
55      public static <T> Factory<T> instantiateFactory(final Class<T> classToInstantiate,
56                                                      Class<?>[] paramTypes,
57                                                      Object[] args) {
58          if (classToInstantiate == null) {
59              throw new IllegalArgumentException("Class to instantiate must not be null");
60          }
61          if (paramTypes == null && args != null
62              || paramTypes != null && args == null
63              || paramTypes != null && args != null && paramTypes.length != args.length) {
64              throw new IllegalArgumentException("Parameter types must match the arguments");
65          }
66  
67          if (paramTypes == null || paramTypes.length == 0) {
68              return new InstantiateFactory<T>(classToInstantiate);
69          }
70          return new InstantiateFactory<T>(classToInstantiate, paramTypes, args);
71      }
72  
73      /**
74       * Constructor that performs no validation.
75       * Use <code>getInstance</code> if you want that.
76       * 
77       * @param classToInstantiate  the class to instantiate
78       */
79      public InstantiateFactory(final Class<T> classToInstantiate) {
80          super();
81          iClassToInstantiate = classToInstantiate;
82          iParamTypes = null;
83          iArgs = null;
84          findConstructor();
85      }
86  
87      /**
88       * Constructor that performs no validation.
89       * Use <code>getInstance</code> if you want that.
90       * 
91       * @param classToInstantiate  the class to instantiate
92       * @param paramTypes  the constructor parameter types, cloned
93       * @param args  the constructor arguments, cloned
94       */
95      public InstantiateFactory(final Class<T> classToInstantiate, final Class<?>[] paramTypes, final Object[] args) {
96          super();
97          iClassToInstantiate = classToInstantiate;
98          iParamTypes = paramTypes.clone();
99          iArgs = args.clone();
100         findConstructor();
101     }
102 
103     /**
104      * Find the Constructor for the class specified.
105      */
106     private void findConstructor() {
107         try {
108             iConstructor = iClassToInstantiate.getConstructor(iParamTypes);
109         } catch (final NoSuchMethodException ex) {
110             throw new IllegalArgumentException("InstantiateFactory: The constructor must exist and be public ");
111         }
112     }
113 
114     /**
115      * Creates an object using the stored constructor.
116      * 
117      * @return the new object
118      */
119     public T create() {
120         // needed for post-serialization
121         if (iConstructor == null) {
122             findConstructor();
123         }
124 
125         try {
126             return iConstructor.newInstance(iArgs);
127         } catch (final InstantiationException ex) {
128             throw new FunctorException("InstantiateFactory: InstantiationException", ex);
129         } catch (final IllegalAccessException ex) {
130             throw new FunctorException("InstantiateFactory: Constructor must be public", ex);
131         } catch (final InvocationTargetException ex) {
132             throw new FunctorException("InstantiateFactory: Constructor threw an exception", ex);
133         }
134     }
135     
136 }