1 17 package org.apache.tools.ant.taskdefs.optional.sitraka; 18 19 import java.io.File ; 20 import java.io.FileInputStream ; 21 import java.util.Enumeration ; 22 import java.util.Hashtable ; 23 import java.util.NoSuchElementException ; 24 import java.util.Vector ; 25 import javax.xml.parsers.DocumentBuilder ; 26 import javax.xml.parsers.DocumentBuilderFactory ; 27 import org.apache.tools.ant.Project; 28 import org.apache.tools.ant.Task; 29 import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.ClassFile; 30 import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.ClassPathLoader; 31 import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.MethodInfo; 32 import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.Utils; 33 import org.w3c.dom.Document ; 34 import org.w3c.dom.Element ; 35 import org.w3c.dom.Node ; 36 import org.w3c.dom.NodeList ; 37 import org.xml.sax.InputSource ; 38 39 46 public class XMLReport { 47 48 private Task task; 49 50 51 private File file; 52 53 54 private File jprobeHome; 55 56 57 private Document report; 58 59 63 private Hashtable classFiles; 64 65 66 private Hashtable pkgMap; 67 68 69 private Hashtable classMap; 70 71 72 private ReportFilters filters; 73 74 75 public XMLReport(File file) { 76 this(null, file); 77 } 78 79 80 public XMLReport(Task task, File file) { 81 this.file = file; 82 this.task = task; 83 } 84 85 86 public void setJProbehome(File home) { 87 jprobeHome = home; 88 } 89 90 91 public void setReportFilters(ReportFilters filters) { 92 this.filters = filters; 93 } 94 95 96 97 protected void createNodeMaps() { 98 pkgMap = new Hashtable (); 99 classMap = new Hashtable (); 100 NodeList packages = report.getElementsByTagName("package"); 103 final int pkglen = packages.getLength(); 104 log("Indexing " + pkglen + " packages"); 105 for (int i = pkglen - 1; i > -1; i--) { 106 Element pkg = (Element ) packages.item(i); 107 String pkgname = pkg.getAttribute("name"); 108 109 int nbclasses = 0; 110 NodeList classes = pkg.getElementsByTagName("class"); 113 final int classlen = classes.getLength(); 114 log("Indexing " + classlen + " classes in package " + pkgname); 115 for (int j = classlen - 1; j > -1; j--) { 116 Element clazz = (Element ) classes.item(j); 117 String classname = clazz.getAttribute("name"); 118 if (pkgname != null && pkgname.length() != 0) { 119 classname = pkgname + "." + classname; 120 } 121 122 int nbmethods = 0; 123 NodeList methods = clazz.getElementsByTagName("method"); 124 final int methodlen = methods.getLength(); 125 for (int k = methodlen - 1; k > -1; k--) { 126 Element meth = (Element ) methods.item(k); 127 StringBuffer methodname = new StringBuffer (meth.getAttribute("name")); 128 methodname.delete(methodname.toString().indexOf("("), 129 methodname.toString().length()); 130 String signature = classname + "." + methodname + "()"; 131 if (filters.accept(signature)) { 132 log("kept method:" + signature); 133 nbmethods++; 134 } else { 135 clazz.removeChild(meth); 136 } 137 } 138 if (nbmethods != 0 && classFiles.containsKey(classname)) { 140 log("Adding class '" + classname + "'"); 141 classMap.put(classname, clazz); 142 nbclasses++; 143 } else { 144 pkg.removeChild(clazz); 145 } 146 } 147 if (nbclasses != 0) { 148 log("Adding package '" + pkgname + "'"); 149 pkgMap.put(pkgname, pkg); 150 } else { 151 pkg.getParentNode().removeChild(pkg); 152 } 153 } 154 log("Indexed " + classMap.size() + " classes in " + pkgMap.size() + " packages"); 155 } 156 157 158 public Document createDocument(String [] classPath) throws Exception { 159 160 classFiles = new Hashtable (); 162 ClassPathLoader cpl = new ClassPathLoader(classPath); 163 Enumeration e = cpl.loaders(); 164 while (e.hasMoreElements()) { 165 ClassPathLoader.FileLoader fl = (ClassPathLoader.FileLoader) e.nextElement(); 166 ClassFile[] classes = fl.getClasses(); 167 log("Processing " + classes.length + " classes in " + fl.getFile()); 168 for (int i = 0; i < classes.length; i++) { 170 classFiles.put(classes[i].getFullName(), classes[i]); 171 } 172 } 173 174 DocumentBuilder dbuilder = newBuilder(); 176 InputSource is = new InputSource (new FileInputStream (file)); 177 if (jprobeHome != null) { 178 File dtdDir = new File (jprobeHome, "dtd"); 179 is.setSystemId("file:///" + dtdDir.getAbsolutePath() + "/"); 180 } 181 report = dbuilder.parse(is); 182 report.normalize(); 183 184 createNodeMaps(); 186 187 Enumeration classes = classFiles.elements(); 189 while (classes.hasMoreElements()) { 190 ClassFile cf = (ClassFile) classes.nextElement(); 191 serializeClass(cf); 192 } 193 update(); 195 return report; 196 } 197 198 203 protected String getMethodSignature(MethodInfo method) { 204 StringBuffer buf = new StringBuffer (method.getName()); 205 buf.append("("); 206 String [] params = method.getParametersType(); 207 for (int i = 0; i < params.length; i++) { 208 String type = params[i]; 209 int pos = type.lastIndexOf('.'); 210 if (pos != -1) { 211 String pkg = type.substring(0, pos); 212 if ("java.lang".equals(pkg)) { 213 params[i] = type.substring(pos + 1); 214 } 215 } 216 buf.append(params[i]); 217 if (i != params.length - 1) { 218 buf.append(", "); 219 } 220 } 221 buf.append(")"); 222 return buf.toString(); 223 } 224 225 228 protected String getMethodSignature(ClassFile clazz, MethodInfo method) { 229 StringBuffer buf = new StringBuffer (clazz.getFullName()); 230 buf.append("."); 231 buf.append(method.getName()); 232 buf.append("()"); 233 return buf.toString(); 234 } 235 236 240 protected void removeAbstractMethods(ClassFile classFile, Element classNode) { 241 MethodInfo[] methods = classFile.getMethods(); 242 Hashtable methodNodeList = getMethods(classNode); 243 final int size = methods.length; 245 for (int i = 0; i < size; i++) { 246 MethodInfo method = methods[i]; 247 String methodSig = getMethodSignature(method); 248 Element methodNode = (Element ) methodNodeList.get(methodSig); 249 if (methodNode != null 250 && Utils.isAbstract(method.getAccessFlags())) { 251 log("\tRemoving abstract method " + methodSig); 252 classNode.removeChild(methodNode); 253 } 254 } 255 } 256 257 258 protected Element createMethodElement(MethodInfo method) { 259 String methodsig = getMethodSignature(method); 260 Element methodElem = report.createElement("method"); 261 methodElem.setAttribute("name", methodsig); 262 Element methodData = report.createElement("cov.data"); 264 methodElem.appendChild(methodData); 265 methodData.setAttribute("calls", "0"); 266 methodData.setAttribute("hit_lines", "0"); 267 methodData.setAttribute("total_lines", String.valueOf(method.getNumberOfLines())); 268 return methodElem; 269 } 270 271 272 protected Element createPackageElement(String pkgname) { 273 Element pkgElem = report.createElement("package"); 274 pkgElem.setAttribute("name", pkgname); 275 Element pkgData = report.createElement("cov.data"); 278 pkgElem.appendChild(pkgData); 279 pkgData.setAttribute("calls", "0"); 280 pkgData.setAttribute("hit_methods", "0"); 281 pkgData.setAttribute("total_methods", "0"); 282 pkgData.setAttribute("hit_lines", "0"); 283 pkgData.setAttribute("total_lines", "0"); 284 return pkgElem; 285 } 286 287 288 protected Element createClassElement(ClassFile classFile) { 289 Element classElem = report.createElement("class"); 291 classElem.setAttribute("name", classFile.getName()); 292 if (null != classFile.getSourceFile()) { 294 classElem.setAttribute("source", classFile.getSourceFile()); 295 } 296 Element classData = report.createElement("cov.data"); 298 classElem.appendChild(classData); 299 classData.setAttribute("calls", "0"); 301 classData.setAttribute("hit_methods", "0"); 302 classData.setAttribute("total_methods", "0"); 303 classData.setAttribute("hit_lines", "0"); 304 classData.setAttribute("total_lines", "0"); 305 return classElem; 306 } 307 308 309 protected void serializeClass(ClassFile classFile) { 310 String fullclassname = classFile.getFullName(); 312 log("Looking for '" + fullclassname + "'"); 313 Element clazz = (Element ) classMap.get(fullclassname); 314 315 if (clazz != null) { 318 log("Ignoring " + fullclassname); 319 removeAbstractMethods(classFile, clazz); 320 return; 321 } 322 323 if (Utils.isInterface(classFile.getAccess())) { 325 return; 326 } 327 328 Vector methods = getFilteredMethods(classFile); 329 if (methods.size() == 0) { 331 return; 332 } 333 334 String pkgname = classFile.getPackage(); 335 Element pkgElem = (Element ) pkgMap.get(pkgname); 337 if (pkgElem == null) { 338 pkgElem = createPackageElement(pkgname); 339 report.getDocumentElement().appendChild(pkgElem); 340 pkgMap.put(pkgname, pkgElem); } 342 344 Element classElem = createClassElement(classFile); 346 pkgElem.appendChild(classElem); 347 348 int total_lines = 0; 349 int total_methods = 0; 350 final int count = methods.size(); 351 for (int i = 0; i < count; i++) { 352 MethodInfo method = (MethodInfo) methods.elementAt(i); 354 if (Utils.isAbstract(method.getAccessFlags())) { 355 continue; } 357 Element methodElem = createMethodElement(method); 358 classElem.appendChild(methodElem); 359 total_lines += method.getNumberOfLines(); 360 total_methods++; 361 } 362 Element classData = getCovDataChild(classElem); 364 classData.setAttribute("total_methods", String.valueOf(total_methods)); 365 classData.setAttribute("total_lines", String.valueOf(total_lines)); 366 367 classMap.put(fullclassname, classElem); 369 } 370 371 protected Vector getFilteredMethods(ClassFile classFile) { 372 MethodInfo[] methodlist = classFile.getMethods(); 373 Vector methods = new Vector (methodlist.length); 374 for (int i = 0; i < methodlist.length; i++) { 375 MethodInfo method = methodlist[i]; 376 String signature = getMethodSignature(classFile, method); 377 if (filters.accept(signature)) { 378 methods.addElement(method); 379 log("keeping " + signature); 380 } else { 381 } 383 } 384 return methods; 385 } 386 387 388 392 protected void update() { 393 int calls = 0; 394 int hit_methods = 0; 395 int total_methods = 0; 396 int hit_lines = 0; 397 int total_lines = 0; 398 399 Enumeration e = pkgMap.elements(); 401 while (e.hasMoreElements()) { 402 Element pkgElem = (Element ) e.nextElement(); 403 String pkgname = pkgElem.getAttribute("name"); 404 Element [] classes = getClasses(pkgElem); 405 int pkg_calls = 0; 406 int pkg_hit_methods = 0; 407 int pkg_total_methods = 0; 408 int pkg_hit_lines = 0; 409 int pkg_total_lines = 0; 410 for (int j = 0; j < classes.length; j++) { 413 Element clazz = classes[j]; 414 String classname = clazz.getAttribute("name"); 415 if (pkgname != null && pkgname.length() != 0) { 416 classname = pkgname + "." + classname; 417 } 418 Element covdata = getCovDataChild(clazz); 420 try { 421 pkg_calls += Integer.parseInt(covdata.getAttribute("calls")); 422 pkg_hit_methods += Integer.parseInt(covdata.getAttribute("hit_methods")); 423 pkg_total_methods += Integer.parseInt(covdata.getAttribute("total_methods")); 424 pkg_hit_lines += Integer.parseInt(covdata.getAttribute("hit_lines")); 425 pkg_total_lines += Integer.parseInt(covdata.getAttribute("total_lines")); 426 } catch (NumberFormatException ex) { 427 log("Error parsing '" + classname + "' (" + j + "/" 428 + classes.length + ") in package '" + pkgname + "'"); 429 throw ex; 430 } 431 } 432 Element covdata = getCovDataChild(pkgElem); 433 covdata.setAttribute("calls", String.valueOf(pkg_calls)); 434 covdata.setAttribute("hit_methods", String.valueOf(pkg_hit_methods)); 435 covdata.setAttribute("total_methods", String.valueOf(pkg_total_methods)); 436 covdata.setAttribute("hit_lines", String.valueOf(pkg_hit_lines)); 437 covdata.setAttribute("total_lines", String.valueOf(pkg_total_lines)); 438 calls += pkg_calls; 439 hit_methods += pkg_hit_methods; 440 total_methods += pkg_total_methods; 441 hit_lines += pkg_hit_lines; 442 total_lines += pkg_total_lines; 443 } 444 Element covdata = getCovDataChild(report.getDocumentElement()); 445 covdata.setAttribute("calls", String.valueOf(calls)); 446 covdata.setAttribute("hit_methods", String.valueOf(hit_methods)); 447 covdata.setAttribute("total_methods", String.valueOf(total_methods)); 448 covdata.setAttribute("hit_lines", String.valueOf(hit_lines)); 449 covdata.setAttribute("total_lines", String.valueOf(total_lines)); 450 } 451 452 protected Element getCovDataChild(Element parent) { 453 NodeList children = parent.getChildNodes(); 454 int len = children.getLength(); 455 for (int i = 0; i < len; i++) { 456 Node child = children.item(i); 457 if (child.getNodeType() == Node.ELEMENT_NODE) { 458 Element elem = (Element ) child; 459 if ("cov.data".equals(elem.getNodeName())) { 460 return elem; 461 } 462 } 463 } 464 throw new NoSuchElementException ("Could not find 'cov.data' " 465 + "element in parent '" + parent.getNodeName() + "'"); 466 } 467 468 protected Hashtable getMethods(Element clazz) { 469 Hashtable map = new Hashtable (); 470 NodeList children = clazz.getChildNodes(); 471 int len = children.getLength(); 472 for (int i = 0; i < len; i++) { 473 Node child = children.item(i); 474 if (child.getNodeType() == Node.ELEMENT_NODE) { 475 Element elem = (Element ) child; 476 if ("method".equals(elem.getNodeName())) { 477 String name = elem.getAttribute("name"); 478 map.put(name, elem); 479 } 480 } 481 } 482 return map; 483 } 484 485 protected Element [] getClasses(Element pkg) { 486 Vector v = new Vector (); 487 NodeList children = pkg.getChildNodes(); 488 int len = children.getLength(); 489 for (int i = 0; i < len; i++) { 490 Node child = children.item(i); 491 if (child.getNodeType() == Node.ELEMENT_NODE) { 492 Element elem = (Element ) child; 493 if ("class".equals(elem.getNodeName())) { 494 v.addElement(elem); 495 } 496 } 497 } 498 Element [] elems = new Element [v.size()]; 499 v.copyInto(elems); 500 return elems; 501 502 } 503 504 protected Element [] getPackages(Element snapshot) { 505 Vector v = new Vector (); 506 NodeList children = snapshot.getChildNodes(); 507 int len = children.getLength(); 508 for (int i = 0; i < len; i++) { 509 Node child = children.item(i); 510 if (child.getNodeType() == Node.ELEMENT_NODE) { 511 Element elem = (Element ) child; 512 if ("package".equals(elem.getNodeName())) { 513 v.addElement(elem); 514 } 515 } 516 } 517 Element [] elems = new Element [v.size()]; 518 v.copyInto(elems); 519 return elems; 520 } 521 522 private static DocumentBuilder newBuilder() { 523 try { 524 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 525 factory.setIgnoringComments(true); 526 factory.setValidating(false); 527 return factory.newDocumentBuilder(); 528 } catch (Exception e) { 529 throw new ExceptionInInitializerError (e); 530 } 531 } 532 533 public void log(String message) { 534 if (task == null) { 535 } else { 537 task.log(message, Project.MSG_DEBUG); 538 } 539 } 540 541 } 542 543 | Popular Tags |