View Javadoc
1 package xdoclet.sdk.ant; 2 3 import org.apache.tools.ant.IntrospectionHelper; 4 import org.apache.tools.ant.types.EnumeratedAttribute; 5 6 import xdoclet.XDocletException; 7 8 import xjavadoc.XClass; 9 import xjavadoc.XCollections; 10 import xjavadoc.XMethod; 11 import xjavadoc.XParameter; 12 import xjavadoc.XTag; 13 14 import java.util.ArrayList; 15 import java.util.Collection; 16 import java.util.Collections; 17 import java.util.Comparator; 18 import java.util.Enumeration; 19 import java.util.HashMap; 20 import java.util.Iterator; 21 import java.util.List; 22 import java.util.Map; 23 import java.util.Properties; 24 25 /*** 26 * 27 * @author <a href="mailto:aslak.hellesoy at bekk.no">Aslak Hellesøy</a> 28 * @author Erik Hatcher 29 * @version $Revision: 1.9 $ 30 */ 31 public class AntUtil { 32 /*** 33 * Default category for tasks without a category attribute. 34 */ 35 public final static String DEFAULT_CATEGORY = "other"; 36 private static Map attributeDisplayMap = new HashMap(); 37 private static Map elementDisplayMap = new HashMap(); 38 private static String[] fluffPrefixes = { "set a", "set the", "sets a", "sets the" }; 39 40 static { 41 attributeDisplayMap.put("java.lang.String", "String"); 42 attributeDisplayMap.put("boolean", "boolean"); 43 attributeDisplayMap.put("org.apache.tools.ant.types.Path", "Path"); 44 attributeDisplayMap.put("org.apache.tools.ant.types.Reference", "Reference"); 45 attributeDisplayMap.put("java.io.File", "File"); 46 attributeDisplayMap.put("java.util.Date", "Date"); 47 attributeDisplayMap.put("java.net.URL", "URL"); 48 attributeDisplayMap.put("java.lang.Long", "long"); 49 attributeDisplayMap.put("java.lang.Integer", "int"); 50 attributeDisplayMap.put("java.lang.Float", "float"); 51 attributeDisplayMap.put("java.lang.Double", "double"); 52 53 elementDisplayMap.put("org.apache.tools.ant.types.Path", "Path"); 54 elementDisplayMap.put("org.apache.tools.ant.types.FileSet", "Fileset"); 55 elementDisplayMap.put("org.apache.tools.ant.taskdefs.Property", "see <property>"); 56 elementDisplayMap.put("org.apache.tools.ant.types.Mapper", "Mapper"); 57 elementDisplayMap.put("org.apache.tools.ant.types.PatternSet", "Patternset"); 58 elementDisplayMap.put("org.apache.tools.ant.types.FileList", "Filelist"); 59 elementDisplayMap.put("org.apache.tools.ant.types.FilterChain", "FilterChain"); 60 elementDisplayMap.put("org.apache.tools.ant.types.FilterSet", "Filterset"); 61 elementDisplayMap.put("org.apache.tools.ant.types.ZipFileSet", "ZipFileset"); 62 elementDisplayMap.put("org.apache.tools.ant.types.DirSet", "Dirset"); 63 elementDisplayMap.put("org.apache.tools.ant.types.XMLCatalog", "XMLCatalog"); 64 } 65 66 /*** 67 * Provides the Ant task name. Order of rules: 68 * <ol> 69 * <li> Value of @ant.task name="..."</li> 70 * <li> Lowercased classname with "Task" suffix removed</li> 71 * </ol> 72 * 73 * @param clazz the class to for which we're getting the task name. 74 * @return the task name 75 */ 76 public final static String getTaskName(XClass clazz) { 77 String tagValue = clazz.getDoc().getTagAttributeValue("ant.task", "name"); 78 79 if (tagValue == null) { 80 // use classname, but strip "Task" suffix if there 81 tagValue = clazz.getName(); 82 83 if (tagValue.endsWith("Task")) { 84 tagValue = tagValue.substring(0, tagValue.indexOf("Task")); 85 } 86 87 tagValue = tagValue.toLowerCase(); 88 } 89 90 return tagValue; 91 } 92 93 /*** 94 * Provides the Ant category name as the Value of the category attribute. 95 * 96 * @param clazz the class to for which we're getting the category name. 97 * @return the task category name 98 */ 99 public final static String getCategoryName(XClass clazz) { 100 String tagValue = clazz.getDoc().getTagAttributeValue("ant.task", "category"); 101 102 if (tagValue != null) { 103 tagValue = tagValue.toLowerCase(); 104 } else { 105 tagValue = DEFAULT_CATEGORY; 106 } 107 108 return tagValue; 109 } 110 111 /*** 112 * Provides the element name for the current method 113 * 114 * @return the element name 115 * @exception XDocletException 116 */ 117 public String elementName(XMethod method) 118 throws XDocletException { 119 String methodName = method.getName(); 120 String elementName = "<not a valid element>"; 121 122 if (methodName.startsWith("addConfigured")) { 123 elementName = methodName.substring(13, methodName.length()); 124 } else if (methodName.startsWith("add")) { 125 elementName = methodName.substring(3, methodName.length()); 126 } else if (methodName.startsWith("create")) { 127 elementName = methodName.substring(6, methodName.length()); 128 } 129 130 return elementName.toLowerCase(); 131 } 132 133 public String displayAttributeType(XMethod method) 134 throws XDocletException { 135 Collection parameters = method.getParameters(); 136 XParameter param = XCollections.parameterIterator(parameters).next(); 137 138 String methodType = param.getType().getQualifiedName(); 139 String display = (String) attributeDisplayMap.get(methodType); 140 141 if (display == null) { 142 Class clazz = getAttributeClass(methodType); 143 144 if (clazz == null) { 145 return methodType; 146 } 147 148 Object instance = null; 149 150 try { 151 instance = clazz.newInstance(); 152 } catch (InstantiationException e) { 153 } catch (IllegalAccessException e) { 154 } 155 156 if ((instance != null) && instance instanceof EnumeratedAttribute) { 157 EnumeratedAttribute enum = (EnumeratedAttribute) instance; 158 String[] values = enum.getValues(); 159 160 display = ""; 161 162 for (int i = 0; i < values.length; i++) { 163 display += (""" + values[i] + """); 164 165 if (i != (values.length - 1)) { 166 display += ", "; 167 } 168 } 169 170 return display; 171 } 172 173 display = ""; 174 } 175 176 return display; 177 } 178 179 public String displayElementType() 180 throws XDocletException { 181 String elementType = elementType(); 182 String display = (String) elementDisplayMap.get(elementType); 183 184 if (display == null) { 185 display = ""; 186 } 187 188 return display; 189 } 190 191 /*** 192 * Provides the element type for the current method 193 * 194 * @return the element type (qualified class name). 195 * @exception XDocletException 196 */ 197 public String elementType() 198 throws XDocletException { 199 XClass clazz = elementClassDoc(); 200 201 if (clazz == null) { 202 throw new XDocletException("Method is not an Ant element!"); 203 } 204 205 return clazz.getQualifiedName(); 206 } 207 208 public String shortMethodDescription(XMethod method) 209 throws XDocletException { 210 String desc = method.getDoc().getFirstSentence(); 211 212 if ((desc == null) || (desc.length() == 0)) { 213 desc = "no description"; 214 } 215 216 desc = desc.trim(); 217 218 String descLower = desc.toLowerCase(); 219 220 for (int i = 0; i < fluffPrefixes.length; i++) { 221 String prefix = fluffPrefixes[i].toLowerCase() + " "; 222 223 if (descLower.startsWith(prefix)) { 224 desc = desc.substring(prefix.length()); 225 226 break; 227 } 228 } 229 230 desc = desc.substring(0, 1).toUpperCase() + desc.substring(1); 231 232 if (!desc.endsWith(".")) { 233 desc += "."; 234 } 235 236 return desc; 237 } 238 239 private Class getAttributeClass(String type) 240 throws XDocletException { 241 // System.out.println("type = " + type); 242 Class clazz = null; 243 244 try { 245 clazz = Class.forName(type); 246 } catch (ClassNotFoundException e) { 247 int lastDotPosition = type.lastIndexOf('.'); 248 249 if (lastDotPosition < 0) { 250 // probably a primitive 251 return null; 252 } 253 254 type = type.substring(0, lastDotPosition) + "$" + type.substring(lastDotPosition + 1); 255 256 try { 257 clazz = Class.forName(type); 258 } catch (ClassNotFoundException e1) { 259 throw new XDocletException(e1.getMessage()); 260 } 261 } 262 263 return clazz; 264 } 265 266 /*** 267 * @param cur_class 268 * @return 269 * @exception XDocletException 270 * @todo refactor to cache methods per class, and save some time 271 */ 272 private XMethod[] getAttributeMethods(XClass cur_class) 273 throws XDocletException { 274 // Use Ant's own introspection mechanism to gather the 275 // attributes this class supports 276 IntrospectionHelper is = null; 277 278 try { 279 is = IntrospectionHelper.getHelper(Class.forName(cur_class.getQualifiedName())); 280 } catch (ClassNotFoundException e) { 281 throw new XDocletException(e); 282 } 283 284 // Regroup the attributes, since IntrospectionHelper 285 // doesn't give us the whole data structure directly 286 Enumeration enum = is.getAttributes(); 287 Properties attributeTypeMap = new Properties(); 288 289 while (enum.hasMoreElements()) { 290 String name = (String) enum.nextElement(); 291 Class type = is.getAttributeType(name); 292 293 attributeTypeMap.setProperty(name, type.getName()); 294 295 // System.out.println(name + " = " + type.getName()); 296 } 297 298 // We need to return XMethod[] from this method 299 // so get all methods from the current class 300 XMethod[] allMethods = getMethods(cur_class); 301 302 // System.out.println("allMethods = " + allMethods.length); 303 // And now filter the methods based 304 // on what IntrospectionHelper says 305 List attributeMethods = new ArrayList(); 306 307 for (int i = 0; i < allMethods.length; i++) { 308 XMethod method = allMethods[i]; 309 String methodName = method.getName(); 310 311 // System.out.println("methodName = " + methodName); 312 if (!methodName.startsWith("set")) { 313 continue; 314 } 315 316 String attributeName = methodName.substring(3).toLowerCase(); 317 318 // System.out.println("attributeName = " + attributeName); 319 if ((method.getParameters().size() != 1) || (!method.isPublic())) { 320 continue; 321 } 322 323 String attributeType = XCollections.parameterIterator(method.getParameters()).next().getType() 324 .getQualifiedName(); 325 326 // System.out.println("attributeType = " + attributeType); 327 String mapAttribute = attributeTypeMap.getProperty(attributeName); 328 329 if (mapAttribute == null) { 330 continue; 331 } 332 333 // inner classes are noted with $ in our map, but not 334 // n the parameter type name. 335 if (!attributeType.equals(mapAttribute.replace('$', '.'))) { 336 continue; 337 } 338 339 // System.out.println(methodName + " : " + attributeName + " : " + attributeType); 340 attributeMethods.add(method); 341 } 342 343 return (XMethod[]) attributeMethods.toArray(new XMethod[0]); 344 } 345 346 /*** 347 * @param cur_class 348 * @return methods corresponding to elements 349 * @throws XDocletException if something goes wrong. 350 * @todo add checks for number parameters and appropriate return value 351 * check for proper exception too? method prefixes: add, create, 352 * addConfigured (but not addText) 353 * @todo add DynamicConfigurator (this should be noted in the template, 354 * not dealt with here) 355 */ 356 private XMethod[] getElementMethods(XClass cur_class) 357 throws XDocletException { 358 // Use Ant's own introspection mechanism to gather the 359 // elements this class supports 360 IntrospectionHelper is = null; 361 362 try { 363 is = IntrospectionHelper.getHelper(Class.forName(cur_class.getQualifiedName())); 364 } catch (ClassNotFoundException e) { 365 throw new XDocletException(e.getMessage()); 366 } 367 368 // Regroup the elements, since IntrospectionHelper 369 // doesn't give us the whole data structure directly 370 Enumeration enum = is.getNestedElements(); 371 Properties elementTypeMap = new Properties(); 372 373 while (enum.hasMoreElements()) { 374 String name = (String) enum.nextElement(); 375 Class type = is.getElementType(name); 376 377 elementTypeMap.setProperty(name, type.getName()); 378 379 // System.out.println(name + " = " + type.getName()); 380 } 381 382 // We need to return MethodDoc[] from this method 383 // so get all methods from the current class 384 XMethod[] allMethods = getMethods(cur_class); 385 386 // And now filter the MethodDoc's based 387 // on what IntrospectionHelper says 388 List elementMethods = new ArrayList(); 389 390 for (int i = 0; i < allMethods.length; i++) { 391 XMethod method = allMethods[i]; 392 String methodName = method.getName(); 393 394 // Object create(), void add(Object), void addConfigured(Object) 395 String elementName = null; 396 397 // true if addXXX or addConfiguredXXX 398 boolean adder = false; 399 400 if (methodName.startsWith("create")) { 401 elementName = methodName.substring(6).toLowerCase(); 402 } 403 404 if (methodName.startsWith("add")) { 405 int length = 3; 406 407 if (methodName.startsWith("addConfigured")) { 408 length = 13; 409 } 410 411 elementName = methodName.substring(length).toLowerCase(); 412 adder = true; 413 } 414 415 if (elementName == null) { 416 continue; 417 } 418 419 // System.out.println("elementName = " + elementName); 420 String elementType = null; 421 422 if (adder) { 423 if (method.getParameters().size() != 1) { 424 continue; 425 } 426 427 elementType = XCollections.parameterIterator(method.getParameters()).next().getType().getQualifiedName(); 428 } else { 429 elementType = method.getReturnType().getType().getQualifiedName(); 430 } 431 432 if (!method.isPublic()) { 433 continue; 434 } 435 436 String mapElementType = elementTypeMap.getProperty(elementName); 437 438 // System.out.println("elementType = " + elementType + " mapElementType = " + mapElementType); 439 if (mapElementType == null) { 440 continue; 441 } 442 443 // inner classes are noted with $ in our map, but not 444 // the parameter type name. 445 if (!elementType.equals(mapElementType.replace('$', '.'))) { 446 continue; 447 } 448 449 elementMethods.add(method); 450 } 451 452 return (XMethod[]) elementMethods.toArray(new XMethod[elementMethods.size()]); 453 } 454 455 /*** 456 * This is a slightly refactored (thank you IntelliJ) version of some 457 * cut-and-paste from XDoclet code. It sorts all 458 * methods together rather than in batches of superclasses like XDoclet stuff does. 459 * 460 * @param cur_class 461 * @return 462 */ 463 private XMethod[] getMethods(XClass cur_class) { 464 Map already = new HashMap(); 465 466 List methods = new ArrayList(); 467 468 while (cur_class != null) { 469 // hardcoded to stop when it hits Task, nothing there 470 // or above that needs to be processed 471 if (cur_class.getQualifiedName().equals("org.apache.tools.ant.Task") 472 || cur_class.getQualifiedName().equals("org.apache.tools.ant.taskdefs.MatchingTask")) { 473 break; 474 } 475 476 Collection curMethods = cur_class.getMethods(); 477 478 Iterator iter = curMethods.iterator(); 479 480 while (iter.hasNext()) { 481 XMethod method = (XMethod) iter.next(); 482 483 if (isDeprecated(method)) { 484 continue; 485 } 486 487 if (shouldIgnore(method)) { 488 continue; 489 } 490 491 String methodName = method.getName(); 492 493 // System.out.println("method = " + method + ":" + methodName); 494 if (method.getContainingClass() == cur_class) { 495 if (already.containsKey(methodName) == false) { 496 already.put(methodName, method); 497 methods.add(method); 498 } 499 } 500 } 501 502 cur_class = cur_class.getSuperclass(); 503 } 504 505 return sortMethods(methods); 506 } 507 508 private boolean isDeprecated(XMethod method) { 509 Collection tags = method.getDoc().getTags(); 510 Iterator iter = tags.iterator(); 511 512 while (iter.hasNext()) { 513 XTag tag = (XTag) iter.next(); 514 515 if (tag.getName().equals("@deprecated")) { 516 return true; 517 } 518 } 519 520 return false; 521 } 522 523 /*** 524 * Provides the element type for the current method. If the return type is 525 * null, the first parameter is used. 526 * 527 * @return ?? 528 */ 529 private XClass elementClassDoc() { 530 XClass clazz = null; 531 532 /* 533 String methodName = getCurrentMethod().getName(); 534 535 if (methodName.startsWith("addConfigured") || 536 methodName.startsWith("add") || 537 methodName.startsWith("create")) { 538 clazz = getCurrentMethod().getReturnType(); 539 if ("void".equals(clazz.getName())) { 540 Collection params = getCurrentMethod().getParameters(); 541 542 if (params.size() == 1) { 543 clazz = XCollections.parameterIterator(params).next().getType(); 544 } 545 } 546 } 547 // System.out.println(methodName + ": clazz = " + clazz.getQualifiedName()); 548 */ 549 return clazz; 550 } 551 552 /*** 553 * For now, lump attributes and elements together since we won't have those 554 * tags on the same method. 555 * 556 * @param method 557 * @return true if the method should be ignored. 558 */ 559 private boolean shouldIgnore(XMethod method) { 560 String value = method.getDoc().getTagAttributeValue("ant.attribute", "ignore"); 561 562 if ("true".equalsIgnoreCase(value)) { 563 return true; 564 } 565 566 value = method.getDoc().getTagAttributeValue("ant.element", "ignore"); 567 568 if ("true".equalsIgnoreCase(value)) { 569 return true; 570 } 571 572 return false; 573 } 574 575 private XMethod[] sortMethods(List methods) { 576 //sort methods 577 Collections.sort(methods, 578 new Comparator() { 579 public int compare(Object o1, Object o2) { 580 XMethod m1 = (XMethod) o1; 581 XMethod m2 = (XMethod) o2; 582 583 return m1.getName().compareTo(m2.getName()); 584 } 585 586 public boolean equals(Object obj) { 587 //dumb 588 return obj == this; 589 } 590 }); 591 592 return (XMethod[]) methods.toArray(new XMethod[0]); 593 } 594 }

This page was automatically generated by Maven