1 /** 2 * Redistribution and use of this software and associated documentation ("Software"), with or 3 * without modification, are permitted provided that the following conditions are met: 4 * 5 * 1. Redistributions of source code must retain copyright statements and notices. Redistributions 6 * must also contain a copy of this document. 7 * 8 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 9 * conditions and the following disclaimer in the documentation and/or other materials provided with 10 * the distribution. 11 * 12 * 3. The name "Exolab" must not be used to endorse or promote products derived from this Software 13 * without prior written permission of Intalio, Inc. For written permission, please contact 14 * info@exolab.org. 15 * 16 * 4. Products derived from this Software may not be called "Exolab" nor may "Exolab" appear in 17 * their names without prior written permission of Intalio, Inc. Exolab is a registered trademark of 18 * Intalio, Inc. 19 * 20 * 5. Due credit should be given to the Exolab Project (http://www.exolab.org/). 21 * 22 * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 24 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTALIO, INC. OR ITS 25 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 29 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * 31 * Copyright 2003 (C) Intalio, Inc. All Rights Reserved. 32 * 33 * $Id$ 34 * 35 * Date Author Changes 04/21/2003 Keith Visco Created 36 */ 37 38 package org.exolab.castor.util; 39 40 import java.lang.reflect.Constructor; 41 import java.lang.reflect.InvocationTargetException; 42 43 import org.exolab.castor.core.exceptions.CastorIllegalStateException; 44 45 /** 46 * The default implementation of ObjectFactory used for creating class instances 47 * 48 * @author <a href="mailto:kvisco@intalio.com">Keith Visco</a> 49 * @version $Revision$ $Date: 2006-04-25 15:08:23 -0600 (Tue, 25 Apr 2006) $ 50 * @see ObjectFactory 51 */ 52 public class DefaultObjectFactory implements ObjectFactory { 53 54 /** 55 * Creates a default instance of the given class. 56 * 57 * @param type the Class to create an instance of 58 * @return the new instance of the given class 59 */ 60 public Object createInstance(Class type) throws IllegalAccessException, InstantiationException { 61 return createInstance(type, null, null); 62 } // -- createInstance 63 64 /** 65 * Creates a default instance of the given class. 66 * 67 * @param type the Class to create an instance of 68 * @param args the array of arguments to pass to the Class constructor 69 * @return the new instance of the given class 70 */ 71 public Object createInstance(Class type, Object[] args) 72 throws IllegalAccessException, InstantiationException { 73 return createInstance(type, null, args); 74 } // -- createInstance 75 76 /** 77 * Creates a default instance of the given class. 78 * 79 * @param type the Class to create an instance of 80 * @param argTypes the Class types for each argument, used to find the correct constructor 81 * @param args the array of arguments to pass to the Class constructor 82 * @return the new instance of the given class 83 */ 84 public Object createInstance(Class type, Class[] argTypes, Object[] args) 85 throws IllegalAccessException, InstantiationException { 86 if ((args == null) || (args.length == 0)) { 87 if (java.util.Date.class.isAssignableFrom(type)) { 88 return handleDates(type); 89 } 90 return type.newInstance(); 91 } 92 93 argTypes = checkArguments(argTypes, args); 94 95 return instantiateUsingConstructor(type, argTypes, args); 96 97 } // -- createInstance 98 99 /** 100 * Create a new instance of the given type by calling a public constructor of this class, passing 101 * the given arguments to the constructor call. 102 * 103 * @param type The class type to instantiate 104 * @param argTypes Argument types. 105 * @param args Arguments (to be used as parameters to the constructor class). 106 * @return An instance of the class type provided 107 * @throws InstantiationException If the given class type does not expose a constructor with the 108 * given number of argument (types). 109 * @throws IllegalAccessException If the given constructor failed during invocation. 110 */ 111 private Object instantiateUsingConstructor(Class type, Class[] argTypes, Object[] args) 112 throws InstantiationException, IllegalAccessException { 113 try { 114 Constructor cons = type.getConstructor(argTypes); 115 return cons.newInstance(args); 116 } catch (java.lang.NoSuchMethodException nsmx) { 117 String err = "unable to find matching public constructor for class: " + type.getName(); 118 err += " with argument types: "; 119 for (int i = 0; i < argTypes.length; i++) { 120 if (i > 0) 121 err += ", "; 122 err += argTypes[i].getName(); 123 } 124 throw new InstantiationException(err); 125 } catch (InvocationTargetException ite) { 126 throw new CastorIllegalStateException(ite.getMessage(), ite.getTargetException()); 127 } 128 } 129 130 /** 131 * Check the arguments (incl. argument types, if provided) for consistency, and deduce argument 132 * types if not provided. 133 * 134 * @param argTypes Argumemnt types. 135 * @param args Arguments 136 * @return A class array for the argument types provided. 137 */ 138 private Class[] checkArguments(Class[] argTypes, Object[] args) { 139 if (argTypes == null) { 140 argTypes = new Class[args.length]; 141 for (int i = 0; i < args.length; i++) { 142 if (args[i] != null) { 143 argTypes[i] = args[i].getClass(); 144 } else { 145 String err = 146 "null arguments to constructor not accepted " + "if the 'argTypes' array is null."; 147 throw new IllegalStateException(getClass().getName() + ": " + err); 148 } 149 } 150 } else if (argTypes.length != args.length) { 151 String err = "The argument type array must be the same length as argument value array."; 152 throw new IllegalArgumentException(getClass().getName() + ": " + err); 153 } 154 return argTypes; 155 } 156 157 158 /** 159 * Handles 'Date' types in a special way. 160 * 161 * @param type The Class type 162 * @return A new instance of the type given 163 * @throws InstantiationException If the given class type cannot be successfully instantiated. 164 * @throws IllegalAccessException If the given constructor failed during invocation. 165 */ 166 private Object handleDates(Class type) throws IllegalAccessException, InstantiationException { 167 168 java.util.Date date = new java.util.Date(); 169 170 if (java.util.Date.class == type) { 171 return date; 172 } else if (java.sql.Date.class == type) { 173 long time = date.getTime(); 174 return new java.sql.Date(time); 175 } else if (java.sql.Time.class == type) { 176 long time = date.getTime(); 177 return new java.sql.Time(time); 178 } else if (java.sql.Timestamp.class == type) { 179 long time = date.getTime(); 180 return new java.sql.Timestamp(time); 181 } else { 182 return type.newInstance(); 183 } 184 185 } // -- handleDates 186 187 } // -- DefaultObjectFactory