| 1 18 19 package org.apache.tools.ant; 20 21 import java.lang.reflect.Constructor ; 22 import java.lang.reflect.InvocationTargetException ; 23 import java.lang.reflect.Method ; 24 import java.util.ArrayList ; 25 import java.util.Collections ; 26 import java.util.Enumeration ; 27 import java.util.Hashtable ; 28 import java.util.HashMap ; 29 import java.util.List ; 30 import java.util.Locale ; 31 import java.util.Map ; 32 import org.apache.tools.ant.types.EnumeratedAttribute; 33 import org.apache.tools.ant.taskdefs.PreSetDef; 34 35 41 public final class IntrospectionHelper { 42 43 47 private static final Map EMPTY_MAP 48 = Collections.unmodifiableMap(new HashMap (0)); 49 50 53 private static final Map HELPERS = new Hashtable (); 54 55 61 private static final Map PRIMITIVE_TYPE_MAP = new HashMap (8); 62 63 static { 65 Class [] primitives = {Boolean.TYPE, Byte.TYPE, Character.TYPE, 66 Short.TYPE, Integer.TYPE, Long.TYPE, 67 Float.TYPE, Double.TYPE}; 68 Class [] wrappers = {Boolean .class, Byte .class, Character .class, 69 Short .class, Integer .class, Long .class, 70 Float .class, Double .class}; 71 for (int i = 0; i < primitives.length; i++) { 72 PRIMITIVE_TYPE_MAP.put (primitives[i], wrappers[i]); 73 } 74 } 75 76 private static final int MAX_REPORT_NESTED_TEXT = 20; 77 private static final String ELLIPSIS = "..."; 78 79 83 private Hashtable attributeTypes = new Hashtable (); 84 85 89 private Hashtable attributeSetters = new Hashtable (); 90 91 95 private Hashtable nestedTypes = new Hashtable (); 96 97 101 private Hashtable nestedCreators = new Hashtable (); 102 103 106 private List addTypeMethods = new ArrayList (); 107 108 111 private Method addText = null; 112 113 116 private Class bean; 117 118 163 private IntrospectionHelper(final Class bean) { 164 this.bean = bean; 165 Method [] methods = bean.getMethods(); 166 for (int i = 0; i < methods.length; i++) { 167 final Method m = methods[i]; 168 final String name = m.getName(); 169 Class returnType = m.getReturnType(); 170 Class [] args = m.getParameterTypes(); 171 172 if (args.length == 1 && java.lang.Void.TYPE.equals(returnType) 174 && ("add".equals(name) || "addConfigured".equals(name))) { 175 insertAddTypeMethod(m); 176 continue; 177 } 178 if (org.apache.tools.ant.ProjectComponent.class.isAssignableFrom( 180 bean) 181 && args.length == 1 && isHiddenSetMethod(name, args[0])) { 182 continue; 183 } 184 if (isContainer() && args.length == 1 && "addTask".equals(name) 186 && org.apache.tools.ant.Task.class.equals(args[0])) { 187 continue; 188 } 189 if ("addText".equals(name) && java.lang.Void.TYPE.equals(returnType) 190 && args.length == 1 && java.lang.String .class.equals(args[0])) { 191 192 addText = methods[i]; 193 } else if (name.startsWith("set") 194 && java.lang.Void.TYPE.equals(returnType) 195 && args.length == 1 && !args[0].isArray()) { 196 String propName = getPropertyName(name, "set"); 197 if (attributeSetters.get(propName) != null) { 198 if (java.lang.String .class.equals(args[0])) { 199 205 continue; 206 } 207 218 } 219 AttributeSetter as = createAttributeSetter(m, args[0], propName); 220 if (as != null) { 221 attributeTypes.put(propName, args[0]); 222 attributeSetters.put(propName, as); 223 } 224 } else if (name.startsWith("create") && !returnType.isArray() 225 && !returnType.isPrimitive() && args.length == 0) { 226 227 String propName = getPropertyName(name, "create"); 228 if (nestedCreators.get(propName) == null) { 231 nestedTypes.put(propName, returnType); 232 nestedCreators.put(propName, new CreateNestedCreator(m)); 233 } 234 } else if (name.startsWith("addConfigured") 235 && java.lang.Void.TYPE.equals(returnType) && args.length == 1 236 && !java.lang.String .class.equals(args[0]) 237 && !args[0].isArray() && !args[0].isPrimitive()) { 238 try { 239 Constructor constructor = null; 240 try { 241 constructor = args[0].getConstructor(new Class [] {}); 242 } catch (NoSuchMethodException ex) { 243 constructor = 244 args[0].getConstructor(new Class [] {Project.class}); 245 } 246 String propName = getPropertyName(name, "addConfigured"); 247 nestedTypes.put(propName, args[0]); 248 nestedCreators.put(propName, new AddNestedCreator(m, 249 constructor, AddNestedCreator.ADD_CONFIGURED)); 250 } catch (NoSuchMethodException nse) { 251 } 253 } else if (name.startsWith("add") 254 && java.lang.Void.TYPE.equals(returnType) && args.length == 1 255 && !java.lang.String .class.equals(args[0]) 256 && !args[0].isArray() && !args[0].isPrimitive()) { 257 try { 258 Constructor constructor = null; 259 try { 260 constructor = args[0].getConstructor(new Class [] {}); 261 } catch (NoSuchMethodException ex) { 262 constructor = 263 args[0].getConstructor(new Class [] {Project.class}); 264 } 265 266 String propName = getPropertyName(name, "add"); 267 if (nestedTypes.get(propName) != null) { 268 273 continue; 274 } 275 nestedTypes.put(propName, args[0]); 276 nestedCreators.put(propName, new AddNestedCreator(m, 277 constructor, AddNestedCreator.ADD)); 278 } catch (NoSuchMethodException nse) { 279 } 281 } 282 } 283 } 284 285 293 private boolean isHiddenSetMethod(String name, Class type) { 294 if ("setLocation".equals(name) 295 && org.apache.tools.ant.Location.class.equals(type)) { 296 return true; 297 } 298 299 if ("setTaskType".equals(name) 300 && java.lang.String .class.equals(type)) { 301 return true; 302 } 303 304 return false; 305 } 306 307 316 public static synchronized IntrospectionHelper getHelper(Class c) { 317 return getHelper(null, c); 318 } 319 320 333 public static IntrospectionHelper getHelper(Project p, Class c) { 334 IntrospectionHelper ih = (IntrospectionHelper) HELPERS.get(c.getName()); 335 if (ih == null || ih.bean != c) { 338 ih = new IntrospectionHelper(c); 339 if (p != null) { 340 HELPERS.put(c.getName(), ih); 343 } 344 } 345 return ih; 346 } 347 348 366 public void setAttribute(Project p, Object element, String attributeName, 367 String value) throws BuildException { 368 AttributeSetter as 369 = (AttributeSetter) attributeSetters.get( 370 attributeName.toLowerCase(Locale.US)); 371 if (as == null) { 372 if (element instanceof DynamicAttributeNS) { 373 DynamicAttributeNS dc = (DynamicAttributeNS) element; 374 String uriPlusPrefix = 375 ProjectHelper.extractUriFromComponentName(attributeName); 376 String uri = 377 ProjectHelper.extractUriFromComponentName(uriPlusPrefix); 378 String localName = 379 ProjectHelper.extractNameFromComponentName(attributeName); 380 String qName = ("".equals(uri) 381 ? localName : (uri + ":" + localName)); 382 383 dc.setDynamicAttribute(uri, localName, qName, value); 384 return; 385 } else if (element instanceof DynamicAttribute) { 386 DynamicAttribute dc = (DynamicAttribute) element; 387 dc.setDynamicAttribute(attributeName.toLowerCase(Locale.US), value); 388 return; 389 } else { 390 if (attributeName.indexOf(':') != -1) { 391 return; } 393 String msg = getElementName(p, element) 394 + " doesn't support the \"" + attributeName 395 + "\" attribute."; 396 throw new UnsupportedAttributeException(msg, attributeName); 397 } 398 } 399 try { 400 as.set(p, element, value); 401 } catch (IllegalAccessException ie) { 402 throw new BuildException(ie); 404 } catch (InvocationTargetException ite) { 405 Throwable t = ite.getTargetException(); 406 if (t instanceof BuildException) { 407 throw (BuildException) t; 408 } 409 throw new BuildException(t); 410 } 411 } 412 413 414 431 public void addText(Project project, Object element, String text) 432 throws BuildException { 433 if (addText == null) { 434 text = text.trim(); 435 if (text.length() == 0) { 437 return; 439 } else { 440 String msg = project.getElementName(element) 442 + " doesn't support nested text data (\"" 443 + condenseText(text) + "\")."; 444 throw new BuildException(msg); 445 } 446 } 447 try { 448 addText.invoke(element, new Object [] {text}); 449 } catch (IllegalAccessException ie) { 450 throw new BuildException(ie); 452 } catch (InvocationTargetException ite) { 453 Throwable t = ite.getTargetException(); 454 if (t instanceof BuildException) { 455 throw (BuildException) t; 456 } 457 throw new BuildException(t); 458 } 459 } 460 461 468 public void throwNotSupported(Project project, Object parent, 469 String elementName) { 470 String msg = project.getElementName(parent) 471 + " doesn't support the nested \"" + elementName + "\" element."; 472 throw new UnsupportedElementException(msg, elementName); 473 } 474 475 private NestedCreator getNestedCreator( 476 Project project, String parentUri, Object parent, 477 String elementName, UnknownElement child) throws BuildException { 478 479 String uri = ProjectHelper.extractUriFromComponentName(elementName); 480 String name = ProjectHelper.extractNameFromComponentName(elementName); 481 482 if (uri.equals(ProjectHelper.ANT_CORE_URI)) { 483 uri = ""; 484 } 485 if (parentUri.equals(ProjectHelper.ANT_CORE_URI)) { 486 parentUri = ""; 487 } 488 NestedCreator nc = null; 489 if (uri.equals(parentUri) || uri.equals("")) { 490 nc = (NestedCreator) nestedCreators.get( 491 name.toLowerCase(Locale.US)); 492 } 493 if (nc == null) { 494 nc = createAddTypeCreator(project, parent, elementName); 495 } 496 if (nc == null && parent instanceof DynamicElementNS) { 497 DynamicElementNS dc = (DynamicElementNS) parent; 498 String qName = (child == null ? name : child.getQName()); 499 final Object nestedElement = 500 dc.createDynamicElement( 501 (child == null ? "" : child.getNamespace()), 502 name, qName); 503 if (nestedElement != null) { 504 nc = new NestedCreator(null) { 505 Object create( 506 Project project, Object parent, Object ignore) { 507 return nestedElement; 508 } 509 }; 510 } 511 } 512 if (nc == null && parent instanceof DynamicElement) { 513 DynamicElement dc = (DynamicElement) parent; 514 final Object nestedElement = 515 dc.createDynamicElement(name.toLowerCase(Locale.US)); 516 if (nestedElement != null) { 517 nc = new NestedCreator(null) { 518 Object create( 519 Project project, Object parent, Object ignore) { 520 return nestedElement; 521 } 522 }; 523 } 524 } 525 if (nc == null) { 526 throwNotSupported(project, parent, elementName); 527 } 528 return nc; 529 } 530 531 554 public Object createElement(Project project, Object parent, 555 String elementName) throws BuildException { 556 NestedCreator nc = getNestedCreator(project, "", parent, elementName, null); 557 try { 558 Object nestedElement = nc.create(project, parent, null); 559 if (project != null) { 560 project.setProjectReference(nestedElement); 561 } 562 return nestedElement; 563 } catch (IllegalAccessException ie) { 564 throw new BuildException(ie); 566 } catch (InstantiationException ine) { 567 throw new BuildException(ine); 569 } catch (InvocationTargetException ite) { 570 Throwable t = ite.getTargetException(); 571 if (t instanceof BuildException) { 572 throw (BuildException) t; 573 } 574 throw new BuildException(t); 575 } 576 } 577 578 590 public Creator getElementCreator( 591 Project project, String parentUri, Object parent, String elementName, 592 UnknownElement ue) { 593 NestedCreator nc = getNestedCreator( 594 project, parentUri, parent, elementName, ue); 595 return new Creator(project, parent, nc); 596 } 597 598 609 public boolean isDynamic() { 610 return DynamicElement.class.isAssignableFrom(bean) 611 || DynamicElementNS.class.isAssignableFrom(bean); 612 } 613 614 624 public boolean isContainer() { 625 return TaskContainer.class.isAssignableFrom(bean); 626 } 627 628 636 public boolean supportsNestedElement(String elementName) { 637 return nestedCreators.containsKey(elementName.toLowerCase(Locale.US)) 638 || isDynamic() 639 || addTypeMethods.size() != 0; 640 } 641 642 651 public boolean supportsNestedElement(String parentUri, String elementName) { 652 if (parentUri.equals(ProjectHelper.ANT_CORE_URI)) { 653 parentUri = ""; 654 } 655 String uri = ProjectHelper.extractUriFromComponentName(elementName); 656 if (uri.equals(ProjectHelper.ANT_CORE_URI)) { 657 uri = ""; 658 } 659 String name = ProjectHelper.extractNameFromComponentName(elementName); 660 661 return ( 662 nestedCreators.containsKey(name.toLowerCase(Locale.US)) 663 && (uri.equals(parentUri) || "".equals(uri))) 664 || isDynamic() || addTypeMethods.size() != 0; 665 } 666 667 687 public void storeElement(Project project, Object parent, Object child, 688 String elementName) throws BuildException { 689 if (elementName == null) { 690 return; 691 } 692 NestedCreator ns = (NestedCreator) nestedCreators.get( 693 elementName.toLowerCase(Locale.US)); 694 if (ns == null) { 695 return; 696 } 697 try { 698 ns.store(parent, child); 699 } catch (IllegalAccessException ie) { 700 throw new BuildException(ie); 702 } catch (InstantiationException ine) { 703 throw new BuildException(ine); 705 } catch (InvocationTargetException ite) { 706 Throwable t = ite.getTargetException(); 707
|