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