001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.geronimo.gbean;
018
019 import java.beans.Introspector;
020 import java.lang.reflect.Constructor;
021 import java.lang.reflect.Method;
022 import java.util.Collection;
023 import java.util.HashMap;
024 import java.util.HashSet;
025 import java.util.Iterator;
026 import java.util.List;
027 import java.util.Map;
028 import java.util.Set;
029 import java.util.Arrays;
030
031 import org.apache.geronimo.kernel.ClassLoading;
032 import org.apache.geronimo.kernel.Kernel;
033
034 /**
035 * @version $Rev: 889880 $ $Date: 2009-12-12 10:45:24 +0800 (Sat, 12 Dec 2009) $
036 */
037 public class GBeanInfoBuilder {
038 public static GBeanInfoBuilder createStatic(Class gbeanType) {
039 if (gbeanType == null) throw new NullPointerException("gbeanType is null");
040 return createStatic(gbeanType, gbeanType.getName(), gbeanType, null, null);
041 }
042
043 public static GBeanInfoBuilder createStatic(Class gbeanType, String j2eeType) {
044 if (gbeanType == null) throw new NullPointerException("gbeanType is null");
045 return createStatic(gbeanType, gbeanType.getName(), gbeanType, null, j2eeType);
046 }
047
048 public static GBeanInfoBuilder createStatic(String name, Class gbeanType) {
049 if (gbeanType == null) throw new NullPointerException("gbeanType is null");
050 return createStatic(gbeanType, name, gbeanType, null, null);
051 }
052
053 public static GBeanInfoBuilder createStatic(String name, Class gbeanType, String j2eeType) {
054 if (gbeanType == null) throw new NullPointerException("gbeanType is null");
055 return createStatic(gbeanType, name, gbeanType, null, j2eeType);
056 }
057
058 public static GBeanInfoBuilder createStatic(Class gbeanType, GBeanInfo source) {
059 if (gbeanType == null) throw new NullPointerException("gbeanType is null");
060 return createStatic(gbeanType, gbeanType.getName(), gbeanType, source, null);
061 }
062
063 public static GBeanInfoBuilder createStatic(Class gbeanType, GBeanInfo source, String j2eeType) {
064 if (gbeanType == null) throw new NullPointerException("gbeanType is null");
065 return createStatic(gbeanType, gbeanType.getName(), gbeanType, source, j2eeType);
066 }
067
068 public static GBeanInfoBuilder createStatic(String name, Class gbeanType, GBeanInfo source) {
069 if (name == null) throw new NullPointerException("name is null");
070 if (gbeanType == null) throw new NullPointerException("gbeanType is null");
071 return createStatic(gbeanType, name, gbeanType, source, null);
072 }
073
074 //
075 // These methods are used by classes that declare a GBeanInfo for another class
076 //
077 public static GBeanInfoBuilder createStatic(Class sourceClass, Class gbeanType) {
078 if (gbeanType == null) throw new NullPointerException("gbeanType is null");
079 return createStatic(sourceClass, gbeanType.getName(), gbeanType, null, null);
080 }
081
082 public static GBeanInfoBuilder createStatic(Class sourceClass, Class gbeanType, String j2eeType) {
083 if (sourceClass == null) throw new NullPointerException("sourceClass is null");
084 if (gbeanType == null) throw new NullPointerException("gbeanType is null");
085 return createStatic(sourceClass, gbeanType.getName(), gbeanType, null, j2eeType);
086 }
087
088 public static GBeanInfoBuilder createStatic(Class sourceClass, Class gbeanType, GBeanInfo source, String j2eeType) {
089 if (sourceClass == null) throw new NullPointerException("sourceClass is null");
090 if (gbeanType == null) throw new NullPointerException("gbeanType is null");
091 return createStatic(sourceClass, gbeanType.getName(), gbeanType, source, j2eeType);
092 }
093
094 public static GBeanInfoBuilder createStatic(Class sourceClass, String name, Class gbeanType, String j2eeType) {
095 if (sourceClass == null) throw new NullPointerException("sourceClass is null");
096 if (name == null) throw new NullPointerException("name is null");
097 if (gbeanType == null) throw new NullPointerException("gbeanType is null");
098 return createStatic(sourceClass, name, gbeanType, null, j2eeType);
099 }
100
101 public static GBeanInfoBuilder createStatic(Class sourceClass, String name, Class gbeanType, GBeanInfo source, String j2eeType) {
102 if (sourceClass == null) throw new NullPointerException("sourceClass is null");
103 if (name == null) throw new NullPointerException("name is null");
104 if (gbeanType == null) throw new NullPointerException("gbeanType is null");
105 return new GBeanInfoBuilder(sourceClass.getName(), name, gbeanType, source, j2eeType);
106 }
107
108 public static final String DEFAULT_J2EE_TYPE = "GBean"; //NameFactory.GERONIMO_SERVICE
109
110 private static final Class[] NO_ARGS = {};
111
112 /**
113 * The class from which the info can be retrieved using GBeanInfo.getGBeanInfo(className, classLoader)
114 */
115 private final String sourceClass;
116
117 private final String name;
118
119 private final String j2eeType;
120
121 private final Class gbeanType;
122
123 private final Map attributes = new HashMap();
124
125 private GConstructorInfo constructor = new GConstructorInfo();
126
127 private final Map operations = new HashMap();
128
129 private final Map references = new HashMap();
130
131 private final Set interfaces = new HashSet();
132
133 private int priority = GBeanInfo.PRIORITY_NORMAL;
134
135 public GBeanInfoBuilder(Class gbeanType) {
136 this(checkNotNull(gbeanType).getName(), gbeanType, null, null);
137 }
138
139 public GBeanInfoBuilder(Class gbeanType, String j2eeType) {
140 this(checkNotNull(gbeanType).getName(), gbeanType, null, j2eeType);
141 }
142
143 public GBeanInfoBuilder(String name, Class gbeanType) {
144 this(name, checkNotNull(gbeanType), null, null);
145 }
146
147 public GBeanInfoBuilder(String name, Class gbeanType, String j2eeType) {
148 this(name, checkNotNull(gbeanType), null, j2eeType);
149 }
150
151 public GBeanInfoBuilder(Class gbeanType, GBeanInfo source) {
152 this(checkNotNull(gbeanType).getName(), gbeanType, source);
153 }
154
155 public GBeanInfoBuilder(Class gbeanType, GBeanInfo source, String j2eeType) {
156 this(checkNotNull(gbeanType).getName(), gbeanType, source, j2eeType);
157 }
158
159 //TODO remove this
160 /**
161 * @deprecated This will be removed in a future release
162 */
163 public GBeanInfoBuilder(String name, ClassLoader classLoader) {
164 this(checkNotNull(name), loadClass(classLoader, name), GBeanInfo.getGBeanInfo(name, classLoader));
165 }
166
167 public GBeanInfoBuilder(String name, Class gbeanType, GBeanInfo source) {
168 this(name, gbeanType, source, null);
169 }
170
171 public GBeanInfoBuilder(String name, Class gbeanType, GBeanInfo source, String j2eeType) {
172 this(null, name, gbeanType, source, j2eeType);
173 }
174
175 private GBeanInfoBuilder(String sourceClass, String name, Class gbeanType, GBeanInfo source, String j2eeType) {
176 checkNotNull(name);
177 checkNotNull(gbeanType);
178 this.name = name;
179 this.gbeanType = gbeanType;
180 this.sourceClass = sourceClass;
181
182 if (source != null) {
183 for (Iterator i = source.getAttributes().iterator(); i.hasNext();) {
184 GAttributeInfo attributeInfo = (GAttributeInfo) i.next();
185 attributes.put(attributeInfo.getName(), attributeInfo);
186 }
187
188 for (Iterator i = source.getOperations().iterator(); i.hasNext();) {
189 GOperationInfo operationInfo = (GOperationInfo) i.next();
190 operations.put(new GOperationSignature(operationInfo.getName(), operationInfo.getParameterList()), operationInfo);
191 }
192
193 for (Iterator iterator = source.getReferences().iterator(); iterator.hasNext();) {
194 GReferenceInfo referenceInfo = (GReferenceInfo) iterator.next();
195 references.put(referenceInfo.getName(), new RefInfo(referenceInfo.getReferenceType(), referenceInfo.getNameTypeName()));
196 }
197
198 for (Iterator iterator = source.getInterfaces().iterator(); iterator.hasNext();) {
199 String intf = (String) iterator.next();
200 interfaces.add(intf);
201 }
202
203 //in case subclass constructor has same parameters as superclass.
204 constructor = source.getConstructor();
205
206 priority = source.getPriority();
207 }
208 if (j2eeType != null) {
209 this.j2eeType = j2eeType;
210 } else if (source != null) {
211 this.j2eeType = source.getJ2eeType();
212 } else {
213 this.j2eeType = DEFAULT_J2EE_TYPE; //NameFactory.GERONIMO_SERVICE
214 }
215
216 // add all interfaces based on GBean type
217 if (gbeanType.isArray()) {
218 throw new IllegalArgumentException("GBean is an array type: gbeanType=" + gbeanType.getName());
219 }
220 Set allTypes = ClassLoading.getAllTypes(gbeanType);
221 for (Iterator iterator = allTypes.iterator(); iterator.hasNext();) {
222 Class type = (Class) iterator.next();
223 addInterface(type);
224 }
225 }
226
227 public void setPersistentAttributes(String[] persistentAttributes) {
228 for (int i = 0; i < persistentAttributes.length; i++) {
229 String attributeName = persistentAttributes[i];
230 GAttributeInfo attribute = (GAttributeInfo) attributes.get(attributeName);
231 if (attribute != null && !references.containsKey(attributeName)) {
232 if (isMagicAttribute(attribute)) {
233 // magic attributes can't be persistent
234 continue;
235 }
236 attributes.put(attributeName,
237 new GAttributeInfo(attributeName,
238 attribute.getType(),
239 true,
240 attribute.isManageable(),
241 attribute.isEncrypted(),
242 attribute.getGetterName(),
243 attribute.getSetterName()));
244 } else {
245 if (attributeName.equals("kernel")) {
246 addAttribute("kernel", Kernel.class, false);
247 } else if (attributeName.equals("classLoader")) {
248 addAttribute("classLoader", ClassLoader.class, false);
249 } else if (attributeName.equals("abstractName")) {
250 addAttribute("abstractName", AbstractName.class, false);
251 } else if (attributeName.equals("objectName")) {
252 addAttribute("objectName", String.class, false);
253 }
254 }
255 }
256 }
257
258 public void setManageableAttributes(String[] manageableAttributes) {
259 for (int i = 0; i < manageableAttributes.length; i++) {
260 String attributeName = manageableAttributes[i];
261 GAttributeInfo attribute = (GAttributeInfo) attributes.get(attributeName);
262 if (attribute != null) {
263 attributes.put(attributeName,
264 new GAttributeInfo(attributeName,
265 attribute.getType(),
266 attribute.isPersistent(),
267 true,
268 attribute.isEncrypted(),
269 attribute.getGetterName(),
270 attribute.getSetterName()));
271 }
272 }
273 }
274
275 private boolean isMagicAttribute(GAttributeInfo attributeInfo) {
276 String name = attributeInfo.getName();
277 String type = attributeInfo.getType();
278 return ("kernel".equals(name) && Kernel.class.getName().equals(type)) ||
279 ("classLoader".equals(name) && ClassLoader.class.getName().equals(type)) ||
280 ("abstractName".equals(name) && AbstractName.class.getName().equals(type)) ||
281 ("objectName".equals(name) && String.class.getName().equals(type));
282 }
283
284 public void addInterface(Class intf) {
285 addInterface(intf, new String[0]);
286 }
287
288 //do not use beaninfo Introspector to list the properties. This method is primarily for interfaces,
289 //and it does not process superinterfaces. It seems to really only work well for classes.
290 public void addInterface(Class intf, String[] persistentAttributes) {
291 addInterface(intf, persistentAttributes, new String[0]);
292 }
293
294 public void addInterface(Class intf, String[] persistentAttributes, String[] manageableAttributes) {
295 Set persistentNames = new HashSet(Arrays.asList(persistentAttributes));
296 Set manageableNames = new HashSet(Arrays.asList(manageableAttributes));
297 Method[] methods = intf.getMethods();
298 for (int i = 0; i < methods.length; i++) {
299 Method method = methods[i];
300 if ("java.lang.Object".equals(method.getDeclaringClass().getName())) continue;
301 if (isGetter(method)) {
302 String attributeName = getAttributeName(method);
303 GAttributeInfo attribute = (GAttributeInfo) attributes.get(attributeName);
304 String attributeType = method.getReturnType().getName();
305 if (attribute == null) {
306 attributes.put(attributeName,
307 new GAttributeInfo(attributeName,
308 attributeType,
309 persistentNames.contains(attributeName),
310 manageableNames.contains(attributeName),
311 method.getName(),
312 null));
313 } else {
314 if (!attributeType.equals(attribute.getType())) {
315 throw new IllegalArgumentException("Getter and setter type do not match: " + attributeName + " for gbeanType: " + gbeanType.getName());
316 }
317 attributes.put(attributeName,
318 new GAttributeInfo(attributeName,
319 attributeType,
320 attribute.isPersistent() || persistentNames.contains(attributeName),
321 attribute.isManageable() || manageableNames.contains(attributeName),
322 attribute.isEncrypted(),
323 method.getName(),
324 attribute.getSetterName()));
325 }
326 } else if (isSetter(method)) {
327 String attributeName = getAttributeName(method);
328 String attributeType = method.getParameterTypes()[0].getName();
329 GAttributeInfo attribute = (GAttributeInfo) attributes.get(attributeName);
330 if (attribute == null) {
331 attributes.put(attributeName,
332 new GAttributeInfo(attributeName,
333 attributeType,
334 persistentNames.contains(attributeName),
335 manageableNames.contains(attributeName),
336 null,
337 method.getName()));
338 } else {
339 if (!attributeType.equals(attribute.getType())) {
340 throw new IllegalArgumentException("Getter and setter type do not match: " + attributeName + " for gbeanType: " + gbeanType.getName());
341 }
342 attributes.put(attributeName,
343 new GAttributeInfo(attributeName,
344 attributeType,
345 attribute.isPersistent() || persistentNames.contains(attributeName),
346 attribute.isManageable() || manageableNames.contains(attributeName),
347 attribute.isEncrypted(),
348 attribute.getGetterName(),
349 method.getName()));
350 }
351 } else {
352 addOperation(new GOperationInfo(method.getName(), method.getParameterTypes(), method.getReturnType().getName()));
353 }
354 }
355 addInterface(interfaces, intf);
356 }
357
358 private static void addInterface(Set set, Class intf) {
359 String name = intf.getName();
360 if(set.contains(name)) {
361 return;
362 }
363 set.add(name);
364 Class cls[] = intf.getInterfaces();
365 for (int i = 0; i < cls.length; i++) {
366 addInterface(set, cls[i]);
367 }
368 }
369 public void addAttribute(String name, Class type, boolean persistent) {
370 addAttribute(name, type.getName(), persistent, true);
371 }
372
373 public void addAttribute(String name, String type, boolean persistent) {
374 addAttribute(name, type, persistent, true);
375 }
376
377 public void addAttribute(String name, Class type, boolean persistent, boolean manageable) {
378 addAttribute(name, type.getName(), persistent, manageable);
379 }
380
381 public void addAttribute(String name, String type, boolean persistent, boolean manageable) {
382 String getter = searchForGetter(name, type, gbeanType);
383 String setter = searchForSetter(name, type, gbeanType);
384 addAttribute(new GAttributeInfo(name, type, persistent, manageable, getter, setter));
385 }
386
387 public void addAttribute(String name, Class type, boolean persistent, boolean manageable, boolean encrypted) {
388 addAttribute(name, type.getName(), persistent, manageable, encrypted);
389 }
390
391 public void addAttribute(String name, String type, boolean persistent, boolean manageable, boolean encrypted) {
392 String getter = searchForGetter(name, type, gbeanType);
393 String setter = searchForSetter(name, type, gbeanType);
394 addAttribute(new GAttributeInfo(name, type, persistent, manageable, encrypted, getter, setter));
395 }
396
397 public void addAttribute(GAttributeInfo info) {
398 attributes.put(info.getName(), info);
399 }
400
401 public void setConstructor(GConstructorInfo constructor) {
402 assert constructor != null;
403 this.constructor = constructor;
404 List names = constructor.getAttributeNames();
405 setPersistentAttributes((String[]) names.toArray(new String[names.size()]));
406 }
407
408 public void setConstructor(String[] names) {
409 constructor = new GConstructorInfo(names);
410 setPersistentAttributes(names);
411 }
412
413 public void addOperation(GOperationInfo operationInfo) {
414 operations.put(new GOperationSignature(operationInfo.getName(), operationInfo.getParameterList()), operationInfo);
415 }
416
417 /**
418 * @deprecated
419 */
420 public void addOperation(String name) {
421 // FIXME : This is needed because the getters/setters are not being added as operation
422 // i.e. kerenl.invoke("getX") fails.
423 addOperation(new GOperationInfo(name, NO_ARGS, ""));
424 }
425
426 /**
427 * @deprecated
428 */
429 public void addOperation(String name, Class[] paramTypes) {
430 //addOperation(new GOperationInfo(name, paramTypes, ""));
431 }
432
433 public void addOperation(String name, String returnType) {
434 addOperation(new GOperationInfo(name, NO_ARGS, returnType));
435 }
436
437 // This is redundant because these operations are added automatically; it can be made private
438 public void addOperation(String name, Class[] paramTypes, String returnType) {
439 addOperation(new GOperationInfo(name, paramTypes, returnType));
440 }
441
442 public void addReference(GReferenceInfo info) {
443 references.put(info.getName(), new RefInfo(info.getReferenceType(), info.getNameTypeName()));
444 }
445
446 /**
447 * Add a reference to another GBean or collection of GBeans
448 * @param name the name of the reference
449 * @param type The proxy type of the GBean or objects in a ReferenceCollection
450 * @param namingType the string expected as the type component of the name. For jsr-77 names this is the j2eeType value
451 */
452 public void addReference(String name, Class type, String namingType) {
453 references.put(name, new RefInfo(type.getName(), namingType));
454 }
455
456 public void addReference(String name, Class type) {
457 references.put(name, new RefInfo(type.getName(), null));
458 }
459
460 public void setPriority(int priority) {
461 this.priority = priority;
462 }
463
464 public GBeanInfo getBeanInfo() {
465 // get the types of the constructor args
466 // this also verifies that we have a valid constructor
467 Map constructorTypes = getConstructorTypes();
468
469 // build the reference infos now that we know the constructor types
470 Set referenceInfos = new HashSet();
471 for (Iterator iterator = references.entrySet().iterator(); iterator.hasNext();) {
472 Map.Entry entry = (Map.Entry) iterator.next();
473 String referenceName = (String) entry.getKey();
474 RefInfo refInfo = (RefInfo) entry.getValue();
475 String referenceType = refInfo.getJavaType();
476 String namingType = refInfo.getNamingType();
477
478 String proxyType = (String) constructorTypes.get(referenceName);
479 String setterName = null;
480 if (proxyType == null) {
481 Method setter = searchForSetterMethod(referenceName, referenceType, gbeanType);
482 if (setter == null) {
483 setter = searchForSetterMethod(referenceName, Collection.class.getName(), gbeanType);
484 if (setter == null) {
485 throw new InvalidConfigurationException("Reference must be a constructor argument or have a setter: name=" + referenceName + " for gbeanType: " + gbeanType);
486 }
487 }
488 proxyType = setter.getParameterTypes()[0].getName();
489
490 setterName = setter.getName();
491 }
492
493 if (!proxyType.equals(Collection.class.getName()) && !proxyType.equals(referenceType)) {
494 throw new InvalidConfigurationException("Reference proxy type must be Collection or " + referenceType + ": name=" + referenceName + " for gbeanType: " + gbeanType.getName());
495 }
496
497 referenceInfos.add(new GReferenceInfo(referenceName, referenceType, proxyType, setterName, namingType));
498 }
499
500 return new GBeanInfo(sourceClass, name, gbeanType.getName(), j2eeType, attributes.values(), constructor, operations.values(), referenceInfos, interfaces, priority);
501 }
502
503 private Map getConstructorTypes() throws InvalidConfigurationException {
504 List arguments = constructor.getAttributeNames();
505 String[] argumentTypes = new String[arguments.size()];
506 boolean[] isReference = new boolean[arguments.size()];
507 for (int i = 0; i < argumentTypes.length; i++) {
508 String argumentName = (String) arguments.get(i);
509 if (references.containsKey(argumentName)) {
510 argumentTypes[i] = ((RefInfo) references.get(argumentName)).getJavaType();
511 isReference[i] = true;
512 } else if (attributes.containsKey(argumentName)) {
513 GAttributeInfo attribute = (GAttributeInfo) attributes.get(argumentName);
514 argumentTypes[i] = attribute.getType();
515 isReference[i] = false;
516 }
517 }
518
519 Constructor[] constructors = gbeanType.getConstructors();
520 Set validConstructors = new HashSet();
521 for (int i = 0; i < constructors.length; i++) {
522 Constructor constructor = constructors[i];
523 if (isValidConstructor(constructor, argumentTypes, isReference)) {
524 validConstructors.add(constructor);
525 }
526 }
527
528 if (validConstructors.isEmpty()) {
529 throw new InvalidConfigurationException("Could not find a valid constructor for GBean: " + gbeanType.getName());
530 }
531 if (validConstructors.size() > 1) {
532 throw new InvalidConfigurationException("More then one valid constructors found for GBean: " + gbeanType.getName());
533 }
534
535 Map constructorTypes = new HashMap();
536 Constructor constructor = (Constructor) validConstructors.iterator().next();
537 Class[] parameterTypes = constructor.getParameterTypes();
538 Iterator argumentIterator = arguments.iterator();
539 for (int i = 0; i < parameterTypes.length; i++) {
540 String parameterType = parameterTypes[i].getName();
541 String argumentName = (String) argumentIterator.next();
542 constructorTypes.put(argumentName, parameterType);
543 }
544 return constructorTypes;
545 }
546
547 private static String searchForGetter(String name, String type, Class gbeanType) throws InvalidConfigurationException {
548 Method getterMethod = null;
549
550 // no explicit name give so we must search for a name
551 String getterName = "get" + name;
552 String isName = "is" + name;
553 Method[] methods = gbeanType.getMethods();
554 for (int i = 0; i < methods.length; i++) {
555 if (methods[i].getParameterTypes().length == 0 && methods[i].getReturnType() != Void.TYPE
556 && (getterName.equalsIgnoreCase(methods[i].getName()) || isName.equalsIgnoreCase(methods[i].getName()))) {
557
558 // found it
559 getterMethod = methods[i];
560 break;
561 }
562 }
563
564 // if the return type of the getter doesn't match, throw an exception
565 if (getterMethod != null && !type.equals(getterMethod.getReturnType().getName())) {
566 throw new InvalidConfigurationException("Incorrect return type for getter method:" +
567 " name=" + name +
568 ", targetClass=" + gbeanType.getName() +
569 ", getter type=" + getterMethod.getReturnType() +
570 ", expected type=" + type);
571 }
572
573 if (getterMethod == null) {
574 return null;
575 }
576 return getterMethod.getName();
577 }
578
579 private static String searchForSetter(String name, String type, Class gbeanType) throws InvalidConfigurationException {
580 Method method = searchForSetterMethod(name, type, gbeanType);
581 if (method == null) {
582 return null;
583 }
584 return method.getName();
585 }
586
587 private static Method searchForSetterMethod(String name, String type, Class gbeanType) throws InvalidConfigurationException {
588 // no explicit name give so we must search for a name
589 String setterName = "set" + name;
590 Method[] methods = gbeanType.getMethods();
591 for (int i = 0; i < methods.length; i++) {
592 Method method = methods[i];
593 if (method.getParameterTypes().length == 1 &&
594 method.getParameterTypes()[0].getName().equals(type) &&
595 method.getReturnType() == Void.TYPE &&
596 setterName.equalsIgnoreCase(method.getName())) {
597
598 return method;
599 }
600 }
601
602 // a setter is not necessary for this attribute
603 return null;
604 }
605
606 private static boolean isValidConstructor(Constructor constructor, String[] argumentTypes, boolean[] isReference) {
607 Class[] parameterTypes = constructor.getParameterTypes();
608
609 // same number of parameters?
610 if (parameterTypes.length != argumentTypes.length) {
611 return false;
612 }
613
614 // is each parameter the correct type?
615 for (int i = 0; i < parameterTypes.length; i++) {
616 String parameterType = parameterTypes[i].getName();
617 if (isReference[i]) {
618 // reference: does type match
619 // OR is it a java.util.Collection
620 // OR is it a java.util.Set?
621 if (!parameterType.equals(argumentTypes[i]) &&
622 !parameterType.equals(Collection.class.getName()) &&
623 !parameterType.equals(Set.class.getName())) {
624 return false;
625 }
626 } else {
627 // attribute: does type match?
628 if (!parameterType.equals(argumentTypes[i])) {
629 return false;
630 }
631 }
632 }
633 return true;
634 }
635
636 private String getAttributeName(Method method) {
637 String name = method.getName();
638 String attributeName = (name.startsWith("get") || name.startsWith("set")) ? name.substring(3) : name.substring(2);
639 attributeName = Introspector.decapitalize(attributeName);
640 return attributeName;
641 }
642
643 private boolean isSetter(Method method) {
644 return method.getName().startsWith("set") && method.getParameterTypes().length == 1;
645 }
646
647 private static boolean isGetter(Method method) {
648 String name = method.getName();
649 return (name.startsWith("get") || name.startsWith("is")) && method.getParameterTypes().length == 0;
650 }
651
652 /**
653 * Checks whether or not the input argument is null; otherwise it throws
654 * {@link IllegalArgumentException}.
655 *
656 * @param clazz the input argument to validate
657 * @throws IllegalArgumentException if input is null
658 */
659 private static Class checkNotNull(final Class clazz) {
660 if (clazz == null) {
661 throw new IllegalArgumentException("null argument supplied");
662 }
663 return clazz;
664 }
665
666 /**
667 * Checks whether or not the input argument is null; otherwise it throws
668 * {@link IllegalArgumentException}.
669 *
670 * @param string the input argument to validate
671 * @throws IllegalArgumentException if input is null
672 */
673 private static String checkNotNull(final String string) {
674 if (string == null) {
675 throw new IllegalArgumentException("null argument supplied");
676 }
677 return string;
678 }
679
680 private static Class loadClass(ClassLoader classLoader, String name) {
681 try {
682 return classLoader.loadClass(name);
683 } catch (ClassNotFoundException e) {
684 throw new InvalidConfigurationException("Could not load class " + name, e);
685 }
686 }
687
688 private static class RefInfo {
689 private final String javaType;
690 private final String namingType;
691
692 public RefInfo(String javaType, String namingType) {
693 this.javaType = javaType;
694 this.namingType = namingType;
695 }
696
697 public String getJavaType() {
698 return javaType;
699 }
700
701 public String getNamingType() {
702 return namingType;
703 }
704 }
705 }