1 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 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 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"; 110 private static final Class [] NO_ARGS = {}; 111 112 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 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 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; } 215 216 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 continue; 235 } 236 attributes.put(attributeName, 237 new GAttributeInfo(attributeName, 238 attribute.getType(), 239 true, 240 attribute.isManageable(), 241 attribute.getGetterName(), 242 attribute.getSetterName())); 243 } else { 244 if (attributeName.equals("kernel")) { 245 addAttribute("kernel", Kernel.class, false); 246 } else if (attributeName.equals("classLoader")) { 247 addAttribute("classLoader", ClassLoader .class, false); 248 } else if (attributeName.equals("abstractName")) { 249 addAttribute("abstractName", AbstractName.class, false); 250 } else if (attributeName.equals("objectName")) { 251 addAttribute("obectName", String .class, false); 252 } 253 } 254 } 255 } 256 257 public void setManageableAttributes(String [] manageableAttributes) { 258 for (int i = 0; i < manageableAttributes.length; i++) { 259 String attributeName = manageableAttributes[i]; 260 GAttributeInfo attribute = (GAttributeInfo) attributes.get(attributeName); 261 if (attribute != null) { 262 attributes.put(attributeName, 263 new GAttributeInfo(attributeName, 264 attribute.getType(), 265 attribute.isPersistent(), 266 true, 267 attribute.getGetterName(), 268 attribute.getSetterName())); 269 } 270 } 271 } 272 273 private boolean isMagicAttribute(GAttributeInfo attributeInfo) { 274 String name = attributeInfo.getName(); 275 String type = attributeInfo.getType(); 276 return ("kernel".equals(name) && Kernel.class.getName().equals(type)) || 277 ("classLoader".equals(name) && ClassLoader .class.getName().equals(type)) || 278 ("abstractName".equals(name) && AbstractName.class.getName().equals(type)) || 279 ("objectName".equals(name) && String .class.getName().equals(type)); 280 } 281 282 public void addInterface(Class intf) { 283 addInterface(intf, new String [0]); 284 } 285 286 public void addInterface(Class intf, String [] persistentAttributes) { 289 addInterface(intf, persistentAttributes, new String [0]); 290 } 291 292 public void addInterface(Class intf, String [] persistentAttributes, String [] manageableAttributes) { 293 Set persistentNames = new HashSet (Arrays.asList(persistentAttributes)); 294 Set manageableNames = new HashSet (Arrays.asList(manageableAttributes)); 295 Method [] methods = intf.getMethods(); 296 for (int i = 0; i < methods.length; i++) { 297 Method method = methods[i]; 298 if ("java.lang.Object".equals(method.getDeclaringClass().getName())) continue; 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(), method.getReturnType().getName())); 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 407 public void addOperation(String name) { 408 addOperation(new GOperationInfo(name, NO_ARGS, "")); 409 } 410 411 414 public void addOperation(String name, Class [] paramTypes) { 415 addOperation(new GOperationInfo(name, paramTypes, "")); 416 } 417 418 public void addOperation(String name, String returnType) { 419 addOperation(new GOperationInfo(name, NO_ARGS, returnType)); 420 } 421 422 public void addOperation(String name, Class [] paramTypes, String returnType) { 423 addOperation(new GOperationInfo(name, paramTypes, returnType)); 424 } 425 426 public void addReference(GReferenceInfo info) { 427 references.put(info.getName(), new RefInfo(info.getReferenceType(), info.getNameTypeName())); 428 } 429 430 436 public void addReference(String name, Class type, String namingType) { 437 references.put(name, new RefInfo(type.getName(), namingType)); 438 } 439 440 public void addReference(String name, Class type) { 441 references.put(name, new RefInfo(type.getName(), null)); 442 } 443 444 public void setPriority(int priority) { 445 this.priority = priority; 446 } 447 448 public GBeanInfo getBeanInfo() { 449 Map constructorTypes = getConstructorTypes(); 452 453 Set referenceInfos = new HashSet (); 455 for (Iterator iterator = references.entrySet().iterator(); iterator.hasNext();) { 456 Map.Entry entry = (Map.Entry ) iterator.next(); 457 String referenceName = (String ) entry.getKey(); 458 RefInfo refInfo = (RefInfo) entry.getValue(); 459 String referenceType = refInfo.getJavaType(); 460 String namingType = refInfo.getNamingType(); 461 462 String proxyType = (String ) constructorTypes.get(referenceName); 463 String setterName = null; 464 if (proxyType == null) { 465 Method setter = searchForSetterMethod(referenceName, referenceType, gbeanType); 466 if (setter == null) { 467 setter = searchForSetterMethod(referenceName, Collection .class.getName(), gbeanType); 468 if (setter == null) { 469 throw new InvalidConfigurationException("Reference must be a constructor argument or have a setter: name=" + referenceName + " for gbeanType: " + gbeanType); 470 } 471 } 472 proxyType = setter.getParameterTypes()[0].getName(); 473 474 setterName = setter.getName(); 475 } 476 477 if (!proxyType.equals(Collection .class.getName()) && !proxyType.equals(referenceType)) { 478 throw new InvalidConfigurationException("Reference proxy type must be Collection or " + referenceType + ": name=" + referenceName + " for gbeanType: " + gbeanType.getName()); 479 } 480 481 referenceInfos.add(new GReferenceInfo(referenceName, referenceType, proxyType, setterName, namingType)); 482 } 483 484 return new GBeanInfo(sourceClass, name, gbeanType.getName(), j2eeType, attributes.values(), constructor, operations.values(), referenceInfos, interfaces, priority); 485 } 486 487 private Map getConstructorTypes() throws InvalidConfigurationException { 488 List arguments = constructor.getAttributeNames(); 489 String [] argumentTypes = new String [arguments.size()]; 490 boolean[] isReference = new boolean[arguments.size()]; 491 for (int i = 0; i < argumentTypes.length; i++) { 492 String argumentName = (String ) arguments.get(i); 493 if (references.containsKey(argumentName)) { 494 argumentTypes[i] = ((RefInfo) references.get(argumentName)).getJavaType(); 495 isReference[i] = true; 496 } else if (attributes.containsKey(argumentName)) { 497 GAttributeInfo attribute = (GAttributeInfo) attributes.get(argumentName); 498 argumentTypes[i] = attribute.getType(); 499 isReference[i] = false; 500 } 501 } 502 503 Constructor [] constructors = gbeanType.getConstructors(); 504 Set validConstructors = new HashSet (); 505 for (int i = 0; i < constructors.length; i++) { 506 Constructor constructor = constructors[i]; 507 if (isValidConstructor(constructor, argumentTypes, isReference)) { 508 validConstructors.add(constructor); 509 } 510 } 511 512 if (validConstructors.isEmpty()) { 513 throw new InvalidConfigurationException("Could not find a valid constructor for GBean: " + gbeanType.getName()); 514 } 515 if (validConstructors.size() > 1) { 516 throw new InvalidConfigurationException("More then one valid constructors found for GBean: " + gbeanType.getName()); 517 } 518 519 Map constructorTypes = new HashMap (); 520 Constructor constructor = (Constructor ) validConstructors.iterator().next(); 521 Class [] parameterTypes = constructor.getParameterTypes(); 522 Iterator argumentIterator = arguments.iterator(); 523 for (int i = 0; i < parameterTypes.length; i++) { 524 String parameterType = parameterTypes[i].getName(); 525 String argumentName = (String ) argumentIterator.next(); 526 constructorTypes.put(argumentName, parameterType); 527 } 528 return constructorTypes; 529 } 530 531 private static String searchForGetter(String name, String type, Class gbeanType) throws InvalidConfigurationException { 532 Method getterMethod = null; 533 534 String getterName = "get" + name; 536 String isName = "is" + name; 537 Method [] methods = gbeanType.getMethods(); 538 for (int i = 0; i < methods.length; i++) { 539 if (methods[i].getParameterTypes().length == 0 && methods[i].getReturnType() != Void.TYPE 540 && (getterName.equalsIgnoreCase(methods[i].getName()) || isName.equalsIgnoreCase(methods[i].getName()))) { 541 542 getterMethod = methods[i]; 544 break; 545 } 546 } 547 548 if (getterMethod != null && !type.equals(getterMethod.getReturnType().getName())) { 550 throw new InvalidConfigurationException("Incorrect return type for getter method:" + 551 " name=" + name + 552 ", targetClass=" + gbeanType.getName() + 553 ", getter type=" + getterMethod.getReturnType() + 554 ", expected type=" + type); 555 } 556 557 if (getterMethod == null) { 558 return null; 559 } 560 return getterMethod.getName(); 561 } 562 563 private static String searchForSetter(String name, String type, Class gbeanType) throws InvalidConfigurationException { 564 Method method = searchForSetterMethod(name, type, gbeanType); 565 if (method == null) { 566 return null; 567 } 568 return method.getName(); 569 } 570 571 private static Method searchForSetterMethod(String name, String type, Class gbeanType) throws InvalidConfigurationException { 572 String setterName = "set" + name; 574 Method [] methods = gbeanType.getMethods(); 575 for (int i = 0; i < methods.length; i++) { 576 Method method = methods[i]; 577 if (method.getParameterTypes().length == 1 && 578 method.getParameterTypes()[0].getName().equals(type) && 579 method.getReturnType() == Void.TYPE && 580 setterName.equalsIgnoreCase(method.getName())) { 581 582 return method; 583 } 584 } 585 586 return null; 588 } 589 590 private static boolean isValidConstructor(Constructor constructor, String [] argumentTypes, boolean[] isReference) { 591 Class [] parameterTypes = constructor.getParameterTypes(); 592 593 if (parameterTypes.length != argumentTypes.length) { 595 return false; 596 } 597 598 for (int i = 0; i < parameterTypes.length; i++) { 600 String parameterType = parameterTypes[i].getName(); 601 if (isReference[i]) { 602 if (!parameterType.equals(argumentTypes[i]) && 606 !parameterType.equals(Collection .class.getName()) && 607 !parameterType.equals(Set .class.getName())) { 608 return false; 609 } 610 } else { 611 if (!parameterType.equals(argumentTypes[i])) { 613 return false; 614 } 615 } 616 } 617 return true; 618 } 619 620 private String getAttributeName(Method method) { 621 String name = method.getName(); 622 String attributeName = (name.startsWith("get") || name.startsWith("set")) ? name.substring(3) : name.substring(2); 623 attributeName = Introspector.decapitalize(attributeName); 624 return attributeName; 625 } 626 627 private boolean isSetter(Method method) { 628 return method.getName().startsWith("set") && method.getParameterTypes().length == 1; 629 } 630 631 private static boolean isGetter(Method method) { 632 String name = method.getName(); 633 return (name.startsWith("get") || name.startsWith("is")) && method.getParameterTypes().length == 0; 634 } 635 636 643 private static Class checkNotNull(final Class clazz) { 644 if (clazz == null) { 645 throw new IllegalArgumentException ("null argument supplied"); 646 } 647 return clazz; 648 } 649 650 657 private static String checkNotNull(final String string) { 658 if (string == null) { 659 throw new IllegalArgumentException ("null argument supplied"); 660 } 661 return string; 662 } 663 664 private static Class loadClass(ClassLoader classLoader, String name) { 665 try { 666 return classLoader.loadClass(name); 667 } catch (ClassNotFoundException e) { 668 throw new InvalidConfigurationException("Could not load class " + name, e); 669 } 670 } 671 672 private static class RefInfo { 673 private final String javaType; 674 private final String namingType; 675 676 public RefInfo(String javaType, String namingType) { 677 this.javaType = javaType; 678 this.namingType = namingType; 679 } 680 681 public String getJavaType() { 682 return javaType; 683 } 684 685 public String getNamingType() { 686 return namingType; 687 } 688 } 689 } 690 | Popular Tags |