Clover coverage report - Ant Coverage
Coverage timestamp: Tue Apr 8 2003 20:43:55 EST
file stats: LOC: 574   Methods: 21
NCLOC: 394   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
XMLReport.java 73.8% 71.1% 76.2% 72%
 1   
 /*
 2   
  * The Apache Software License, Version 1.1
 3   
  *
 4   
  * Copyright (c) 2001-2002 The Apache Software Foundation.  All rights
 5   
  * reserved.
 6   
  *
 7   
  * Redistribution and use in source and binary forms, with or without
 8   
  * modification, are permitted provided that the following conditions
 9   
  * are met:
 10   
  *
 11   
  * 1. Redistributions of source code must retain the above copyright
 12   
  *    notice, this list of conditions and the following disclaimer.
 13   
  *
 14   
  * 2. Redistributions in binary form must reproduce the above copyright
 15   
  *    notice, this list of conditions and the following disclaimer in
 16   
  *    the documentation and/or other materials provided with the
 17   
  *    distribution.
 18   
  *
 19   
  * 3. The end-user documentation included with the redistribution, if
 20   
  *    any, must include the following acknowlegement:
 21   
  *       "This product includes software developed by the
 22   
  *        Apache Software Foundation (http://www.apache.org/)."
 23   
  *    Alternately, this acknowlegement may appear in the software itself,
 24   
  *    if and wherever such third-party acknowlegements normally appear.
 25   
  *
 26   
  * 4. The names "Ant" and "Apache Software
 27   
  *    Foundation" must not be used to endorse or promote products derived
 28   
  *    from this software without prior written permission. For written
 29   
  *    permission, please contact apache@apache.org.
 30   
  *
 31   
  * 5. Products derived from this software may not be called "Apache"
 32   
  *    nor may "Apache" appear in their names without prior written
 33   
  *    permission of the Apache Group.
 34   
  *
 35   
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 36   
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 37   
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 38   
  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 39   
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 40   
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 41   
  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 42   
  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 43   
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 44   
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 45   
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 46   
  * SUCH DAMAGE.
 47   
  * ====================================================================
 48   
  *
 49   
  * This software consists of voluntary contributions made by many
 50   
  * individuals on behalf of the Apache Software Foundation.  For more
 51   
  * information on the Apache Software Foundation, please see
 52   
  * <http://www.apache.org/>.
 53   
  */
 54   
 package org.apache.tools.ant.taskdefs.optional.sitraka;
 55   
 
 56   
 import java.io.File;
 57   
 import java.io.FileInputStream;
 58   
 import java.util.Enumeration;
 59   
 import java.util.Hashtable;
 60   
 import java.util.NoSuchElementException;
 61   
 import java.util.Vector;
 62   
 import javax.xml.parsers.DocumentBuilder;
 63   
 import javax.xml.parsers.DocumentBuilderFactory;
 64   
 import org.apache.tools.ant.Project;
 65   
 import org.apache.tools.ant.Task;
 66   
 import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.ClassFile;
 67   
 import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.ClassPathLoader;
 68   
 import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.MethodInfo;
 69   
 import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.Utils;
 70   
 import org.w3c.dom.Document;
 71   
 import org.w3c.dom.Element;
 72   
 import org.w3c.dom.Node;
 73   
 import org.w3c.dom.NodeList;
 74   
 import org.xml.sax.InputSource;
 75   
 
 76   
 /**
 77   
  * Little hack to process XML report from JProbe. It will fix
 78   
  * some reporting errors from JProbe 3.0 and makes use of a reference
 79   
  * classpath to add classes/methods that were not reported by JProbe
 80   
  * as being used (ie loaded)
 81   
  *
 82   
  * @author <a href="sbailliez@imediation.com">Stephane Bailliez</a>
 83   
  */
 84   
 public class XMLReport {
 85   
     /** task caller, can be null, used for logging purpose */
 86   
     private Task task;
 87   
 
 88   
     /** the XML file to process just from CovReport */
 89   
     private File file;
 90   
 
 91   
     /** jprobe home path. It is used to get the DTD */
 92   
     private File jprobeHome;
 93   
 
 94   
     /** parsed document */
 95   
     private Document report;
 96   
 
 97   
     /** mapping of class names to <code>ClassFile</code>s from the reference classpath.  It is used to filter the JProbe report. */
 98   
     private Hashtable classFiles;
 99   
 
 100   
     /** mapping package name / package node for faster access */
 101   
     private Hashtable pkgMap;
 102   
 
 103   
     /** mapping classname / class node for faster access */
 104   
     private Hashtable classMap;
 105   
 
 106   
     /** method filters */
 107   
     private ReportFilters filters;
 108   
 
 109   
     /** create a new XML report, logging will be on stdout */
 110  1
     public XMLReport(File file) {
 111  1
         this(null, file);
 112   
     }
 113   
 
 114   
     /** create a new XML report, logging done on the task */
 115  1
     public XMLReport(Task task, File file) {
 116  1
         this.file = file;
 117  1
         this.task = task;
 118   
     }
 119   
 
 120   
     /** set the JProbe home path. Used to get the DTD */
 121  0
     public void setJProbehome(File home) {
 122  0
         jprobeHome = home;
 123   
     }
 124   
 
 125   
     /** set the  */
 126  1
     public void setReportFilters(ReportFilters filters) {
 127  1
         this.filters = filters;
 128   
     }
 129   
 
 130   
 
 131   
     /** create node maps so that we can access node faster by their name */
 132  1
     protected void createNodeMaps() {
 133  1
         pkgMap = new Hashtable();
 134  1
         classMap = new Hashtable();
 135   
         // create a map index of all packages by their name
 136   
         // @todo can be done faster by direct access.
 137  1
         NodeList packages = report.getElementsByTagName("package");
 138  1
         final int pkglen = packages.getLength();
 139  1
         log("Indexing " + pkglen + " packages");
 140  1
         for (int i = pkglen - 1; i > -1; i--) {
 141  14
             Element pkg = (Element) packages.item(i);
 142  14
             String pkgname = pkg.getAttribute("name");
 143   
 
 144  14
             int nbclasses = 0;
 145   
             // create a map index of all classes by their fully
 146   
             // qualified name.
 147  14
             NodeList classes = pkg.getElementsByTagName("class");
 148  14
             final int classlen = classes.getLength();
 149  14
             log("Indexing " + classlen + " classes in package " + pkgname);
 150  14
             for (int j = classlen - 1; j > -1; j--) {
 151  245
                 Element clazz = (Element) classes.item(j);
 152  245
                 String classname = clazz.getAttribute("name");
 153  245
                 if (pkgname != null && pkgname.length() != 0) {
 154  245
                     classname = pkgname + "." + classname;
 155   
                 }
 156   
 
 157  245
                 int nbmethods = 0;
 158  245
                 NodeList methods = clazz.getElementsByTagName("method");
 159  245
                 final int methodlen = methods.getLength();
 160  245
                 for (int k = methodlen - 1; k > -1; k--) {
 161  3055
                     Element meth = (Element) methods.item(k);
 162  3055
                     StringBuffer methodname = new StringBuffer(meth.getAttribute("name"));
 163  3055
                     methodname.delete(methodname.toString().indexOf("("), methodname.toString().length());
 164  3055
                     String signature = classname + "." + methodname + "()";
 165  3055
                     if (filters.accept(signature)) {
 166  3
                         log("kept method:" + signature);
 167  3
                         nbmethods++;
 168   
                     } else {
 169  3052
                         clazz.removeChild(meth);
 170   
                     }
 171   
                 }
 172   
                 // if we don't keep any method, we don't keep the class
 173  245
                 if (nbmethods != 0 && classFiles.containsKey(classname)) {
 174  1
                     log("Adding class '" + classname + "'");
 175  1
                     classMap.put(classname, clazz);
 176  1
                     nbclasses++;
 177   
                 } else {
 178  244
                     pkg.removeChild(clazz);
 179   
                 }
 180   
             }
 181  14
             if (nbclasses != 0) {
 182  1
                 log("Adding package '" + pkgname + "'");
 183  1
                 pkgMap.put(pkgname, pkg);
 184   
             } else {
 185  13
                 pkg.getParentNode().removeChild(pkg);
 186   
             }
 187   
         }
 188  1
         log("Indexed " + classMap.size() + " classes in " + pkgMap.size() + " packages");
 189   
     }
 190   
 
 191   
     /** create the whole new document */
 192  1
     public Document createDocument(String[] classPath) throws Exception {
 193   
 
 194   
         // Iterate over the classpath to identify reference classes
 195  1
         classFiles = new Hashtable();
 196  1
         ClassPathLoader cpl = new ClassPathLoader(classPath);
 197  1
         Enumeration enum = cpl.loaders();
 198  1
         while (enum.hasMoreElements()) {
 199  3
             ClassPathLoader.FileLoader fl = (ClassPathLoader.FileLoader) enum.nextElement();
 200  3
             ClassFile[] classes = fl.getClasses();
 201  3
             log("Processing " + classes.length + " classes in " + fl.getFile());
 202   
             // process all classes
 203  3
             for (int i = 0; i < classes.length; i++) {
 204  8693
                 classFiles.put(classes[i].getFullName(), classes[i]);
 205   
             }
 206   
         }
 207   
 
 208   
         // Load the JProbe coverage XML report
 209  1
         DocumentBuilder dbuilder = newBuilder();
 210  1
         InputSource is = new InputSource(new FileInputStream(file));
 211  1
         if (jprobeHome != null) {
 212  0
             File dtdDir = new File(jprobeHome, "dtd");
 213  0
             is.setSystemId("file:///" + dtdDir.getAbsolutePath() + "/");
 214   
         }
 215  1
         report = dbuilder.parse(is);
 216  1
         report.normalize();
 217   
 
 218   
         // create maps for faster node access (also filters out unwanted nodes)
 219  1
         createNodeMaps();
 220   
 
 221   
         // Make sure each class from the reference path ends up in the report
 222  1
         Enumeration classes = classFiles.elements();
 223  1
         while (classes.hasMoreElements()) {
 224  8693
             ClassFile cf = (ClassFile) classes.nextElement();
 225  8693
             serializeClass(cf);
 226   
         }
 227   
         // update the document with the stats
 228  1
         update();
 229  1
         return report;
 230   
     }
 231   
 
 232   
     /**
 233   
      * JProbe does not put the java.lang prefix for classes
 234   
      * in this package, so used this nice method so that
 235   
      * I have the same signature for methods
 236   
      */
 237  47
     protected String getMethodSignature(MethodInfo method) {
 238  47
         StringBuffer buf = new StringBuffer(method.getName());
 239  47
         buf.append("(");
 240  47
         String[] params = method.getParametersType();
 241  47
         for (int i = 0; i < params.length; i++) {
 242  57
             String type = params[i];
 243  57
             int pos = type.lastIndexOf('.');
 244  57
             if (pos != -1) {
 245  22
                 String pkg = type.substring(0, pos);
 246  22
                 if ("java.lang".equals(pkg)) {
 247  16
                     params[i] = type.substring(pos + 1);
 248   
                 }
 249   
             }
 250  57
             buf.append(params[i]);
 251  57
             if (i != params.length - 1) {
 252  10
                 buf.append(", ");
 253   
             }
 254   
         }
 255  47
         buf.append(")");
 256  47
         return buf.toString();
 257   
     }
 258   
 
 259   
     /**
 260   
      * Convert to a CovReport-like signature - &lt;classname&gt;&#046;&lt;method&gt;().
 261   
      */
 262  72231
     protected String getMethodSignature(ClassFile clazz, MethodInfo method) {
 263  72231
         StringBuffer buf = new StringBuffer(clazz.getFullName());
 264  72231
         buf.append(".");
 265  72231
         buf.append(method.getName());
 266  72231
         buf.append("()");
 267  72231
         return buf.toString();
 268   
     }
 269   
 
 270   
     /**
 271   
      * Do additional work on an element to remove abstract methods that
 272   
      * are reported by JProbe 3.0
 273   
      */
 274  1
     protected void removeAbstractMethods(ClassFile classFile, Element classNode) {
 275  1
         MethodInfo[] methods = classFile.getMethods();
 276  1
         Hashtable methodNodeList = getMethods(classNode);
 277   
         // assert xmlMethods.size() == methods.length()
 278  1
         final int size = methods.length;
 279  1
         for (int i = 0; i < size; i++) {
 280  47
             MethodInfo method = methods[i];
 281  47
             String methodSig = getMethodSignature(method);
 282  47
             Element methodNode = (Element) methodNodeList.get(methodSig);
 283  47
             if (methodNode != null &&
 284   
                     Utils.isAbstract(method.getAccessFlags())) {
 285  0
                 log("\tRemoving abstract method " + methodSig);
 286  0
                 classNode.removeChild(methodNode);
 287   
             }
 288   
         }
 289   
     }
 290   
 
 291   
     /** create an empty method element with its cov.data values */
 292  0
     protected Element createMethodElement(MethodInfo method) {
 293  0
         String methodsig = getMethodSignature(method);
 294  0
         Element methodElem = report.createElement("method");
 295  0
         methodElem.setAttribute("name", methodsig);
 296   
         // create the method cov.data element
 297  0
         Element methodData = report.createElement("cov.data");
 298  0
         methodElem.appendChild(methodData);
 299  0
         methodData.setAttribute("calls", "0");
 300  0
         methodData.setAttribute("hit_lines", "0");
 301  0
         methodData.setAttribute("total_lines", String.valueOf(method.getNumberOfLines()));
 302  0
         return methodElem;
 303   
     }
 304   
 
 305   
     /** create an empty package element with its default cov.data (0) */
 306  0
     protected Element createPackageElement(String pkgname) {
 307  0
         Element pkgElem = report.createElement("package");
 308  0
         pkgElem.setAttribute("name", pkgname);
 309   
         // create the package cov.data element / default
 310   
         // must be updated at the end of the whole process
 311  0
         Element pkgData = report.createElement("cov.data");
 312  0
         pkgElem.appendChild(pkgData);
 313  0
         pkgData.setAttribute("calls", "0");
 314  0
         pkgData.setAttribute("hit_methods", "0");
 315  0
         pkgData.setAttribute("total_methods", "0");
 316  0
         pkgData.setAttribute("hit_lines", "0");
 317  0
         pkgData.setAttribute("total_lines", "0");
 318  0
         return pkgElem;
 319   
     }
 320   
 
 321   
     /** create an empty class element with its default cov.data (0) */
 322  0
     protected Element createClassElement(ClassFile classFile) {
 323   
         // create the class element
 324  0
         Element classElem = report.createElement("class");
 325  0
         classElem.setAttribute("name", classFile.getName());
 326   
         // source file possibly does not exist in the bytecode
 327  0
         if (null != classFile.getSourceFile()) {
 328  0
             classElem.setAttribute("source", classFile.getSourceFile());
 329   
         }
 330   
         // create the cov.data elem
 331  0
         Element classData = report.createElement("cov.data");
 332  0
         classElem.appendChild(classData);
 333   
         // create the class cov.data element
 334  0
         classData.setAttribute("calls", "0");
 335  0
         classData.setAttribute("hit_methods", "0");
 336  0
         classData.setAttribute("total_methods", "0");
 337  0
         classData.setAttribute("hit_lines", "0");
 338  0
         classData.setAttribute("total_lines", "0");
 339  0
         return classElem;
 340   
     }
 341   
 
 342   
     /** serialize a classfile into XML */
 343  8693
     protected void serializeClass(ClassFile classFile) {
 344   
         // the class already is reported so ignore it
 345  8693
         String fullclassname = classFile.getFullName();
 346  8693
         log("Looking for '" + fullclassname + "'");
 347  8693
         Element clazz = (Element) classMap.get(fullclassname);
 348   
 
 349   
         // ignore classes that are already reported, all the information is
 350   
         // already there.
 351  8693
         if (clazz != null) {
 352  1
             log("Ignoring " + fullclassname);
 353  1
             removeAbstractMethods(classFile, clazz);
 354  1
             return;
 355   
         }
 356   
 
 357   
         // ignore interfaces files, there is no code in there to cover.
 358  8692
         if (Utils.isInterface(classFile.getAccess())) {
 359  1019
             return;
 360   
         }
 361   
 
 362  7673
         Vector methods = getFilteredMethods(classFile);
 363   
         // no need to process, there are no methods to add for this class.
 364  7673
         if (methods.size() == 0) {
 365  7673
             return;
 366   
         }
 367   
 
 368  0
         String pkgname = classFile.getPackage();
 369   
         // System.out.println("Looking for package " + pkgname);
 370  0
         Element pkgElem = (Element) pkgMap.get(pkgname);
 371  0
         if (pkgElem == null) {
 372  0
             pkgElem = createPackageElement(pkgname);
 373  0
             report.getDocumentElement().appendChild(pkgElem);
 374  0
             pkgMap.put(pkgname, pkgElem); // add the pkg to the map
 375   
         }
 376   
         // this is a brand new class, so we have to create a new node
 377   
 
 378   
         // create the class element
 379  0
         Element classElem = createClassElement(classFile);
 380  0
         pkgElem.appendChild(classElem);
 381   
 
 382  0
         int total_lines = 0;
 383  0
         int total_methods = 0;
 384  0
         final int count = methods.size();
 385  0
         for (int i = 0; i < count; i++) {
 386   
             // create the method element
 387  0
             MethodInfo method = (MethodInfo) methods.elementAt(i);
 388  0
             if (Utils.isAbstract(method.getAccessFlags())) {
 389  0
                 continue; // no need to report abstract methods
 390   
             }
 391  0
             Element methodElem = createMethodElement(method);
 392  0
             classElem.appendChild(methodElem);
 393  0
             total_lines += method.getNumberOfLines();
 394  0
             total_methods++;
 395   
         }
 396   
         // create the class cov.data element
 397  0
         Element classData = getCovDataChild(classElem);
 398  0
         classData.setAttribute("total_methods", String.valueOf(total_methods));
 399  0
         classData.setAttribute("total_lines", String.valueOf(total_lines));
 400   
 
 401   
         // add itself to the node map
 402  0
         classMap.put(fullclassname, classElem);
 403   
     }
 404   
 
 405  7673
     protected Vector getFilteredMethods(ClassFile classFile) {
 406  7673
         MethodInfo[] methodlist = classFile.getMethods();
 407  7673
         Vector methods = new Vector(methodlist.length);
 408  7673
         for (int i = 0; i < methodlist.length; i++) {
 409  72231
             MethodInfo method = methodlist[i];
 410  72231
             String signature = getMethodSignature(classFile, method);
 411  72231
             if (filters.accept(signature)) {
 412  0
                 methods.addElement(method);
 413  0
                 log("keeping " + signature);
 414   
             } else {
 415   
 //              log("discarding " + signature);
 416   
             }
 417   
         }
 418  7673
         return methods;
 419   
     }
 420   
 
 421   
 
 422   
     /** update the count of the XML, that is accumulate the stats on
 423   
      * methods, classes and package so that the numbers are valid
 424   
      * according to the info that was appended to the XML.
 425   
      */
 426  1
     protected void update() {
 427  1
         int calls = 0;
 428  1
         int hit_methods = 0;
 429  1
         int total_methods = 0;
 430  1
         int hit_lines = 0;
 431  1
         int total_lines = 0;
 432   
 
 433   
         // use the map for access, all nodes should be there
 434  1
         Enumeration enum = pkgMap.elements();
 435  1
         while (enum.hasMoreElements()) {
 436  1
             Element pkgElem = (Element) enum.nextElement();
 437  1
             String pkgname = pkgElem.getAttribute("name");
 438  1
             Element[] classes = getClasses(pkgElem);
 439  1
             int pkg_calls = 0;
 440  1
             int pkg_hit_methods = 0;
 441  1
             int pkg_total_methods = 0;
 442  1
             int pkg_hit_lines = 0;
 443  1
             int pkg_total_lines = 0;
 444   
             //System.out.println("Processing package '" + pkgname + "': " + classes.length + " classes");
 445  1
             for (int j = 0; j < classes.length; j++) {
 446  1
                 Element clazz = classes[j];
 447  1
                 String classname = clazz.getAttribute("name");
 448  1
                 if (pkgname != null && pkgname.length() != 0) {
 449  1
                     classname = pkgname + "." + classname;
 450   
                 }
 451   
                 // there's only cov.data as a child so bet on it
 452  1
                 Element covdata = getCovDataChild(clazz);
 453  1
                 try {
 454  1
                     pkg_calls += Integer.parseInt(covdata.getAttribute("calls"));
 455  1
                     pkg_hit_methods += Integer.parseInt(covdata.getAttribute("hit_methods"));
 456  1
                     pkg_total_methods += Integer.parseInt(covdata.getAttribute("total_methods"));
 457  1
                     pkg_hit_lines += Integer.parseInt(covdata.getAttribute("hit_lines"));
 458  1
                     pkg_total_lines += Integer.parseInt(covdata.getAttribute("total_lines"));
 459   
                 } catch (NumberFormatException e) {
 460  0
                     log("Error parsing '" + classname + "' (" + j + "/" + classes.length + ") in package '" + pkgname + "'");
 461  0
                     throw e;
 462   
                 }
 463   
             }
 464  1
             Element covdata = getCovDataChild(pkgElem);
 465  1
             covdata.setAttribute("calls", String.valueOf(pkg_calls));
 466  1
             covdata.setAttribute("hit_methods", String.valueOf(pkg_hit_methods));
 467  1
             covdata.setAttribute("total_methods", String.valueOf(pkg_total_methods));
 468  1
             covdata.setAttribute("hit_lines", String.valueOf(pkg_hit_lines));
 469  1
             covdata.setAttribute("total_lines", String.valueOf(pkg_total_lines));
 470  1
             calls += pkg_calls;
 471  1
             hit_methods += pkg_hit_methods;
 472  1
             total_methods += pkg_total_methods;
 473  1
             hit_lines += pkg_hit_lines;
 474  1
             total_lines += pkg_total_lines;
 475   
         }
 476  1
         Element covdata = getCovDataChild(report.getDocumentElement());
 477  1
         covdata.setAttribute("calls", String.valueOf(calls));
 478  1
         covdata.setAttribute("hit_methods", String.valueOf(hit_methods));
 479  1
         covdata.setAttribute("total_methods", String.valueOf(total_methods));
 480  1
         covdata.setAttribute("hit_lines", String.valueOf(hit_lines));
 481  1
         covdata.setAttribute("total_lines", String.valueOf(total_lines));
 482   
     }
 483   
 
 484  3
     protected Element getCovDataChild(Element parent) {
 485  3
         NodeList children = parent.getChildNodes();
 486  3
         int len = children.getLength();
 487  8
         for (int i = 0; i < len; i++) {
 488  8
             Node child = children.item(i);
 489  8
             if (child.getNodeType() == Node.ELEMENT_NODE) {
 490  4
                 Element elem = (Element) child;
 491  4
                 if ("cov.data".equals(elem.getNodeName())) {
 492  3
                     return elem;
 493   
                 }
 494   
             }
 495   
         }
 496  0
         throw new NoSuchElementException("Could not find 'cov.data' element in parent '" + parent.getNodeName() + "'");
 497   
     }
 498   
 
 499  1
     protected Hashtable getMethods(Element clazz) {
 500  1
         Hashtable map = new Hashtable();
 501  1
         NodeList children = clazz.getChildNodes();
 502  1
         int len = children.getLength();
 503  1
         for (int i = 0; i < len; i++) {
 504  53
             Node child = children.item(i);
 505  53
             if (child.getNodeType() == Node.ELEMENT_NODE) {
 506  4
                 Element elem = (Element) child;
 507  4
                 if ("method".equals(elem.getNodeName())) {
 508  3
                     String name = elem.getAttribute("name");
 509  3
                     map.put(name, elem);
 510   
                 }
 511   
             }
 512   
         }
 513  1
         return map;
 514   
     }
 515   
 
 516  1
     protected Element[] getClasses(Element pkg) {
 517  1
         Vector v = new Vector();
 518  1
         NodeList children = pkg.getChildNodes();
 519  1
         int len = children.getLength();
 520  1
         for (int i = 0; i < len; i++) {
 521  58
             Node child = children.item(i);
 522  58
             if (child.getNodeType() == Node.ELEMENT_NODE) {
 523  2
                 Element elem = (Element) child;
 524  2
                 if ("class".equals(elem.getNodeName())) {
 525  1
                     v.addElement(elem);
 526   
                 }
 527   
             }
 528   
         }
 529  1
         Element[] elems = new Element[v.size()];
 530  1
         v.copyInto(elems);
 531  1
         return elems;
 532   
 
 533   
     }
 534   
 
 535  0
     protected Element[] getPackages(Element snapshot) {
 536  0
         Vector v = new Vector();
 537  0
         NodeList children = snapshot.getChildNodes();
 538  0
         int len = children.getLength();
 539  0
         for (int i = 0; i < len; i++) {
 540  0
             Node child = children.item(i);
 541  0
             if (child.getNodeType() == Node.ELEMENT_NODE) {
 542  0
                 Element elem = (Element) child;
 543  0
                 if ("package".equals(elem.getNodeName())) {
 544  0
                     v.addElement(elem);
 545   
                 }
 546   
             }
 547   
         }
 548  0
         Element[] elems = new Element[v.size()];
 549  0
         v.copyInto(elems);
 550  0
         return elems;
 551   
     }
 552   
 
 553  1
     private static DocumentBuilder newBuilder() {
 554  1
         try {
 555  1
             DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
 556  1
             factory.setIgnoringComments(true);
 557  1
             factory.setValidating(false);
 558  1
             return factory.newDocumentBuilder();
 559   
         } catch (Exception e) {
 560  0
             throw new ExceptionInInitializerError(e);
 561   
         }
 562   
     }
 563   
 
 564  8718
     public void log(String message) {
 565  8718
         if (task == null) {
 566   
             //System.out.println(message);
 567   
         } else {
 568  0
             task.log(message, Project.MSG_DEBUG);
 569   
         }
 570   
     }
 571   
 
 572   
 }
 573   
 
 574