/** * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "Exolab" must not be used to endorse or promote * products derived from this Software without prior written * permission of Intalio, Inc. For written permission, * please contact info@exolab.org. * * 4. Products derived from this Software may not be called "Exolab" * nor may "Exolab" appear in their names without prior written * permission of Intalio, Inc. Exolab is a registered * trademark of Intalio, Inc. * * 5. Due credit should be given to the Exolab Project * (http://www.exolab.org/). * * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * INTALIO, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2003 (C) Intalio, Inc. All Rights Reserved. * * $Id$ * * Date Author Changes * 04/21/2003 Keith Visco Created */ package org.exolab.castor.util; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import org.exolab.castor.core.exceptions.CastorIllegalStateException; /** * The default implementation of ObjectFactory used for * creating class instances * * @author <a href="mailto:kvisco@intalio.com">Keith Visco</a> * @version $Revision$ $Date: 2006-04-25 15:08:23 -0600 (Tue, 25 Apr 2006) $ * @see ObjectFactory */ public class DefaultObjectFactory implements ObjectFactory { /** * Creates a default instance of the given class. * * @param type the Class to create an instance of * @return the new instance of the given class */ public Object createInstance(Class type) throws IllegalAccessException, InstantiationException { return createInstance(type, null, null); } //-- createInstance /** * Creates a default instance of the given class. * * @param type the Class to create an instance of * @param args the array of arguments to pass to the Class constructor * @return the new instance of the given class */ public Object createInstance(Class type, Object[] args) throws IllegalAccessException, InstantiationException { return createInstance(type, null, args); } //-- createInstance /** * Creates a default instance of the given class. * * @param type the Class to create an instance of * @param argTypes the Class types for each argument, used * to find the correct constructor * @param args the array of arguments to pass to the Class constructor * @return the new instance of the given class */ public Object createInstance(Class type, Class[] argTypes, Object[] args) throws IllegalAccessException, InstantiationException { if ((args == null) || (args.length == 0)) { if (java.util.Date.class.isAssignableFrom(type)) { return handleDates(type); } return type.newInstance(); } argTypes = checkArguments(argTypes, args); return instantiateUsingConstructor(type, argTypes, args); } //-- createInstance /** * Create a new instance of the given type by calling a public constructor * of this class, passing the given arguments to the constructor call. * @param type The class type to instantiate * @param argTypes Argument types. * @param args Arguments (to be used as parameters to the constructor class). * @return An instance of the class type provided * @throws InstantiationException If the given class type does not expose a constructor * with the given number of argument (types). * @throws IllegalAccessException If the given constructor failed during invocation. */ private Object instantiateUsingConstructor(Class type, Class[] argTypes, Object[] args) throws InstantiationException, IllegalAccessException { try { Constructor cons = type.getConstructor(argTypes); return cons.newInstance(args); } catch(java.lang.NoSuchMethodException nsmx) { String err = "unable to find matching public constructor for class: " + type.getName(); err += " with argument types: "; for (int i = 0; i < argTypes.length; i++) { if (i > 0) err += ", "; err += argTypes[i].getName(); } throw new InstantiationException(err); } catch(InvocationTargetException ite) { throw new CastorIllegalStateException( ite.getMessage(), ite.getTargetException()); } } /** * Check the arguments (incl. argument types, if provided) for consistency, and * deduce argument types if not provided. * @param argTypes Argumemnt types. * @param args Arguments * @return A class array for the argument types provided. */ private Class[] checkArguments(Class[] argTypes, Object[] args) { if (argTypes == null) { argTypes = new Class[args.length]; for (int i = 0; i < args.length; i++) { if (args[i] != null) { argTypes[i] = args[i].getClass(); } else { String err = "null arguments to constructor not accepted " + "if the 'argTypes' array is null."; throw new IllegalStateException(getClass().getName() + ": " + err); } } } else if (argTypes.length != args.length) { String err = "The argument type array must be the same length as argument value array."; throw new IllegalArgumentException(getClass().getName() + ": " + err); } return argTypes; } /** * Handles 'Date' types in a special way. * @param type The Class type * @return A new instance of the type given * @throws InstantiationException If the given class type cannot be successfully instantiated. * @throws IllegalAccessException If the given constructor failed during invocation. */ private Object handleDates(Class type) throws IllegalAccessException, InstantiationException { java.util.Date date = new java.util.Date(); if (java.util.Date.class == type) { return date; } else if (java.sql.Date.class == type) { long time = date.getTime(); return new java.sql.Date(time); } else if (java.sql.Time.class == type) { long time = date.getTime(); return new java.sql.Time(time); } else if (java.sql.Timestamp.class == type) { long time = date.getTime(); return new java.sql.Timestamp(time); } else { return type.newInstance(); } } //-- handleDates } //-- DefaultObjectFactory