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 Exoffice Technologies. For written permission,
18 * please contact tma@netspace.net.au.
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 Exoffice Technologies. Exolab is a registered
23 * trademark of Exoffice Technologies.
24 *
25 * 5. Due credit should be given to the Exolab Project
26 * (http://www.exolab.org/).
27 *
28 * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES 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 * EXOFFICE TECHNOLOGIES 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 2001-2004 (C) Exoffice Technologies Inc. All Rights Reserved.
42 *
43 * $Id: ClassHelper.java,v 1.3 2004/01/31 13:44:24 tanderson Exp $
44 */
45 package org.exolab.jmscts.core;
46
47 import java.lang.reflect.InvocationTargetException;
48 import java.lang.reflect.Method;
49 import java.lang.reflect.Modifier;
50 import java.util.ArrayList;
51
52 import org.exolab.jmscts.core.types.PropertyTypeType;
53
54
55 /***
56 * Helper for loading classes and setting/getting any public properties.
57 *
58 * @version $Revision: 1.3 $ $Date: 2004/01/31 13:44:24 $
59 * @author <a href="mailto:tma@netspace.net.au">Tim Anderson</a>
60 */
61 public final class ClassHelper {
62
63
64 /***
65 * A map of objectified primitive types, and their corresponding primitive
66 * types
67 */
68 private static final Class[][] TYPES = {
69 {Boolean.class, boolean.class}, {Byte.class, byte.class},
70 {Short.class, short.class}, {Character.class, char.class},
71 {Integer.class, int.class}, {Long.class, long.class},
72 {Float.class, float.class}, {Double.class, double.class}};
73
74
75 /***
76 * Prevent construction of utility class
77 */
78 private ClassHelper() {
79 }
80
81 /***
82 * Create a new instance of an object identified by its class name,
83 * and set its properties
84 *
85 * @param className the name of the class
86 * @param properties the list of properties to set
87 * @return a new instance the specified class
88 * @throws ClassNotFoundException if the class cannot be located
89 * @throws IllegalAccessException if the class or initializer is not
90 * accessible
91 * @throws InstantiationException if the instantiation fails
92 * @throws InvocationTargetException if the underlying method throws an
93 * exception
94 * @throws NoSuchMethodException if a matching method is not found
95 */
96 public static Object instantiate(String className,
97 Property[] properties)
98 throws ClassNotFoundException, IllegalAccessException,
99 InstantiationException, InvocationTargetException,
100 NoSuchMethodException {
101
102 Object object = Class.forName(className).newInstance();
103 for (int i = 0; i < properties.length; ++i) {
104 Property property = properties[i];
105 Class type = Class.forName(property.getType().toString());
106 Class[] types = new Class[] {type};
107 String name = "set" + property.getName();
108 Method method = object.getClass().getMethod(name, types);
109 Object arg = PropertyHelper.create(property);
110 Object[] args = new Object[]{arg};
111 method.invoke(object, args);
112 }
113 return object;
114 }
115
116 /***
117 * Helper to returns the properties of an object
118 *
119 * @param object the object to retrieve properties for
120 * @return the set of properties of object
121 * @throws IllegalAccessException if the class or initializer is not
122 * accessible
123 * @throws InvocationTargetException if the underlying method throws an
124 * exception
125 */
126 public static Property[] getProperties(Object object)
127 throws IllegalAccessException, InvocationTargetException {
128 final String prefix = "get";
129
130 ArrayList result = new ArrayList();
131 Method[] methods = object.getClass().getDeclaredMethods();
132 for (int i = 0; i < methods.length; ++i) {
133 Method method = methods[i];
134 int modifier = method.getModifiers();
135 if (method.getParameterTypes().length == 0
136 && Modifier.isPublic(modifier) && !Modifier.isStatic(modifier)
137 && method.getName().startsWith(prefix)) {
138
139 Class type = method.getReturnType();
140 if (type.equals(Boolean.class)
141 || type.equals(Short.class)
142 || type.equals(Integer.class)
143 || type.equals(Long.class)
144 || type.equals(Float.class)
145 || type.equals(Double.class)
146 || type.equals(String.class)) {
147 Property property = new Property();
148 String name = method.getName().substring(prefix.length());
149 property.setName(name);
150 property.setType(PropertyTypeType.valueOf(type.getName()));
151 Object value = method.invoke(object, new Object[]{});
152 property.setValue(value.toString());
153 result.add(property);
154 }
155 }
156 }
157 return (Property[]) result.toArray(new Property[]{});
158 }
159
160 /***
161 * Helper to return a method given its name and a list of arguments
162 *
163 * @param type the class to locate the method on
164 * @param name the method name
165 * @param args the list of arguments to match against, or null if the
166 * method takes no arguments
167 * @return the method matching the name and list of arguments
168 * @throws NoSuchMethodException if the method cannot be found
169 */
170 public static Method getMethod(Class type, String name, Object[] args)
171 throws NoSuchMethodException {
172
173 boolean containsNull = false;
174 Class[] types = null;
175 if (args != null) {
176 types = new Class[args.length];
177 for (int i = 0; i < args.length; ++i) {
178 if (args[i] != null) {
179 types[i] = args[i].getClass();
180 } else {
181 containsNull = true;
182 }
183 }
184 } else {
185 types = new Class[]{};
186 }
187
188 Method method = null;
189 if (!containsNull) {
190 try {
191 // try a direct lookup
192 method = type.getMethod(name, types);
193 } catch (NoSuchMethodException ignore) {
194 if (types.length != 0) {
195 // try converting any objectified types to primitives
196 Class[] converted = new Class[types.length];
197 for (int i = 0; i < args.length; ++i) {
198 converted[i] = getPrimitiveType(args[i].getClass());
199 }
200 try {
201 method = type.getMethod(name, types);
202 } catch (NoSuchMethodException ignore2) {
203 // no-op
204 }
205 }
206 }
207 }
208 if (method == null) {
209 // try and find it iteratively, using the class' public declared
210 // methods
211 Method[] methods = type.getDeclaredMethods();
212 for (int i = 0; i < methods.length; ++i) {
213 if (Modifier.isPublic(methods[i].getModifiers())
214 && methods[i].getName().equals(name)) {
215 if (checkParameters(methods[i], types)) {
216 method = methods[i];
217 break;
218 }
219 }
220 }
221 if (method == null) {
222 // try and find it iteratively, using the MUCH slower
223 // getMethods() method
224 methods = type.getMethods();
225 for (int i = 0; i < methods.length; ++i) {
226 if (methods[i].getName().equals(name)) {
227 if (checkParameters(methods[i], types)) {
228 method = methods[i];
229 break;
230 }
231 }
232 }
233 }
234 if (method == null) {
235 String msg = "No method found for name=" + name
236 + ", argument types=(";
237 if (args != null && args.length > 0) {
238 for (int i = 0; i < args.length; ++i) {
239 if (i > 0) {
240 msg += ", ";
241 }
242 if (args[i] != null) {
243 msg += args[i].getClass().getName();
244 } else {
245 msg += "Object";
246 }
247 }
248 }
249 msg += ")";
250
251 throw new NoSuchMethodException(msg);
252 }
253 }
254 return method;
255 }
256
257 /***
258 * Helper to return the primitive type associated with an object wrapper
259 * type
260 *
261 * @param wrapper the object wrapper class
262 * @return the associated primitive type, or the wrapper type, if there
263 * is no associated primitive type
264 */
265 public static Class getPrimitiveType(Class wrapper) {
266 Class result = null;
267 for (int i = 0; i < TYPES.length; ++i) {
268 if (wrapper.equals(TYPES[i][0])) {
269 result = TYPES[i][1];
270 break;
271 }
272 }
273
274 return (result != null) ? result : wrapper;
275 }
276
277 /***
278 * Helper to return the primitive type name associated with an object
279 * wrapper type
280 *
281 * @param wrapper the object wrapper class
282 * @return the associated primitive type name, or the wrapper type name,
283 * if there is no associated primitive type. Array types are returned
284 * in the form '<class>[]'
285 */
286 public static String getPrimitiveName(Class wrapper) {
287 String result = null;
288 Class type = getPrimitiveType(wrapper);
289 if (type.isArray()) {
290 result = type.getComponentType().getName() + "[]";
291 } else {
292 result = type.getName();
293 }
294 return result;
295 }
296
297 /***
298 * Helper to determine if a list of argument types match that of
299 * a method
300 *
301 * @param method the method to check
302 * @param types the argument types
303 * @return <code>true</code> if the argument types are compatible
304 */
305 private static boolean checkParameters(Method method, Class[] types) {
306 boolean result = true;
307 Class[] parameters = method.getParameterTypes();
308 if (parameters.length != types.length) {
309 result = false;
310 } else {
311 for (int i = 0; i < parameters.length; ++i) {
312 Class parameter = parameters[i];
313 if (types[i] == null) {
314 if (parameter.isPrimitive()) {
315 result = false;
316 break;
317 }
318 } else if (!parameter.isAssignableFrom(types[i])
319 && !parameter.isAssignableFrom(
320 getPrimitiveType(types[i]))) {
321 result = false;
322 break;
323 }
324 }
325 }
326 return result;
327 }
328
329 }
This page was automatically generated by Maven