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 */ 017package org.apache.commons.collections4.functors; 018 019import java.io.Serializable; 020import java.lang.reflect.Constructor; 021import java.lang.reflect.InvocationTargetException; 022 023import org.apache.commons.collections4.Factory; 024import org.apache.commons.collections4.FunctorException; 025 026/** 027 * Factory implementation that creates a new object instance by reflection. 028 * 029 * @since 3.0 030 * @version $Id: InstantiateFactory.html 972421 2015-11-14 20:00:04Z tn $ 031 */ 032public class InstantiateFactory<T> implements Factory<T>, Serializable { 033 034 /** The serial version */ 035 private static final long serialVersionUID = -7732226881069447957L; 036 037 /** The class to create */ 038 private final Class<T> iClassToInstantiate; 039 /** The constructor parameter types */ 040 private final Class<?>[] iParamTypes; 041 /** The constructor arguments */ 042 private final Object[] iArgs; 043 /** The constructor */ 044 private transient Constructor<T> iConstructor = null; 045 046 /** 047 * Factory method that performs validation. 048 * 049 * @param <T> the type the factory creates 050 * @param classToInstantiate the class to instantiate, not null 051 * @param paramTypes the constructor parameter types, cloned 052 * @param args the constructor arguments, cloned 053 * @return a new instantiate factory 054 */ 055 public static <T> Factory<T> instantiateFactory(final Class<T> classToInstantiate, 056 final Class<?>[] paramTypes, 057 final Object[] args) { 058 if (classToInstantiate == null) { 059 throw new IllegalArgumentException("Class to instantiate must not be null"); 060 } 061 if (paramTypes == null && args != null 062 || paramTypes != null && args == null 063 || paramTypes != null && args != null && paramTypes.length != args.length) { 064 throw new IllegalArgumentException("Parameter types must match the arguments"); 065 } 066 067 if (paramTypes == null || paramTypes.length == 0) { 068 return new InstantiateFactory<T>(classToInstantiate); 069 } 070 return new InstantiateFactory<T>(classToInstantiate, paramTypes, args); 071 } 072 073 /** 074 * Constructor that performs no validation. 075 * Use <code>instantiateFactory</code> if you want that. 076 * 077 * @param classToInstantiate the class to instantiate 078 */ 079 public InstantiateFactory(final Class<T> classToInstantiate) { 080 super(); 081 iClassToInstantiate = classToInstantiate; 082 iParamTypes = null; 083 iArgs = null; 084 findConstructor(); 085 } 086 087 /** 088 * Constructor that performs no validation. 089 * Use <code>instantiateFactory</code> if you want that. 090 * 091 * @param classToInstantiate the class to instantiate 092 * @param paramTypes the constructor parameter types, cloned 093 * @param args the constructor arguments, cloned 094 */ 095 public InstantiateFactory(final Class<T> classToInstantiate, final Class<?>[] paramTypes, final Object[] args) { 096 super(); 097 iClassToInstantiate = classToInstantiate; 098 iParamTypes = paramTypes.clone(); 099 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}