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