View Javadoc

1   /**
2    *
3    * Copyright 2003-2004 The Apache Software Foundation
4    *
5    *  Licensed under the Apache License, Version 2.0 (the "License");
6    *  you may not use this file except in compliance with the License.
7    *  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   */
17  package org.apache.geronimo.gbean;
18  
19  import java.beans.Introspector;
20  import java.lang.reflect.Constructor;
21  import java.lang.reflect.Method;
22  import java.util.Collection;
23  import java.util.HashMap;
24  import java.util.HashSet;
25  import java.util.Iterator;
26  import java.util.List;
27  import java.util.Map;
28  import java.util.Set;
29  import java.util.Arrays;
30  
31  import org.apache.geronimo.kernel.ClassLoading;
32  import org.apache.geronimo.kernel.Kernel;
33  
34  /**
35   * @version $Rev: 471683 $ $Date: 2006-11-06 02:28:54 -0800 (Mon, 06 Nov 2006) $
36   */
37  public class GBeanInfoBuilder {
38      public static GBeanInfoBuilder createStatic(Class gbeanType) {
39          if (gbeanType == null) throw new NullPointerException("gbeanType is null");
40          return createStatic(gbeanType, gbeanType.getName(), gbeanType, null, null);
41      }
42  
43      public static GBeanInfoBuilder createStatic(Class gbeanType, String j2eeType) {
44          if (gbeanType == null) throw new NullPointerException("gbeanType is null");
45          return createStatic(gbeanType, gbeanType.getName(), gbeanType, null, j2eeType);
46      }
47  
48      public static GBeanInfoBuilder createStatic(String name, Class gbeanType) {
49          if (gbeanType == null) throw new NullPointerException("gbeanType is null");
50          return createStatic(gbeanType, name, gbeanType, null, null);
51      }
52  
53      public static GBeanInfoBuilder createStatic(String name, Class gbeanType, String j2eeType) {
54          if (gbeanType == null) throw new NullPointerException("gbeanType is null");
55          return createStatic(gbeanType, name, gbeanType, null, j2eeType);
56      }
57  
58      public static GBeanInfoBuilder createStatic(Class gbeanType, GBeanInfo source) {
59          if (gbeanType == null) throw new NullPointerException("gbeanType is null");
60          return createStatic(gbeanType, gbeanType.getName(), gbeanType, source, null);
61      }
62  
63      public static GBeanInfoBuilder createStatic(Class gbeanType, GBeanInfo source, String j2eeType) {
64          if (gbeanType == null) throw new NullPointerException("gbeanType is null");
65          return createStatic(gbeanType, gbeanType.getName(), gbeanType, source, j2eeType);
66      }
67  
68      public static GBeanInfoBuilder createStatic(String name, Class gbeanType, GBeanInfo source) {
69          if (name == null) throw new NullPointerException("name is null");
70          if (gbeanType == null) throw new NullPointerException("gbeanType is null");
71          return createStatic(gbeanType, name, gbeanType, source, null);
72      }
73  
74      //
75      // These methods are used by classes that declare a GBeanInfo for another class
76      //
77      public static GBeanInfoBuilder createStatic(Class sourceClass, Class gbeanType) {
78          if (gbeanType == null) throw new NullPointerException("gbeanType is null");
79          return createStatic(sourceClass, gbeanType.getName(), gbeanType, null, null);
80      }
81  
82      public static GBeanInfoBuilder createStatic(Class sourceClass, Class gbeanType, String j2eeType) {
83          if (sourceClass == null) throw new NullPointerException("sourceClass is null");
84          if (gbeanType == null) throw new NullPointerException("gbeanType is null");
85          return createStatic(sourceClass, gbeanType.getName(), gbeanType, null, j2eeType);
86      }
87  
88      public static GBeanInfoBuilder createStatic(Class sourceClass, Class gbeanType, GBeanInfo source, String j2eeType) {
89          if (sourceClass == null) throw new NullPointerException("sourceClass is null");
90          if (gbeanType == null) throw new NullPointerException("gbeanType is null");
91          return createStatic(sourceClass, gbeanType.getName(), gbeanType, source, j2eeType);
92      }
93  
94      public static GBeanInfoBuilder createStatic(Class sourceClass, String name, Class gbeanType, String j2eeType) {
95          if (sourceClass == null) throw new NullPointerException("sourceClass is null");
96          if (name == null) throw new NullPointerException("name is null");
97          if (gbeanType == null) throw new NullPointerException("gbeanType is null");
98          return createStatic(sourceClass, name, gbeanType, null, j2eeType);
99      }
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(),
191                         operationInfo.getParameterList()), operationInfo);
192             }
193 
194             for (Iterator iterator = source.getReferences().iterator(); iterator.hasNext();) {
195                 GReferenceInfo referenceInfo = (GReferenceInfo) iterator.next();
196                 references.put(referenceInfo.getName(), new RefInfo(referenceInfo.getReferenceType(), referenceInfo.getNameTypeName()));
197             }
198 
199             for (Iterator iterator = source.getInterfaces().iterator(); iterator.hasNext();) {
200                 String intf = (String) iterator.next();
201                 interfaces.add(intf);
202             }
203 
204             //in case subclass constructor has same parameters as superclass.
205             constructor = source.getConstructor();
206 
207             priority = source.getPriority();
208         }
209         if (j2eeType != null) {
210             this.j2eeType = j2eeType;
211         } else if (source != null) {
212             this.j2eeType = source.getJ2eeType();
213         } else {
214             this.j2eeType = DEFAULT_J2EE_TYPE; //NameFactory.GERONIMO_SERVICE
215         }
216 
217         // add all interfaces based on GBean type
218         if (gbeanType.isArray()) {
219             throw new IllegalArgumentException("GBean is an array type: gbeanType=" + gbeanType.getName());
220         }
221         Set allTypes = ClassLoading.getAllTypes(gbeanType);
222         for (Iterator iterator = allTypes.iterator(); iterator.hasNext();) {
223             Class type = (Class) iterator.next();
224             addInterface(type);
225         }
226     }
227 
228     public void setPersistentAttributes(String[] persistentAttributes) {
229         for (int i = 0; i < persistentAttributes.length; i++) {
230             String attributeName = persistentAttributes[i];
231             GAttributeInfo attribute = (GAttributeInfo) attributes.get(attributeName);
232             if (attribute != null && !references.containsKey(attributeName)) {
233                 if (isMagicAttribute(attribute)) {
234                     // magic attributes can't be persistent
235                     continue;
236                 }
237                 attributes.put(attributeName,
238                         new GAttributeInfo(attributeName,
239                                 attribute.getType(),
240                                 true,
241                                 attribute.isManageable(),
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("obectName", 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.getGetterName(),
269                                 attribute.getSetterName()));
270             }
271         }
272     }
273 
274     private boolean isMagicAttribute(GAttributeInfo attributeInfo) {
275         String name = attributeInfo.getName();
276         String type = attributeInfo.getType();
277         return ("kernel".equals(name) && Kernel.class.getName().equals(type)) ||
278                 ("classLoader".equals(name) && ClassLoader.class.getName().equals(type)) ||
279                 ("abstractName".equals(name) && AbstractName.class.getName().equals(type)) ||
280                 ("objectName".equals(name) && String.class.getName().equals(type));
281     }
282 
283     public void addInterface(Class intf) {
284         addInterface(intf, new String[0]);
285     }
286 
287     //do not use beaninfo Introspector to list the properties.  This method is primarily for interfaces,
288     //and it does not process superinterfaces.  It seems to really only work well for classes.
289     public void addInterface(Class intf, String[] persistentAttributes) {
290         addInterface(intf, persistentAttributes, new String[0]);
291     }
292 
293     public void addInterface(Class intf, String[] persistentAttributes, String[] manageableAttributes) {
294         Set persistentNames = new HashSet(Arrays.asList(persistentAttributes));
295         Set manageableNames = new HashSet(Arrays.asList(manageableAttributes));
296         Method[] methods = intf.getMethods();
297         for (int i = 0; i < methods.length; i++) {
298             Method method = methods[i];
299             if (isGetter(method)) {
300                 String attributeName = getAttributeName(method);
301                 GAttributeInfo attribute = (GAttributeInfo) attributes.get(attributeName);
302                 String attributeType = method.getReturnType().getName();
303                 if (attribute == null) {
304                     attributes.put(attributeName,
305                             new GAttributeInfo(attributeName,
306                                     attributeType,
307                                     persistentNames.contains(attributeName),
308                                     manageableNames.contains(attributeName),
309                                     method.getName(),
310                                     null));
311                 } else {
312                     if (!attributeType.equals(attribute.getType())) {
313                         throw new IllegalArgumentException("Getter and setter type do not match: " + attributeName + " for gbeanType: " + gbeanType.getName());
314                     }
315                     attributes.put(attributeName,
316                             new GAttributeInfo(attributeName,
317                                     attributeType,
318                                     attribute.isPersistent() || persistentNames.contains(attributeName),
319                                     attribute.isManageable() || manageableNames.contains(attributeName),
320                                     method.getName(),
321                                     attribute.getSetterName()));
322                 }
323             } else if (isSetter(method)) {
324                 String attributeName = getAttributeName(method);
325                 String attributeType = method.getParameterTypes()[0].getName();
326                 GAttributeInfo attribute = (GAttributeInfo) attributes.get(attributeName);
327                 if (attribute == null) {
328                     attributes.put(attributeName,
329                             new GAttributeInfo(attributeName,
330                                     attributeType,
331                                     persistentNames.contains(attributeName),
332                                     manageableNames.contains(attributeName),
333                                     null,
334                                     method.getName()));
335                 } else {
336                     if (!attributeType.equals(attribute.getType())) {
337                         throw new IllegalArgumentException("Getter and setter type do not match: " + attributeName + " for gbeanType: " + gbeanType.getName());
338                     }
339                     attributes.put(attributeName,
340                             new GAttributeInfo(attributeName,
341                                     attributeType,
342                                     attribute.isPersistent() || persistentNames.contains(attributeName),
343                                     attribute.isManageable() || manageableNames.contains(attributeName),
344                                     attribute.getGetterName(),
345                                     method.getName()));
346                 }
347             } else {
348                 addOperation(new GOperationInfo(method.getName(), method.getParameterTypes()));
349             }
350         }
351         addInterface(interfaces, intf);
352     }
353 
354     private static void addInterface(Set set, Class intf) {
355         String name = intf.getName();
356         if(set.contains(name)) {
357             return;
358         }
359         set.add(name);
360         Class cls[] = intf.getInterfaces();
361         for (int i = 0; i < cls.length; i++) {
362             addInterface(set, cls[i]);
363         }
364     }
365 
366     public void addAttribute(String name, Class type, boolean persistent) {
367         addAttribute(name, type.getName(), persistent, true);
368     }
369 
370     public void addAttribute(String name, String type, boolean persistent) {
371         addAttribute(name, type, persistent, true);
372     }
373 
374     public void addAttribute(String name, Class type, boolean persistent, boolean manageable) {
375         addAttribute(name, type.getName(), persistent, manageable);
376     }
377 
378     public void addAttribute(String name, String type, boolean persistent, boolean manageable) {
379         String getter = searchForGetter(name, type, gbeanType);
380         String setter = searchForSetter(name, type, gbeanType);
381         addAttribute(new GAttributeInfo(name, type, persistent, manageable, getter, setter));
382     }
383 
384     public void addAttribute(GAttributeInfo info) {
385         attributes.put(info.getName(), info);
386     }
387 
388     public void setConstructor(GConstructorInfo constructor) {
389         assert constructor != null;
390         this.constructor = constructor;
391         List names = constructor.getAttributeNames();
392         setPersistentAttributes((String[]) names.toArray(new String[names.size()]));
393     }
394 
395     public void setConstructor(String[] names) {
396         constructor = new GConstructorInfo(names);
397         setPersistentAttributes(names);
398     }
399 
400     public void addOperation(GOperationInfo operationInfo) {
401         operations.put(new GOperationSignature(operationInfo.getName(), operationInfo.getParameterList()), operationInfo);
402     }
403 
404     public void addOperation(String name) {
405         addOperation(new GOperationInfo(name, NO_ARGS));
406     }
407 
408     public void addOperation(String name, Class[] paramTypes) {
409         addOperation(new GOperationInfo(name, paramTypes));
410     }
411 
412     public void addReference(GReferenceInfo info) {
413         references.put(info.getName(), new RefInfo(info.getReferenceType(), info.getNameTypeName()));
414     }
415 
416     /**
417      * Add a reference to another GBean or collection of GBeans
418      * @param name the name of the reference
419      * @param type The proxy type of the GBean or objects in a ReferenceCollection
420      * @param namingType the string expected as the type component of the name.  For jsr-77 names this is the j2eeType value
421      */
422     public void addReference(String name, Class type, String namingType) {
423         references.put(name, new RefInfo(type.getName(), namingType));
424     }
425 
426     public void addReference(String name, Class type) {
427         references.put(name, new RefInfo(type.getName(), null));
428     }
429 
430     public void setPriority(int priority) {
431         this.priority = priority;
432     }
433 
434     public GBeanInfo getBeanInfo() {
435         // get the types of the constructor args
436         // this also verifies that we have a valid constructor
437         Map constructorTypes = getConstructorTypes();
438 
439         // build the reference infos now that we know the constructor types
440         Set referenceInfos = new HashSet();
441         for (Iterator iterator = references.entrySet().iterator(); iterator.hasNext();) {
442             Map.Entry entry = (Map.Entry) iterator.next();
443             String referenceName = (String) entry.getKey();
444             RefInfo refInfo = (RefInfo) entry.getValue();
445             String referenceType = refInfo.getJavaType();
446             String namingType = refInfo.getNamingType();
447 
448             String proxyType = (String) constructorTypes.get(referenceName);
449             String setterName = null;
450             if (proxyType == null) {
451                 Method setter = searchForSetterMethod(referenceName, referenceType, gbeanType);
452                 if (setter == null) {
453                     setter = searchForSetterMethod(referenceName, Collection.class.getName(), gbeanType);
454                     if (setter == null) {
455                         throw new InvalidConfigurationException("Reference must be a constructor argument or have a setter: name=" + referenceName + " for gbeanType: " + gbeanType);
456                     }
457                 }
458                 proxyType = setter.getParameterTypes()[0].getName();
459 
460                 setterName = setter.getName();
461             }
462 
463             if (!proxyType.equals(Collection.class.getName()) && !proxyType.equals(referenceType)) {
464                 throw new InvalidConfigurationException("Reference proxy type must be Collection or " + referenceType + ": name=" + referenceName + " for gbeanType: " + gbeanType.getName());
465             }
466 
467             referenceInfos.add(new GReferenceInfo(referenceName, referenceType, proxyType, setterName, namingType));
468         }
469 
470         return new GBeanInfo(sourceClass, name, gbeanType.getName(), j2eeType, attributes.values(), constructor, operations.values(), referenceInfos, interfaces, priority);
471     }
472 
473     private Map getConstructorTypes() throws InvalidConfigurationException {
474         List arguments = constructor.getAttributeNames();
475         String[] argumentTypes = new String[arguments.size()];
476         boolean[] isReference = new boolean[arguments.size()];
477         for (int i = 0; i < argumentTypes.length; i++) {
478             String argumentName = (String) arguments.get(i);
479             if (references.containsKey(argumentName)) {
480                 argumentTypes[i] = ((RefInfo) references.get(argumentName)).getJavaType();
481                 isReference[i] = true;
482             } else if (attributes.containsKey(argumentName)) {
483                 GAttributeInfo attribute = (GAttributeInfo) attributes.get(argumentName);
484                 argumentTypes[i] = attribute.getType();
485                 isReference[i] = false;
486             }  
487         }
488 
489         Constructor[] constructors = gbeanType.getConstructors();
490         Set validConstructors = new HashSet();
491         for (int i = 0; i < constructors.length; i++) {
492             Constructor constructor = constructors[i];
493             if (isValidConstructor(constructor, argumentTypes, isReference)) {
494                 validConstructors.add(constructor);
495             }
496         }
497 
498         if (validConstructors.isEmpty()) {
499             throw new InvalidConfigurationException("Could not find a valid constructor for GBean: " + gbeanType.getName());
500         }
501         if (validConstructors.size() > 1) {
502             throw new InvalidConfigurationException("More then one valid constructors found for GBean: " + gbeanType.getName());
503         }
504 
505         Map constructorTypes = new HashMap();
506         Constructor constructor = (Constructor) validConstructors.iterator().next();
507         Class[] parameterTypes = constructor.getParameterTypes();
508         Iterator argumentIterator = arguments.iterator();
509         for (int i = 0; i < parameterTypes.length; i++) {
510             String parameterType = parameterTypes[i].getName();
511             String argumentName = (String) argumentIterator.next();
512             constructorTypes.put(argumentName, parameterType);
513         }
514         return constructorTypes;
515     }
516 
517     private static String searchForGetter(String name, String type, Class gbeanType) throws InvalidConfigurationException {
518         Method getterMethod = null;
519 
520         // no explicit name give so we must search for a name
521         String getterName = "get" + name;
522         String isName = "is" + name;
523         Method[] methods = gbeanType.getMethods();
524         for (int i = 0; i < methods.length; i++) {
525             if (methods[i].getParameterTypes().length == 0 && methods[i].getReturnType() != Void.TYPE
526                     && (getterName.equalsIgnoreCase(methods[i].getName()) || isName.equalsIgnoreCase(methods[i].getName()))) {
527 
528                 // found it
529                 getterMethod = methods[i];
530                 break;
531             }
532         }
533 
534         // if the return type of the getter doesn't match, throw an exception
535         if (getterMethod != null && !type.equals(getterMethod.getReturnType().getName())) {
536             throw new InvalidConfigurationException("Incorrect return type for getter method:" +
537                     " name=" + name +
538                     ", targetClass=" + gbeanType.getName() +
539                     ", getter type=" + getterMethod.getReturnType() +
540                     ", expected type=" + type);
541         }
542 
543         if (getterMethod == null) {
544             return null;
545         }
546         return getterMethod.getName();
547     }
548 
549     private static String searchForSetter(String name, String type, Class gbeanType) throws InvalidConfigurationException {
550         Method method = searchForSetterMethod(name, type, gbeanType);
551         if (method == null) {
552             return null;
553         }
554         return method.getName();
555     }
556 
557     private static Method searchForSetterMethod(String name, String type, Class gbeanType) throws InvalidConfigurationException {
558         // no explicit name give so we must search for a name
559         String setterName = "set" + name;
560         Method[] methods = gbeanType.getMethods();
561         for (int i = 0; i < methods.length; i++) {
562             Method method = methods[i];
563             if (method.getParameterTypes().length == 1 &&
564                     method.getParameterTypes()[0].getName().equals(type) &&
565                     method.getReturnType() == Void.TYPE &&
566                     setterName.equalsIgnoreCase(method.getName())) {
567 
568                 return method;
569             }
570         }
571 
572         // a setter is not necessary for this attribute
573         return null;
574     }
575 
576     private static boolean isValidConstructor(Constructor constructor, String[] argumentTypes, boolean[] isReference) {
577         Class[] parameterTypes = constructor.getParameterTypes();
578 
579         // same number of parameters?
580         if (parameterTypes.length != argumentTypes.length) {
581             return false;
582         }
583 
584         // is each parameter the correct type?
585         for (int i = 0; i < parameterTypes.length; i++) {
586             String parameterType = parameterTypes[i].getName();
587             if (isReference[i]) {
588                 // reference: does type match
589                 // OR is it a java.util.Collection
590                 // OR is it a java.util.Set?
591                 if (!parameterType.equals(argumentTypes[i]) &&
592                         !parameterType.equals(Collection.class.getName()) &&
593                         !parameterType.equals(Set.class.getName())) {
594                     return false;
595                 }
596             } else {
597                 // attribute: does type match?
598                 if (!parameterType.equals(argumentTypes[i])) {
599                     return false;
600                 }
601             }
602         }
603         return true;
604     }
605 
606     private String getAttributeName(Method method) {
607         String name = method.getName();
608         String attributeName = (name.startsWith("get") || name.startsWith("set")) ? name.substring(3) : name.substring(2);
609         attributeName = Introspector.decapitalize(attributeName);
610         return attributeName;
611     }
612 
613     private boolean isSetter(Method method) {
614         return method.getName().startsWith("set") && method.getParameterTypes().length == 1;
615     }
616 
617     private static boolean isGetter(Method method) {
618         String name = method.getName();
619         return (name.startsWith("get") || name.startsWith("is")) && method.getParameterTypes().length == 0;
620     }
621 
622     /**
623      * Checks whether or not the input argument is null; otherwise it throws
624      * {@link IllegalArgumentException}.
625      *
626      * @param clazz the input argument to validate
627      * @throws IllegalArgumentException if input is null
628      */
629     private static Class checkNotNull(final Class clazz) {
630         if (clazz == null) {
631             throw new IllegalArgumentException("null argument supplied");
632         }
633         return clazz;
634     }
635 
636     /**
637      * Checks whether or not the input argument is null; otherwise it throws
638      * {@link IllegalArgumentException}.
639      *
640      * @param string the input argument to validate
641      * @throws IllegalArgumentException if input is null
642      */
643     private static String checkNotNull(final String string) {
644         if (string == null) {
645             throw new IllegalArgumentException("null argument supplied");
646         }
647         return string;
648     }
649 
650     private static Class loadClass(ClassLoader classLoader, String name) {
651         try {
652             return classLoader.loadClass(name);
653         } catch (ClassNotFoundException e) {
654             throw new InvalidConfigurationException("Could not load class " + name, e);
655         }
656     }
657 
658     private static class RefInfo {
659         private final String javaType;
660         private final String namingType;
661 
662         public RefInfo(String javaType, String namingType) {
663             this.javaType = javaType;
664             this.namingType = namingType;
665         }
666 
667         public String getJavaType() {
668             return javaType;
669         }
670 
671         public String getNamingType() {
672             return namingType;
673         }
674     }
675 }