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 if (t instanceof BuildException) { 708 throw (BuildException) t; 709 } 710 throw new BuildException(t); 711 } 712 } 713 714 726 public Class getElementType(String elementName) 727 throws BuildException { 728 Class nt = (Class ) nestedTypes.get(elementName); 729 if (nt == null) { 730 throw new UnsupportedElementException("Class " 731 + bean.getName() + " doesn't support the nested \"" 732 + elementName + "\" element.", elementName); 733 } 734 return nt; 735 } 736 737 749 public Class getAttributeType(String attributeName) 750 throws BuildException { 751 Class at = (Class ) attributeTypes.get(attributeName); 752 if (at == null) { 753 throw new UnsupportedAttributeException("Class " 754 + bean.getName() + " doesn't support the \"" 755 + attributeName + "\" attribute.", attributeName); 756 } 757 return at; 758 } 759 760 770 public Method getAddTextMethod() 771 throws BuildException { 772 if (!supportsCharacters()) { 773 throw new BuildException("Class " + bean.getName() 774 + " doesn't support nested text data."); 775 } 776 return addText; 777 } 778 779 791 public Method getElementMethod(String elementName) 792 throws BuildException { 793 Object creator = nestedCreators.get(elementName); 794 if (creator == null) { 795 throw new UnsupportedElementException("Class " 796 + bean.getName() + " doesn't support the nested \"" 797 + elementName + "\" element.", elementName); 798 } 799 return ((NestedCreator) creator).method; 800 } 801 802 813 public Method getAttributeMethod(String attributeName) 814 throws BuildException { 815 Object setter = attributeSetters.get(attributeName); 816 if (setter == null) { 817 throw new UnsupportedAttributeException("Class " 818 + bean.getName() + " doesn't support the \"" 819 + attributeName + "\" attribute.", attributeName); 820 } 821 return ((AttributeSetter) setter).method; 822 } 823 824 829 public boolean supportsCharacters() { 830 return addText != null; 831 } 832 833 841 public Enumeration getAttributes() { 842 return attributeSetters.keys(); 843 } 844 845 853 public Map getAttributeMap() { 854 return (attributeTypes.size() < 1) 855 ? EMPTY_MAP : Collections.unmodifiableMap(attributeTypes); 856 } 857 858 866 public Enumeration getNestedElements() { 867 return nestedTypes.keys(); 868 } 869 870 878 public Map getNestedElementMap() { 879 return (nestedTypes.size() < 1) 880 ? EMPTY_MAP : Collections.unmodifiableMap(nestedTypes); 881 } 882 883 900 public List getExtensionPoints() { 901 return (addTypeMethods.size() < 1) ? Collections.EMPTY_LIST 902 : Collections.unmodifiableList(addTypeMethods); 903 } 904 905 936 private AttributeSetter createAttributeSetter(final Method m, 937 Class arg, 938 final String attrName) { 939 final Class reflectedArg = PRIMITIVE_TYPE_MAP.containsKey(arg) 942 ? (Class ) PRIMITIVE_TYPE_MAP.get(arg) : arg; 943 944 if (java.lang.String .class.equals(reflectedArg)) { 946 return new AttributeSetter(m) { 947 public void set(Project p, Object parent, String value) 948 throws InvocationTargetException , IllegalAccessException { 949 m.invoke(parent, (Object []) (new String [] {value})); 950 } 951 }; 952 } else if (java.lang.Character .class.equals(reflectedArg)) { 954 return new AttributeSetter(m) { 955 public void set(Project p, Object parent, String value) 956 throws InvocationTargetException , IllegalAccessException { 957 if (value.length() == 0) { 958 throw new BuildException("The value \"\" is not a " 959 + "legal value for attribute \"" + attrName + "\""); 960 } 961 m.invoke(parent, (Object []) 962 (new Character [] {new Character (value.charAt(0))})); 963 } 964 }; 965 } else if (java.lang.Boolean .class.equals(reflectedArg)) { 968 return new AttributeSetter(m) { 969 public void set(Project p, Object parent, String value) 970 throws InvocationTargetException , IllegalAccessException { 971 m.invoke(parent, (Object []) ( 972 new Boolean [] {Project.toBoolean(value) 973 ? Boolean.TRUE : Boolean.FALSE})); 974 } 975 }; 976 } else if (java.lang.Class .class.equals(reflectedArg)) { 978 return new AttributeSetter(m) { 979 public void set(Project p, Object parent, String value) 980 throws InvocationTargetException , IllegalAccessException , BuildException { 981 try { 982 m.invoke(parent, new Object [] {Class.forName(value)}); 983 } catch (ClassNotFoundException ce) { 984 throw new BuildException(ce); 985 } 986 } 987 }; 988 } else if (java.io.File .class.equals(reflectedArg)) { 990 return new AttributeSetter(m) { 991 public void set(Project p, Object parent, String value) 992 throws InvocationTargetException , IllegalAccessException { 993 m.invoke(parent, new Object [] {p.resolveFile(value)}); 994 } 995 }; 996 } else if (EnumeratedAttribute.class.isAssignableFrom(reflectedArg)) { 998 return new AttributeSetter(m) { 999 public void set(Project p, Object parent, String value) 1000 throws InvocationTargetException , IllegalAccessException , BuildException { 1001 try { 1002 EnumeratedAttribute ea = 1003 (EnumeratedAttribute) reflectedArg.newInstance(); 1004 ea.setValue(value); 1005 m.invoke(parent, new Object [] {ea}); 1006 } catch (InstantiationException ie) { 1007 throw new BuildException(ie); 1008 } 1009 } 1010 }; 1011 } else if (reflectedArg.getSuperclass() != null 1012 && reflectedArg.getSuperclass().getName().equals("java.lang.Enum")) { 1013 return new AttributeSetter(m) { 1014 public void set(Project p, Object parent, String value) 1015 throws InvocationTargetException , IllegalAccessException , BuildException { 1016 try { 1017 m.invoke(parent, new Object [] { 1018 reflectedArg.getMethod("valueOf", new Class [] {String .class}). 1019 invoke(null, new Object [] {value})}); 1020 } catch (InvocationTargetException x) { 1021 if (x.getTargetException() instanceof IllegalArgumentException ) { 1022 throw new BuildException( 1023 "'" + value + "' is not a permitted value for " 1024 + reflectedArg.getName()); 1025 } else { 1026 throw new BuildException(x.getTargetException()); 1027 } 1028 } catch (Exception x) { 1029 throw new BuildException(x); 1030 } 1031 } 1032 }; 1033 } else { 1038 boolean includeProject; 1039 Constructor c; 1040 try { 1041 c = reflectedArg.getConstructor(new Class [] {Project.class, String .class}); 1043 includeProject = true; 1044 } catch (NoSuchMethodException nme) { 1045 try { 1047 c = reflectedArg.getConstructor(new Class [] {String .class}); 1048 includeProject = false; 1049 } catch (NoSuchMethodException nme2) { 1050 return null; 1052 } 1053 } 1054 final boolean finalIncludeProject = includeProject; 1055 final Constructor finalConstructor = c; 1056 1057 return new AttributeSetter(m) { 1058 public void set(Project p, Object parent, String value) 1059 throws InvocationTargetException , IllegalAccessException , BuildException { 1060 try { 1061 Object [] args = (finalIncludeProject) 1062 ? new Object [] {p, value} : new Object [] {value}; 1063 1064 Object attribute = finalConstructor.newInstance(args); 1065 if (p != null) { 1066 p.setProjectReference(attribute); 1067 } 1068 m.invoke(parent, new Object [] {attribute}); 1069 } catch (InstantiationException ie) { 1070 throw new BuildException(ie); 1071 } 1072 } 1073 }; 1074 } 1075 } 1076 1077 1091 protected String getElementName(Project project, Object element) { 1092 return project.getElementName(element); 1093 } 1094 1095 1108 private String getPropertyName(String methodName, String prefix) { 1109 return methodName.substring(prefix.length()).toLowerCase(Locale.US); 1110 } 1111 1112 1117 public static final class Creator { 1118 private NestedCreator nestedCreator; 1119 private Object parent; 1120 private Project project; 1121 private Object nestedObject; 1122 private String polyType; 1123 1124 1138 private Creator( 1139 Project project, Object parent, NestedCreator nestedCreator) { 1140 this.project = project; 1141 this.parent = parent; 1142 this.nestedCreator = nestedCreator; 1143 } 1144 1145 1150 public void setPolyType(String polyType) { 1151 this.polyType = polyType; 1152 } 1153 1154 1160 public Object create() { 1161 if (polyType != null) { 1162 if (!nestedCreator.isPolyMorphic()) { 1163 throw new BuildException( 1164 "Not allowed to use the polymorphic form" 1165 + " for this element"); 1166 } 1167 ComponentHelper helper = 1168 ComponentHelper.getComponentHelper(project); 1169 nestedObject = helper.createComponent(polyType); 1170 if (nestedObject == null) { 1171 throw new BuildException( 1172 "Unable to create object of type " + polyType); 1173 } 1174 } 1175 try { 1176 nestedObject = nestedCreator.create( 1177 project, parent, nestedObject); 1178 if (project != null) { 1179 project.setProjectReference(nestedObject); 1180 } 1181 return nestedObject; 1182 } catch (IllegalAccessException ex) { 1183 throw new BuildException(ex); 1184 } catch (InstantiationException ex) { 1185 throw new BuildException(ex); 1186 } catch (IllegalArgumentException ex) { 1187 if (polyType != null) { 1188 throw new BuildException( 1189 "Invalid type used " + polyType); 1190 } 1191 throw ex; 1192 } catch (InvocationTargetException ex) { 1193 Throwable t = ex.getTargetException(); 1194 if (t instanceof BuildException) { 1195 throw (BuildException) t; 1196 } 1197 throw new BuildException(t); 1198 } 1199 } 1200 1201 1205 public Object getRealObject() { 1206 return nestedCreator.getRealObject(); 1207 } 1208 1209 1214 public void store() { 1215 try { 1216 nestedCreator.store(parent, nestedObject); 1217 } catch (IllegalAccessException ex) { 1218 throw new BuildException(ex); 1219 } catch (InstantiationException ex) { 1220 throw new BuildException(ex); 1221 } catch (IllegalArgumentException ex) { 1222 if (polyType != null) { 1223 throw new BuildException( 1224 "Invalid type used " + polyType); 1225 } 1226 throw ex; 1227 } catch (InvocationTargetException ex) { 1228 Throwable t = ex.getTargetException(); 1229 if (t instanceof BuildException) { 1230 throw (BuildException) t; 1231 } 1232 throw new BuildException(t); 1233 } 1234 } 1235 } 1236 1237 1241 private abstract static class NestedCreator { 1242 private Method method; 1244 NestedCreator(Method m) { 1245 this.method = m; 1246 } 1247 Method getMethod() { 1248 return method; 1249 } 1250 boolean isPolyMorphic() { 1251 return false; 1252 } 1253 Object getRealObject() { 1254 return null; 1255 } 1256 abstract Object create(Project project, Object parent, Object child) 1257 throws InvocationTargetException , 1258 IllegalAccessException , 1259 InstantiationException ; 1260 void store(Object parent, Object child) 1261 throws InvocationTargetException , 1262 IllegalAccessException , 1263 InstantiationException { 1264 } 1266 } 1267 1268 private class CreateNestedCreator extends NestedCreator { 1269 CreateNestedCreator(Method m) { 1270 super(m); 1271 } 1272 1273 Object create(Project project, Object parent, Object ignore) 1274 throws InvocationTargetException , IllegalAccessException { 1275 return getMethod().invoke(parent, new Object [] {}); 1276 } 1277 } 1278 1279 1280 private class AddNestedCreator extends NestedCreator { 1281 1282 static final int ADD = 1; 1283 static final int ADD_CONFIGURED = 2; 1284 1285 private Constructor constructor; 1286 private int behavior; 1288 AddNestedCreator(Method m, Constructor c, int behavior) { 1289 super(m); 1290 this.constructor = c; 1291 this.behavior = behavior; 1292 } 1293 1294 boolean isPolyMorphic() { 1295 return true; 1296 } 1297 1298 Object create(Project project, Object parent, Object child) 1299 throws InvocationTargetException , 1300 IllegalAccessException , InstantiationException { 1301 if (child == null) { 1302 child = constructor.newInstance( 1303 (constructor.getParameterTypes().length == 0) 1304 ? new Object [] {} : new Object [] {project}); 1305 } 1306 if (child instanceof PreSetDef.PreSetDefinition) { 1307 child = ((PreSetDef.PreSetDefinition) child) 1308 .createObject(project); 1309 } 1310 if (behavior == ADD) { 1311 istore(parent, child); 1312 } 1313 return child; 1314 } 1315 1316 void store(Object parent, Object child) 1317 throws InvocationTargetException , 1318 IllegalAccessException , InstantiationException { 1319 if (behavior == ADD_CONFIGURED) { 1320 istore(parent, child); 1321 } 1322 } 1323 1324 private void istore(Object parent, Object child) 1325 throws InvocationTargetException , 1326 IllegalAccessException , InstantiationException { 1327 getMethod().invoke(parent, new Object [] {child}); 1328 } 1329 } 1330 1331 1335 private abstract static class AttributeSetter { 1336 private Method method; AttributeSetter(Method m) { 1338 this.method = m; 1339 } 1340 abstract void set(Project p, Object parent, String value) 1341 throws InvocationTargetException , 1342 IllegalAccessException , 1343 BuildException; 1344 } 1345 1346 1349 public static void clearCache() { 1350 HELPERS.clear(); 1351 } 1352 1353 1356 private NestedCreator createAddTypeCreator( 1357 Project project, Object parent, String elementName) 1358 throws BuildException { 1359 if (addTypeMethods.size() == 0) { 1360 return null; 1361 } 1362 ComponentHelper helper = ComponentHelper.getComponentHelper(project); 1363 1364 Object addedObject = null; 1365 Method addMethod = null; 1366 Class clazz = helper.getComponentClass(elementName); 1367 if (clazz == null) { 1368 return null; 1369 } 1370 addMethod = findMatchingMethod(clazz, addTypeMethods); 1371 if (addMethod == null) { 1372 return null; 1373 } 1374 addedObject = helper.createComponent(elementName); 1375 if (addedObject == null) { 1376 return null; 1377 } 1378 Object rObject = addedObject; 1379 if (addedObject instanceof PreSetDef.PreSetDefinition) { 1380 rObject = ((PreSetDef.PreSetDefinition) addedObject).createObject( 1381 project); 1382 } 1383 final Object nestedObject = addedObject; 1384 final Object realObject = rObject; 1385 1386 return new NestedCreator(addMethod) { 1387 Object create(Project project, Object parent, Object ignore) 1388 throws InvocationTargetException , IllegalAccessException { 1389 if (!getMethod().getName().endsWith("Configured")) { 1390 getMethod().invoke(parent, new Object [] {realObject}); 1391 } 1392 return nestedObject; 1393 } 1394 1395 Object getRealObject() { 1396 return realObject; 1397 } 1398 1399 void store(Object parent, Object child) 1400 throws InvocationTargetException , IllegalAccessException , 1401 InstantiationException { 1402 if (getMethod().getName().endsWith("Configured")) { 1403 getMethod().invoke(parent, new Object [] {realObject}); 1404 } 1405 } 1406 }; 1407 } 1408 1409 1418 private void insertAddTypeMethod(Method method) { 1419 Class argClass = method.getParameterTypes()[0]; 1420 for (int c = 0; c < addTypeMethods.size(); ++c) { 1421 Method current = (Method ) addTypeMethods.get(c); 1422 if (current.getParameterTypes()[0].equals(argClass)) { 1423 if (method.getName().equals("addConfigured")) { 1424 addTypeMethods.set(c, method); 1426 } 1427 return; } 1429 if (current.getParameterTypes()[0].isAssignableFrom( 1430 argClass)) { 1431 addTypeMethods.add(c, method); 1432 return; } 1434 } 1435 addTypeMethods.add(method); 1436 } 1437 1438 1445 private Method findMatchingMethod(Class paramClass, List methods) { 1446 Class matchedClass = null; 1447 Method matchedMethod = null; 1448 1449 for (int i = 0; i < methods.size(); ++i) { 1450 Method method = (Method ) methods.get(i); 1451 Class methodClass = method.getParameterTypes()[0]; 1452 if (methodClass.isAssignableFrom(paramClass)) { 1453 if (matchedClass == null) { 1454 matchedClass = methodClass; 1455 matchedMethod = method; 1456 } else { 1457 if (!methodClass.isAssignableFrom(matchedClass)) { 1458 throw new BuildException("ambiguous: types " 1459 + matchedClass.getName() + " and " 1460 + methodClass.getName() + " match " 1461 + paramClass.getName()); 1462 } 1463 } 1464 } 1465 } 1466 return matchedMethod; 1467 } 1468 1469 private String condenseText(final String text) { 1470 if (text.length() <= MAX_REPORT_NESTED_TEXT) { 1471 return text; 1472 } 1473 int ends = (MAX_REPORT_NESTED_TEXT - ELLIPSIS.length()) / 2; 1474 return new StringBuffer (text).replace(ends, text.length() - ends, 1475 ELLIPSIS).toString(); 1476 } 1477} 1478 | Popular Tags |