diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/sitraka/XMLReport.java b/src/main/org/apache/tools/ant/taskdefs/optional/sitraka/XMLReport.java
index f6c3bc0d9..c43872f96 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/sitraka/XMLReport.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/sitraka/XMLReport.java
@@ -53,33 +53,32 @@
*/
package org.apache.tools.ant.taskdefs.optional.sitraka;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.ClassFile;
+import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.ClassPathLoader;
+import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.MethodInfo;
+import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.Utils;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.Transformer;
import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.NodeList;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.xml.sax.InputSource;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
-import java.util.Hashtable;
import java.util.Enumeration;
-import java.util.Vector;
+import java.util.Hashtable;
import java.util.NoSuchElementException;
-import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.ClassPathLoader;
-import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.ClassFile;
-import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.MethodInfo;
-import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.MethodInfoList;
-import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.Utils;
-import org.apache.tools.ant.Task;
-import org.apache.tools.ant.Project;
+import java.util.Vector;
/**
* Little hack to process XML report from JProbe. It will fix
@@ -90,498 +89,488 @@ import org.apache.tools.ant.Project;
* @author Stephane Bailliez
*/
public class XMLReport {
- /** task caller, can be null, used for logging purpose */
- protected Task task;
-
- /** the XML file to process just from CovReport */
- protected File file;
-
- /** jprobe home path. It is used to get the DTD */
- protected File jprobeHome;
-
- /** parsed document */
- protected Document report;
-
- /** mapping package name / package node for faster access */
- protected Hashtable pkgMap;
-
- /** mapping classname / class node for faster access */
- protected Hashtable classMap;
-
- /** method filters */
- protected ReportFilters filters;
-
- /** create a new XML report, logging will be on stdout */
- public XMLReport(File file){
- this(null, file);
- }
-
- /** create a new XML report, logging done on the task */
- public XMLReport(Task task, File file){
- this.file = file;
- this.task = task;
- }
-
- /** set the JProbe home path. Used to get the DTD */
- public void setJProbehome(File home){
- jprobeHome = home;
- }
-
- /** set the */
- public void setReportFilters(ReportFilters filters){
- this.filters = filters;
- }
-
-
-
- /** create node maps so that we can access node faster by their name */
- protected void createNodeMaps(){
- pkgMap = new Hashtable();
- classMap = new Hashtable();
- // create a map index of all packages by their name
- // @todo can be done faster by direct access.
- NodeList packages = report.getElementsByTagName("package");
- final int pkglen = packages.getLength();
- log("Indexing " + pkglen + " packages");
- for (int i = pkglen-1; i > -1 ; i--){
- Element pkg = (Element)packages.item(i);
- String pkgname = pkg.getAttribute("name");
-
- int nbclasses = 0;
- // create a map index of all classes by their fully
- // qualified name.
- NodeList classes = pkg.getElementsByTagName("class");
- final int classlen = classes.getLength();
- log("Indexing " + classlen + " classes in package " + pkgname);
- for (int j = classlen-1; j > -1 ; j--){
- Element clazz = (Element)classes.item(j);
- String classname = clazz.getAttribute("name");
- if (pkgname != null && pkgname.length() != 0){
- classname = pkgname + "." + classname;
- }
-
- int nbmethods = 0;
- NodeList methods = clazz.getElementsByTagName("method");
- final int methodlen = methods.getLength();
- for (int k = methodlen-1; k > -1; k--){
- Element meth = (Element)methods.item(k);
- StringBuffer methodname = new StringBuffer(meth.getAttribute("name"));
- methodname.delete(methodname.toString().indexOf("(") , methodname.toString().length());
- String signature = classname + "." + methodname + "()";
- if (filters.accept(signature)){
- log("keeped method:" + signature);
- nbmethods++;
- }
- else {
- clazz.removeChild(meth);
- }
- }
- // if we don't keep any method, we don't keep the class
- if (nbmethods != 0){
- log("Adding class '" + classname + "'");
- classMap.put(classname, clazz);
- nbclasses++;
- }
- else {
- pkg.removeChild(clazz);
- }
- }
- if (nbclasses != 0){
- log("Adding package '" + pkgname + "'");
- pkgMap.put(pkgname, pkg);
- }
- else {
- pkg.getParentNode().removeChild(pkg);
- }
- }
- log("Indexed " + classMap.size() + " classes in " + pkgMap.size() + " packages");
- }
-
- /** create the whole new document */
- public Document createDocument(String[] classPath) throws Exception {
-
- DocumentBuilder dbuilder = newBuilder();
- InputSource is = new InputSource( new FileInputStream(file) );
- if (jprobeHome != null){
- File dtdDir = new File(jprobeHome, "Dtd/snapshot.dtd");
- is.setSystemId( "file:///" + dtdDir.getAbsolutePath() );
- }
- report = dbuilder.parse( is );
- report.normalize();
-
- // create maps for faster node access
- createNodeMaps();
-
- // iterate over the classpath...
- ClassPathLoader cpl = new ClassPathLoader(classPath);
- Enumeration enum = cpl.loaders();
- while ( enum.hasMoreElements() ){
- ClassPathLoader.FileLoader fl = (ClassPathLoader.FileLoader)enum.nextElement();
- ClassFile[] classes = fl.getClasses();
- log("Processing " + classes.length + " classes in " + fl.getFile());
- // process all classes
- for (int i = 0; i < classes.length; i++){
- serializeClass(classes[i]);
- }
- }
- // update the document with the stats
- update();
- return report;
- }
-
- /**
- * JProbe does not put the java.lang prefix for classes
- * in this package, so used this nice method so that
- * I have the same signature for methods
- */
- protected String getMethodSignature(MethodInfo method){
- StringBuffer buf = new StringBuffer(method.getName());
- buf.append("(");
- String[] params = method.getParametersType();
- for (int i = 0; i < params.length; i++){
- String type = params[i];
- int pos = type.lastIndexOf('.');
- if (pos != -1){
- String pkg = type.substring(0, pos);
- if ("java.lang".equals(pkg)){
- params[i] = type.substring(pos + 1);
- }
- }
- buf.append(params[i]);
- if (i != params.length - 1){
- buf.append(", ");
- }
- }
- buf.append(")");
- return buf.toString();
- }
-
- /**
- * Convert to a CovReport-like signature ie, .()
- */
- protected String getMethodSignature(ClassFile clazz, MethodInfo method){
- StringBuffer buf = new StringBuffer(clazz.getFullName());
- buf.append(".");
- buf.append(method.getName());
- buf.append("()");
- return buf.toString();
- }
-
- /**
- * Do additional work on an element to remove abstract methods that
- * are reported by JProbe 3.0
- */
- protected void removeAbstractMethods(ClassFile classFile, Element classNode){
- MethodInfoList methods = classFile.getMethods();
- Hashtable methodNodeList = getMethods(classNode);
- // assert xmlMethods.size() == methods.length()
- final int size = methods.length();
- for (int i = 0; i < size; i++){
- MethodInfo method = methods.getMethod(i);
- String methodSig = getMethodSignature(method);
- Element methodNode = (Element)methodNodeList.get(methodSig);
- if ( methodNode != null &&
- Utils.isAbstract(method.getAccessFlags())) {
- log("\tRemoving method " + methodSig);
- classNode.removeChild(methodNode);
- }
- }
- }
-
- /** create an empty method element with its cov.data values */
- protected Element createMethodElement(MethodInfo method){
- String methodsig = getMethodSignature(method);
- Element methodElem = report.createElement("method");
- methodElem.setAttribute("name", methodsig);
- // create the method cov.data element
- Element methodData = report.createElement("cov.data");
- methodElem.appendChild(methodData);
- methodData.setAttribute("calls", "0");
- methodData.setAttribute("hit_lines", "0");
- methodData.setAttribute("total_lines", String.valueOf(method.getNumberOfLines()));
- return methodElem;
- }
-
- /** create an empty package element with its default cov.data (0) */
- protected Element createPackageElement(String pkgname){
- Element pkgElem = report.createElement("package");
- pkgElem.setAttribute("name", pkgname);
- // create the package cov.data element / default
- // must be updated at the end of the whole process
- Element pkgData = report.createElement("cov.data");
- pkgElem.appendChild(pkgData);
- pkgData.setAttribute("calls", "0");
- pkgData.setAttribute("hit_methods", "0");
- pkgData.setAttribute("total_methods", "0");
- pkgData.setAttribute("hit_lines", "0");
- pkgData.setAttribute("total_lines", "0");
- return pkgElem;
- }
-
- /** create an empty class element with its default cov.data (0) */
- protected Element createClassElement(ClassFile classFile){
- // create the class element
- Element classElem = report.createElement("class");
- classElem.setAttribute("name", classFile.getName());
- classElem.setAttribute("source", classFile.getSourceFile());
- // create the cov.data elem
- Element classData = report.createElement("cov.data");
- classElem.appendChild(classData);
- // create the class cov.data element
- classData.setAttribute("calls", "0");
- classData.setAttribute("hit_methods", "0");
- classData.setAttribute("total_methods", "0");
- classData.setAttribute("hit_lines", "0");
- classData.setAttribute("total_lines", "0");
- return classElem;
- }
-
- /** serialize a classfile into XML */
- protected void serializeClass(ClassFile classFile){
- // the class already is reported so ignore it
- String fullclassname = classFile.getFullName();
- log("Looking for '" + fullclassname + "'");
- Element clazz = (Element)classMap.get(fullclassname);
-
- // ignore classes that are already reported, all the information is
- // already there.
- if ( clazz != null ){
- log("Ignoring " + fullclassname);
- removeAbstractMethods(classFile, clazz);
- return;
- }
-
- // ignore interfaces files, there is no code in there to cover.
- if (Utils.isInterface(classFile.getAccess())){
- return;
- }
-
- Vector methods = getFilteredMethods(classFile);
- // no need to process, there are no methods to add for this class.
- if (methods.size() == 0){
- return;
- }
-
- String pkgname = classFile.getPackage();
- // System.out.println("Looking for package " + pkgname);
- Element pkgElem = (Element)pkgMap.get(pkgname);
- if (pkgElem == null){
- pkgElem = createPackageElement(pkgname);
- report.getDocumentElement().appendChild(pkgElem);
- pkgMap.put(pkgname, pkgElem); // add the pkg to the map
- }
- // this is a brand new class, so we have to create a new node
-
- // create the class element
- Element classElem = createClassElement(classFile);
- pkgElem.appendChild(classElem);
-
- int total_lines = 0;
- int total_methods = 0;
- for (int i = 0; i < methods.size(); i++){
- // create the method element
- MethodInfo method = (MethodInfo)methods.elementAt(i);
- if ( Utils.isAbstract(method.getAccessFlags() ) ){
- continue; // no need to report abstract methods
- }
- Element methodElem = createMethodElement(method);
- classElem.appendChild(methodElem);
- total_lines += method.getNumberOfLines();
- total_methods++;
- }
- // create the class cov.data element
- Element classData = getCovDataChild(classElem);
- classData.setAttribute("total_methods", String.valueOf(total_methods));
- classData.setAttribute("total_lines", String.valueOf(total_lines));
-
- // add itself to the node map
- classMap.put(fullclassname, classElem);
- }
-
- protected Vector getFilteredMethods(ClassFile classFile){
- Vector methods = new Vector();
- MethodInfoList methodlist = classFile.getMethods();
- for (int i = 0; i < methodlist.length(); i++){
- MethodInfo method = methodlist.getMethod(i);
- String signature = getMethodSignature(classFile, method);
- if (filters.accept(signature)){
- methods.addElement(method);
- log("keeping " + signature);
- } else {
+ /** task caller, can be null, used for logging purpose */
+ protected Task task;
+
+ /** the XML file to process just from CovReport */
+ protected File file;
+
+ /** jprobe home path. It is used to get the DTD */
+ protected File jprobeHome;
+
+ /** parsed document */
+ protected Document report;
+
+ /** mapping of class names to ClassFile
s from the reference classpath. It is used to filter the JProbe report. */
+ protected Hashtable classFiles;
+
+ /** mapping package name / package node for faster access */
+ protected Hashtable pkgMap;
+
+ /** mapping classname / class node for faster access */
+ protected Hashtable classMap;
+
+ /** method filters */
+ protected ReportFilters filters;
+
+ /** create a new XML report, logging will be on stdout */
+ public XMLReport(File file) {
+ this(null, file);
+ }
+
+ /** create a new XML report, logging done on the task */
+ public XMLReport(Task task, File file) {
+ this.file = file;
+ this.task = task;
+ }
+
+ /** set the JProbe home path. Used to get the DTD */
+ public void setJProbehome(File home) {
+ jprobeHome = home;
+ }
+
+ /** set the */
+ public void setReportFilters(ReportFilters filters) {
+ this.filters = filters;
+ }
+
+
+ /** create node maps so that we can access node faster by their name */
+ protected void createNodeMaps() {
+ pkgMap = new Hashtable();
+ classMap = new Hashtable();
+ // create a map index of all packages by their name
+ // @todo can be done faster by direct access.
+ NodeList packages = report.getElementsByTagName("package");
+ final int pkglen = packages.getLength();
+ log("Indexing " + pkglen + " packages");
+ for (int i = pkglen - 1; i > -1; i--) {
+ Element pkg = (Element) packages.item(i);
+ String pkgname = pkg.getAttribute("name");
+
+ int nbclasses = 0;
+ // create a map index of all classes by their fully
+ // qualified name.
+ NodeList classes = pkg.getElementsByTagName("class");
+ final int classlen = classes.getLength();
+ log("Indexing " + classlen + " classes in package " + pkgname);
+ for (int j = classlen - 1; j > -1; j--) {
+ Element clazz = (Element) classes.item(j);
+ String classname = clazz.getAttribute("name");
+ if (pkgname != null && pkgname.length() != 0) {
+ classname = pkgname + "." + classname;
+ }
+
+ int nbmethods = 0;
+ NodeList methods = clazz.getElementsByTagName("method");
+ final int methodlen = methods.getLength();
+ for (int k = methodlen - 1; k > -1; k--) {
+ Element meth = (Element) methods.item(k);
+ StringBuffer methodname = new StringBuffer(meth.getAttribute("name"));
+ methodname.delete(methodname.toString().indexOf("("), methodname.toString().length());
+ String signature = classname + "." + methodname + "()";
+ if (filters.accept(signature)) {
+ log("kept method:" + signature);
+ nbmethods++;
+ } else {
+ clazz.removeChild(meth);
+ }
+ }
+ // if we don't keep any method, we don't keep the class
+ if (nbmethods != 0 && classFiles.containsKey(classname)) {
+ log("Adding class '" + classname + "'");
+ classMap.put(classname, clazz);
+ nbclasses++;
+ } else {
+ pkg.removeChild(clazz);
+ }
+ }
+ if (nbclasses != 0) {
+ log("Adding package '" + pkgname + "'");
+ pkgMap.put(pkgname, pkg);
+ } else {
+ pkg.getParentNode().removeChild(pkg);
+ }
+ }
+ log("Indexed " + classMap.size() + " classes in " + pkgMap.size() + " packages");
+ }
+
+ /** create the whole new document */
+ public Document createDocument(String[] classPath) throws Exception {
+
+ // Iterate over the classpath to identify reference classes
+ classFiles = new Hashtable();
+ ClassPathLoader cpl = new ClassPathLoader(classPath);
+ Enumeration enum = cpl.loaders();
+ while (enum.hasMoreElements()) {
+ ClassPathLoader.FileLoader fl = (ClassPathLoader.FileLoader) enum.nextElement();
+ ClassFile[] classes = fl.getClasses();
+ log("Processing " + classes.length + " classes in " + fl.getFile());
+ // process all classes
+ for (int i = 0; i < classes.length; i++) {
+ classFiles.put(classes[i].getFullName(), classes[i]);
+ }
+ }
+
+ // Load the JProbe coverage XML report
+ DocumentBuilder dbuilder = newBuilder();
+ InputSource is = new InputSource(new FileInputStream(file));
+ if (jprobeHome != null) {
+ File dtdDir = new File(jprobeHome, "Dtd");
+ is.setSystemId("file:///" + dtdDir.getAbsolutePath() + "/");
+ }
+ report = dbuilder.parse(is);
+ report.normalize();
+
+ // create maps for faster node access (also filters out unwanted nodes)
+ createNodeMaps();
+
+ // Make sure each class from the reference path ends up in the report
+ Enumeration classes = classFiles.elements();
+ while (classes.hasMoreElements()) {
+ ClassFile cf = (ClassFile) classes.nextElement();
+ serializeClass(cf);
+ }
+ // update the document with the stats
+ update();
+ return report;
+ }
+
+ /**
+ * JProbe does not put the java.lang prefix for classes
+ * in this package, so used this nice method so that
+ * I have the same signature for methods
+ */
+ protected String getMethodSignature(MethodInfo method) {
+ StringBuffer buf = new StringBuffer(method.getName());
+ buf.append("(");
+ String[] params = method.getParametersType();
+ for (int i = 0; i < params.length; i++) {
+ String type = params[i];
+ int pos = type.lastIndexOf('.');
+ if (pos != -1) {
+ String pkg = type.substring(0, pos);
+ if ("java.lang".equals(pkg)) {
+ params[i] = type.substring(pos + 1);
+ }
+ }
+ buf.append(params[i]);
+ if (i != params.length - 1) {
+ buf.append(", ");
+ }
+ }
+ buf.append(")");
+ return buf.toString();
+ }
+
+ /**
+ * Convert to a CovReport-like signature ie, .()
+ */
+ protected String getMethodSignature(ClassFile clazz, MethodInfo method) {
+ StringBuffer buf = new StringBuffer(clazz.getFullName());
+ buf.append(".");
+ buf.append(method.getName());
+ buf.append("()");
+ return buf.toString();
+ }
+
+ /**
+ * Do additional work on an element to remove abstract methods that
+ * are reported by JProbe 3.0
+ */
+ protected void removeAbstractMethods(ClassFile classFile, Element classNode) {
+ MethodInfo[] methods = classFile.getMethods();
+ Hashtable methodNodeList = getMethods(classNode);
+ // assert xmlMethods.size() == methods.length()
+ final int size = methods.length;
+ for (int i = 0; i < size; i++) {
+ MethodInfo method = methods[i];
+ String methodSig = getMethodSignature(method);
+ Element methodNode = (Element) methodNodeList.get(methodSig);
+ if (methodNode != null &&
+ Utils.isAbstract(method.getAccessFlags())) {
+ log("\tRemoving method " + methodSig);
+ classNode.removeChild(methodNode);
+ }
+ }
+ }
+
+ /** create an empty method element with its cov.data values */
+ protected Element createMethodElement(MethodInfo method) {
+ String methodsig = getMethodSignature(method);
+ Element methodElem = report.createElement("method");
+ methodElem.setAttribute("name", methodsig);
+ // create the method cov.data element
+ Element methodData = report.createElement("cov.data");
+ methodElem.appendChild(methodData);
+ methodData.setAttribute("calls", "0");
+ methodData.setAttribute("hit_lines", "0");
+ methodData.setAttribute("total_lines", String.valueOf(method.getNumberOfLines()));
+ return methodElem;
+ }
+
+ /** create an empty package element with its default cov.data (0) */
+ protected Element createPackageElement(String pkgname) {
+ Element pkgElem = report.createElement("package");
+ pkgElem.setAttribute("name", pkgname);
+ // create the package cov.data element / default
+ // must be updated at the end of the whole process
+ Element pkgData = report.createElement("cov.data");
+ pkgElem.appendChild(pkgData);
+ pkgData.setAttribute("calls", "0");
+ pkgData.setAttribute("hit_methods", "0");
+ pkgData.setAttribute("total_methods", "0");
+ pkgData.setAttribute("hit_lines", "0");
+ pkgData.setAttribute("total_lines", "0");
+ return pkgElem;
+ }
+
+ /** create an empty class element with its default cov.data (0) */
+ protected Element createClassElement(ClassFile classFile) {
+ // create the class element
+ Element classElem = report.createElement("class");
+ classElem.setAttribute("name", classFile.getName());
+ classElem.setAttribute("source", classFile.getSourceFile());
+ // create the cov.data elem
+ Element classData = report.createElement("cov.data");
+ classElem.appendChild(classData);
+ // create the class cov.data element
+ classData.setAttribute("calls", "0");
+ classData.setAttribute("hit_methods", "0");
+ classData.setAttribute("total_methods", "0");
+ classData.setAttribute("hit_lines", "0");
+ classData.setAttribute("total_lines", "0");
+ return classElem;
+ }
+
+ /** serialize a classfile into XML */
+ protected void serializeClass(ClassFile classFile) {
+ // the class already is reported so ignore it
+ String fullclassname = classFile.getFullName();
+ log("Looking for '" + fullclassname + "'");
+ Element clazz = (Element) classMap.get(fullclassname);
+
+ // ignore classes that are already reported, all the information is
+ // already there.
+ if (clazz != null) {
+ log("Ignoring " + fullclassname);
+ removeAbstractMethods(classFile, clazz);
+ return;
+ }
+
+ // ignore interfaces files, there is no code in there to cover.
+ if (Utils.isInterface(classFile.getAccess())) {
+ return;
+ }
+
+ Vector methods = getFilteredMethods(classFile);
+ // no need to process, there are no methods to add for this class.
+ if (methods.size() == 0) {
+ return;
+ }
+
+ String pkgname = classFile.getPackage();
+ // System.out.println("Looking for package " + pkgname);
+ Element pkgElem = (Element) pkgMap.get(pkgname);
+ if (pkgElem == null) {
+ pkgElem = createPackageElement(pkgname);
+ report.getDocumentElement().appendChild(pkgElem);
+ pkgMap.put(pkgname, pkgElem); // add the pkg to the map
+ }
+ // this is a brand new class, so we have to create a new node
+
+ // create the class element
+ Element classElem = createClassElement(classFile);
+ pkgElem.appendChild(classElem);
+
+ int total_lines = 0;
+ int total_methods = 0;
+ for (int i = 0; i < methods.size(); i++) {
+ // create the method element
+ MethodInfo method = (MethodInfo) methods.elementAt(i);
+ if (Utils.isAbstract(method.getAccessFlags())) {
+ continue; // no need to report abstract methods
+ }
+ Element methodElem = createMethodElement(method);
+ classElem.appendChild(methodElem);
+ total_lines += method.getNumberOfLines();
+ total_methods++;
+ }
+ // create the class cov.data element
+ Element classData = getCovDataChild(classElem);
+ classData.setAttribute("total_methods", String.valueOf(total_methods));
+ classData.setAttribute("total_lines", String.valueOf(total_lines));
+
+ // add itself to the node map
+ classMap.put(fullclassname, classElem);
+ }
+
+ protected Vector getFilteredMethods(ClassFile classFile) {
+ Vector methods = new Vector();
+ MethodInfo[] methodlist = classFile.getMethods();
+ for (int i = 0; i < methodlist.length; i++) {
+ MethodInfo method = methodlist[i];
+ String signature = getMethodSignature(classFile, method);
+ if (filters.accept(signature)) {
+ methods.addElement(method);
+ log("keeping " + signature);
+ } else {
// log("discarding " + signature);
- }
- }
- return methods;
- }
-
-
- /** update the count of the XML, that is accumulate the stats on
- * methods, classes and package so that the numbers are valid
- * according to the info that was appended to the XML.
- */
- protected void update(){
- int calls = 0;
- int hit_methods = 0;
- int total_methods = 0;
- int hit_lines = 0;
- int total_lines = 0;
-
- // use the map for access, all nodes should be there
- Enumeration enum = pkgMap.elements();
- while ( enum.hasMoreElements() ){
- Element pkgElem = (Element)enum.nextElement();
- String pkgname = pkgElem.getAttribute("name");
- Element[] classes = getClasses(pkgElem);
- int pkg_calls = 0;
- int pkg_hit_methods = 0;
- int pkg_total_methods = 0;
- int pkg_hit_lines = 0;
- int pkg_total_lines = 0;
- //System.out.println("Processing package '" + pkgname + "': " + classes.length + " classes");
- for (int j = 0; j < classes.length; j++){
- Element clazz = classes[j];
- String classname = clazz.getAttribute("name");
- if (pkgname != null && pkgname.length() != 0){
- classname = pkgname + "." + classname;
- }
- // there's only cov.data as a child so bet on it
- Element covdata = getCovDataChild(clazz);
- try {
- pkg_calls += Integer.parseInt(covdata.getAttribute("calls"));
- pkg_hit_methods += Integer.parseInt(covdata.getAttribute("hit_methods"));
- pkg_total_methods += Integer.parseInt(covdata.getAttribute("total_methods"));
- pkg_hit_lines += Integer.parseInt(covdata.getAttribute("hit_lines"));
- pkg_total_lines += Integer.parseInt(covdata.getAttribute("total_lines"));
- } catch (NumberFormatException e){
- System.err.println("Error parsing '" + classname + "' (" + j + "/" + classes.length + ") in package '" + pkgname + "'");
- throw e;
- }
- }
- Element covdata = getCovDataChild(pkgElem);
- covdata.setAttribute("calls", String.valueOf(pkg_calls));
- covdata.setAttribute("hit_methods", String.valueOf(pkg_hit_methods));
- covdata.setAttribute("total_methods", String.valueOf(pkg_total_methods));
- covdata.setAttribute("hit_lines", String.valueOf(pkg_hit_lines));
- covdata.setAttribute("total_lines", String.valueOf(pkg_total_lines));
- calls += pkg_calls;
- hit_methods += pkg_hit_methods;
- total_methods += pkg_total_methods;
- hit_lines += pkg_hit_lines;
- total_lines += pkg_total_lines;
- }
- Element covdata = getCovDataChild(report.getDocumentElement());
- covdata.setAttribute("calls", String.valueOf(calls));
- covdata.setAttribute("hit_methods", String.valueOf(hit_methods));
- covdata.setAttribute("total_methods", String.valueOf(total_methods));
- covdata.setAttribute("hit_lines", String.valueOf(hit_lines));
- covdata.setAttribute("total_lines", String.valueOf(total_lines));
- }
-
- protected Element getCovDataChild(Element parent){
- NodeList children = parent.getChildNodes();
- int len = children.getLength();
- for (int i = 0; i < len; i++){
- Node child = children.item(i);
- if (child.getNodeType() == Node.ELEMENT_NODE){
- Element elem = (Element)child;
- if ("cov.data".equals(elem.getNodeName())){
- return elem;
- }
- }
- }
- throw new NoSuchElementException("Could not find 'cov.data' element in parent '" + parent.getNodeName() + "'");
- }
-
- protected Hashtable getMethods(Element clazz){
- Hashtable map = new Hashtable();
- NodeList children = clazz.getChildNodes();
- int len = children.getLength();
- for (int i = 0; i < len; i++){
- Node child = children.item(i);
- if (child.getNodeType() == Node.ELEMENT_NODE){
- Element elem = (Element)child;
- if ("method".equals(elem.getNodeName())){
- String name = elem.getAttribute("name");
- map.put(name, elem);
- }
- }
- }
- return map;
- }
-
- protected Element[] getClasses(Element pkg){
- Vector v = new Vector();
- NodeList children = pkg.getChildNodes();
- int len = children.getLength();
- for (int i = 0; i < len; i++){
- Node child = children.item(i);
- if (child.getNodeType() == Node.ELEMENT_NODE){
- Element elem = (Element)child;
- if ("class".equals(elem.getNodeName())){
- v.addElement(elem);
- }
- }
- }
- Element[] elems = new Element[v.size()];
- v.copyInto(elems);
- return elems;
-
- }
-
- protected Element[] getPackages(Element snapshot){
- Vector v = new Vector();
- NodeList children = snapshot.getChildNodes();
- int len = children.getLength();
- for (int i = 0; i < len; i++){
- Node child = children.item(i);
- if (child.getNodeType() == Node.ELEMENT_NODE){
- Element elem = (Element)child;
- if ("package".equals(elem.getNodeName())){
- v.addElement(elem);
- }
- }
- }
- Element[] elems = new Element[v.size()];
- v.copyInto(elems);
- return elems;
- }
-
- private static DocumentBuilder newBuilder() {
- try {
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- factory.setIgnoringComments(true);
- factory.setValidating(false);
- return factory.newDocumentBuilder();
- } catch (Exception e){
- throw new ExceptionInInitializerError(e);
- }
- }
-
- public void log(String message){
- if (task == null){
- //System.out.println(message);
- } else {
- task.log(message, Project.MSG_DEBUG);
- }
- }
-
- public static void main(String[] args) throws Exception {
- File reportFile = new File( XMLReport.class.getResource("covreport-test.xml").getFile() );
- XMLReport report = new XMLReport( reportFile );
- report.setJProbehome(new File("d:/Program Files/JProbe"));
- ReportFilters filters = new ReportFilters();
- ReportFilters.Include incl = new ReportFilters.Include();
- incl.setClass("*");
- incl.setMethod("set*");
- filters.addInclude(incl);
- report.setReportFilters(filters);
- Document doc = report.createDocument( new String[]{"Z:/imediation/ichannel/sources/toolkit/lib/imtoolkit.jar"} );
- TransformerFactory tfactory = TransformerFactory.newInstance();
- Transformer transformer = tfactory.newTransformer();
- transformer.setOutputProperty(OutputKeys.INDENT, "yes");
- transformer.setOutputProperty(OutputKeys.METHOD, "xml");
- transformer.transform(new DOMSource(doc), new StreamResult( new FileOutputStream( "d:/tmp/snapshot_merge.xml")));
- }
+ }
+ }
+ return methods;
+ }
+
+
+ /** update the count of the XML, that is accumulate the stats on
+ * methods, classes and package so that the numbers are valid
+ * according to the info that was appended to the XML.
+ */
+ protected void update() {
+ int calls = 0;
+ int hit_methods = 0;
+ int total_methods = 0;
+ int hit_lines = 0;
+ int total_lines = 0;
+
+ // use the map for access, all nodes should be there
+ Enumeration enum = pkgMap.elements();
+ while (enum.hasMoreElements()) {
+ Element pkgElem = (Element) enum.nextElement();
+ String pkgname = pkgElem.getAttribute("name");
+ Element[] classes = getClasses(pkgElem);
+ int pkg_calls = 0;
+ int pkg_hit_methods = 0;
+ int pkg_total_methods = 0;
+ int pkg_hit_lines = 0;
+ int pkg_total_lines = 0;
+ //System.out.println("Processing package '" + pkgname + "': " + classes.length + " classes");
+ for (int j = 0; j < classes.length; j++) {
+ Element clazz = classes[j];
+ String classname = clazz.getAttribute("name");
+ if (pkgname != null && pkgname.length() != 0) {
+ classname = pkgname + "." + classname;
+ }
+ // there's only cov.data as a child so bet on it
+ Element covdata = getCovDataChild(clazz);
+ try {
+ pkg_calls += Integer.parseInt(covdata.getAttribute("calls"));
+ pkg_hit_methods += Integer.parseInt(covdata.getAttribute("hit_methods"));
+ pkg_total_methods += Integer.parseInt(covdata.getAttribute("total_methods"));
+ pkg_hit_lines += Integer.parseInt(covdata.getAttribute("hit_lines"));
+ pkg_total_lines += Integer.parseInt(covdata.getAttribute("total_lines"));
+ } catch (NumberFormatException e) {
+ System.err.println("Error parsing '" + classname + "' (" + j + "/" + classes.length + ") in package '" + pkgname + "'");
+ throw e;
+ }
+ }
+ Element covdata = getCovDataChild(pkgElem);
+ covdata.setAttribute("calls", String.valueOf(pkg_calls));
+ covdata.setAttribute("hit_methods", String.valueOf(pkg_hit_methods));
+ covdata.setAttribute("total_methods", String.valueOf(pkg_total_methods));
+ covdata.setAttribute("hit_lines", String.valueOf(pkg_hit_lines));
+ covdata.setAttribute("total_lines", String.valueOf(pkg_total_lines));
+ calls += pkg_calls;
+ hit_methods += pkg_hit_methods;
+ total_methods += pkg_total_methods;
+ hit_lines += pkg_hit_lines;
+ total_lines += pkg_total_lines;
+ }
+ Element covdata = getCovDataChild(report.getDocumentElement());
+ covdata.setAttribute("calls", String.valueOf(calls));
+ covdata.setAttribute("hit_methods", String.valueOf(hit_methods));
+ covdata.setAttribute("total_methods", String.valueOf(total_methods));
+ covdata.setAttribute("hit_lines", String.valueOf(hit_lines));
+ covdata.setAttribute("total_lines", String.valueOf(total_lines));
+ }
+
+ protected Element getCovDataChild(Element parent) {
+ NodeList children = parent.getChildNodes();
+ int len = children.getLength();
+ for (int i = 0; i < len; i++) {
+ Node child = children.item(i);
+ if (child.getNodeType() == Node.ELEMENT_NODE) {
+ Element elem = (Element) child;
+ if ("cov.data".equals(elem.getNodeName())) {
+ return elem;
+ }
+ }
+ }
+ throw new NoSuchElementException("Could not find 'cov.data' element in parent '" + parent.getNodeName() + "'");
+ }
+
+ protected Hashtable getMethods(Element clazz) {
+ Hashtable map = new Hashtable();
+ NodeList children = clazz.getChildNodes();
+ int len = children.getLength();
+ for (int i = 0; i < len; i++) {
+ Node child = children.item(i);
+ if (child.getNodeType() == Node.ELEMENT_NODE) {
+ Element elem = (Element) child;
+ if ("method".equals(elem.getNodeName())) {
+ String name = elem.getAttribute("name");
+ map.put(name, elem);
+ }
+ }
+ }
+ return map;
+ }
+
+ protected Element[] getClasses(Element pkg) {
+ Vector v = new Vector();
+ NodeList children = pkg.getChildNodes();
+ int len = children.getLength();
+ for (int i = 0; i < len; i++) {
+ Node child = children.item(i);
+ if (child.getNodeType() == Node.ELEMENT_NODE) {
+ Element elem = (Element) child;
+ if ("class".equals(elem.getNodeName())) {
+ v.addElement(elem);
+ }
+ }
+ }
+ Element[] elems = new Element[v.size()];
+ v.copyInto(elems);
+ return elems;
+
+ }
+
+ protected Element[] getPackages(Element snapshot) {
+ Vector v = new Vector();
+ NodeList children = snapshot.getChildNodes();
+ int len = children.getLength();
+ for (int i = 0; i < len; i++) {
+ Node child = children.item(i);
+ if (child.getNodeType() == Node.ELEMENT_NODE) {
+ Element elem = (Element) child;
+ if ("package".equals(elem.getNodeName())) {
+ v.addElement(elem);
+ }
+ }
+ }
+ Element[] elems = new Element[v.size()];
+ v.copyInto(elems);
+ return elems;
+ }
+
+ private static DocumentBuilder newBuilder() {
+ try {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setIgnoringComments(true);
+ factory.setValidating(false);
+ return factory.newDocumentBuilder();
+ } catch (Exception e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ public void log(String message) {
+ if (task == null) {
+ //System.out.println(message);
+ } else {
+ task.log(message, Project.MSG_DEBUG);
+ }
+ }
}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/sitraka/bytecode/ClassFile.java b/src/main/org/apache/tools/ant/taskdefs/optional/sitraka/bytecode/ClassFile.java
index 7fa657950..75f4d3b19 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/sitraka/bytecode/ClassFile.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/sitraka/bytecode/ClassFile.java
@@ -53,154 +53,132 @@
*/
package org.apache.tools.ant.taskdefs.optional.sitraka.bytecode;
+import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.DataInputStream;
-import org.apache.tools.ant.taskdefs.optional.depend.constantpool.ConstantPool;
import org.apache.tools.ant.taskdefs.optional.depend.constantpool.ClassCPInfo;
-import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.attributes.AttributeInfoList;
-import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.attributes.SourceFile;
+import org.apache.tools.ant.taskdefs.optional.depend.constantpool.ConstantPool;
+import org.apache.tools.ant.taskdefs.optional.depend.constantpool.Utf8CPInfo;
import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.attributes.AttributeInfo;
-import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.attributes.SourceDir;
import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.attributes.LineNumberTable;
/**
* Object representing a class.
*
+ * Information are kept to the strict minimum for JProbe reports so
+ * that not too many objects are created for a class, otherwise the
+ * JVM can quickly run out of memory when analyzing a great deal of
+ * classes and keeping them in memory for global analysis.
+ *
* @author Stephane Bailliez
*/
-public class ClassFile {
-
- protected ConstantPool constantPool;
-
- protected InterfaceList interfaces;
-
- protected FieldInfoList fields;
-
- protected MethodInfoList methods;
-
- protected String sourceDir;
-
- protected String sourceFile;
-
- protected int access_flags;
-
- protected int this_class;
-
- protected int super_class;
-
- protected boolean isSynthetic;
-
- protected boolean isDeprecated;
-
- public ClassFile(InputStream is) throws IOException {
- DataInputStream dis = new DataInputStream(is);
- constantPool = new ConstantPool();
-
- int magic = dis.readInt(); // 0xCAFEBABE
- int minor = dis.readShort();
- int major = dis.readShort();
-
- constantPool.read(dis);
- constantPool.resolve();
-
- access_flags = dis.readShort();
- this_class = dis.readShort();
- super_class = dis.readShort();
-
- interfaces = new InterfaceList(constantPool);
- interfaces.read(dis);
- //System.out.println(interfaces.toString());
-
- fields = new FieldInfoList(constantPool);
- fields.read(dis);
- //System.out.println(fields.toString());
-
- methods = new MethodInfoList(constantPool);
- methods.read(dis);
- //System.out.println(methods.toString());
-
- AttributeInfoList attributes = new AttributeInfoList(constantPool);
- attributes.read(dis);
- SourceFile srcFile = (SourceFile)attributes.getAttribute(AttributeInfo.SOURCE_FILE);
- if (srcFile != null){
- sourceFile = srcFile.getValue();
- }
- SourceDir srcDir = (SourceDir)attributes.getAttribute(AttributeInfo.SOURCE_DIR);
- if (srcDir != null){
- sourceDir = srcDir.getValue();
- }
- isSynthetic = attributes.getAttribute(AttributeInfo.SYNTHETIC) != null;
- isDeprecated = attributes.getAttribute(AttributeInfo.DEPRECATED) != null;
- }
-
- public int getAccess(){
- return access_flags;
- }
- public InterfaceList getInterfaces(){
- return interfaces;
- }
- public String getSourceFile(){
- return sourceFile;
- }
- public String getSourceDir(){
- return sourceDir;
- }
- public boolean isSynthetic() {
- return isSynthetic;
- }
- public boolean isDeprecated() {
- return isDeprecated;
- }
- public MethodInfoList getMethods(){
- return methods;
- }
- public FieldInfoList getFields(){
- return fields;
- }
- public String getSuperName(){
- return Utils.getUTF8Value(constantPool, super_class);
- }
- public String getFullName(){
- return ((ClassCPInfo)constantPool.getEntry(this_class)).getClassName().replace('/','.');
- }
- public String getName(){
- String name = getFullName();
- int pos = name.lastIndexOf('.');
- if (pos == -1){
- return "";
- }
- return name.substring(pos + 1);
- }
- public String getPackage(){
- String name = getFullName();
- int pos = name.lastIndexOf('.');
- if (pos == -1){
- return "";
- }
- return name.substring(0, pos);
- }
-
- /** dirty test method, move it into a testcase */
- public static void main(String[] args) throws Exception {
- System.out.println("loading classfile...");
- InputStream is = ClassLoader.getSystemResourceAsStream("java/util/Vector.class");
- ClassFile clazzfile = new ClassFile(is);
- System.out.println("Class name: " + clazzfile.getName());
- MethodInfoList methods = clazzfile.getMethods();
- for (int i = 0; i < methods.length(); i++){
- MethodInfo method = methods.getMethod(i);
- System.out.println("Method: " + method.getFullSignature());
- System.out.println("line: " + method.getNumberOfLines());
- LineNumberTable lnt = method.getCode().getLineNumberTable();
- }
- }
-
+public final class ClassFile {
+
+ private MethodInfo[] methods;
+
+ private String sourceFile;
+
+ private String fullname;
+
+ private int access_flags;
+
+ public ClassFile(InputStream is) throws IOException {
+ DataInputStream dis = new DataInputStream(is);
+ ConstantPool constantPool = new ConstantPool();
+
+ int magic = dis.readInt(); // 0xCAFEBABE
+ int minor = dis.readShort();
+ int major = dis.readShort();
+
+ constantPool.read(dis);
+ constantPool.resolve();
+
+ // class information
+ access_flags = dis.readShort();
+ int this_class = dis.readShort();
+ fullname = ((ClassCPInfo) constantPool.getEntry(this_class)).getClassName().replace('/', '.');
+ int super_class = dis.readShort();
+
+ // skip interfaces...
+ int count = dis.readShort();
+ dis.skipBytes(count * 2); // short
+
+ // skip fields...
+ int numFields = dis.readShort();
+ for (int i = 0; i < numFields; i++) {
+ // 3 short: access flags, name index, descriptor index
+ dis.skip(2 * 3);
+ // attribute list...
+ int attributes_count = dis.readUnsignedShort();
+ for (int j = 0; j < attributes_count; j++) {
+ dis.skipBytes(2); // skip attr_id (short)
+ int len = dis.readInt();
+ dis.skipBytes(len);
+ }
+ }
+
+ // read methods
+ int method_count = dis.readShort();
+ methods = new MethodInfo[method_count];
+ for (int i = 0; i < method_count; i++) {
+ methods[i] = new MethodInfo();
+ methods[i].read(constantPool, dis);
+ }
+
+ // get interesting attributes.
+ int attributes_count = dis.readUnsignedShort();
+ for (int j = 0; j < attributes_count; j++) {
+ int attr_id = dis.readShort();
+ int len = dis.readInt();
+ String attr_name = Utils.getUTF8Value(constantPool, attr_id);
+ if (AttributeInfo.SOURCE_FILE.equals(attr_name)) {
+ int name_index = dis.readShort();
+ sourceFile = ((Utf8CPInfo) constantPool.getEntry(name_index)).getValue();
+ } else {
+ dis.skipBytes(len);
+ }
+ }
+ }
+
+ public int getAccess() {
+ return access_flags;
+ }
+
+ public String getSourceFile() {
+ return sourceFile;
+ }
+
+ public MethodInfo[] getMethods() {
+ return methods;
+ }
+
+ public String getFullName() {
+ return fullname;
+ }
+
+ public String getName() {
+ String name = getFullName();
+ int pos = name.lastIndexOf('.');
+ if (pos == -1) {
+ return "";
+ }
+ return name.substring(pos + 1);
+ }
+
+ public String getPackage() {
+ String name = getFullName();
+ int pos = name.lastIndexOf('.');
+ if (pos == -1) {
+ return "";
+ }
+ return name.substring(0, pos);
+ }
+
}
-
+
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/sitraka/bytecode/MethodInfo.java b/src/main/org/apache/tools/ant/taskdefs/optional/sitraka/bytecode/MethodInfo.java
index a7673b218..d822e33aa 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/sitraka/bytecode/MethodInfo.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/sitraka/bytecode/MethodInfo.java
@@ -53,15 +53,11 @@
*/
package org.apache.tools.ant.taskdefs.optional.sitraka.bytecode;
-import java.io.IOException;
import java.io.DataInputStream;
+import java.io.IOException;
import org.apache.tools.ant.taskdefs.optional.depend.constantpool.ConstantPool;
-import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.attributes.Code;
-import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.attributes.Exceptions;
-import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.attributes.AttributeInfoList;
import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.attributes.AttributeInfo;
-import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.attributes.LineNumberTable;
/**
* Method info structure.
@@ -69,104 +65,119 @@ import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.attributes.LineNu
*
* @author Stephane Bailliez
*/
-public class MethodInfo {
- protected ConstantPool constantPool;
- protected int access_flags;
- protected int name_index;
- protected int descriptor_index;
- protected Code code;
- protected boolean deprecated;
- protected boolean synthetic;
- protected Exceptions exceptions;
- public MethodInfo(ConstantPool pool){
- constantPool = pool;
- }
-
- public void read(DataInputStream dis) throws IOException {
- access_flags = dis.readShort();
- name_index = dis.readShort();
- descriptor_index = dis.readShort();
- AttributeInfoList attrlist = new AttributeInfoList(constantPool);
- attrlist.read(dis);
- code = (Code)attrlist.getAttribute(AttributeInfo.CODE);
- synthetic = attrlist.getAttribute(AttributeInfo.SYNTHETIC) != null;
- deprecated = attrlist.getAttribute(AttributeInfo.DEPRECATED) != null;
- exceptions = (Exceptions)attrlist.getAttribute(AttributeInfo.EXCEPTIONS);
- }
-
- public int getAccessFlags(){
- return access_flags;
- }
-
- public String getName(){
- return Utils.getUTF8Value(constantPool, name_index);
- }
-
- public String getDescriptor(){
- return Utils.getUTF8Value(constantPool, descriptor_index);
- }
-
- public String getFullSignature(){
- return getReturnType() + " " + getShortSignature();
- }
-
- public String getShortSignature(){
- StringBuffer buf = new StringBuffer(getName());
- buf.append("(");
- String[] params = getParametersType();
- for (int i = 0; i < params.length; i++){
- buf.append(params[i]);
- if (i != params.length - 1){
- buf.append(", ");
- }
- }
- buf.append(")");
- return buf.toString();
- }
-
- public String getReturnType(){
- return Utils.getMethodReturnType(getDescriptor());
- }
-
- public String[] getParametersType(){
- return Utils.getMethodParams(getDescriptor());
- }
-
- public Code getCode(){
- return code;
- }
-
- public int getNumberOfLines(){
- int len = -1;
- if (code != null){
- LineNumberTable lnt = code.getLineNumberTable();
- if (lnt != null){
- len = lnt.length();
- }
- }
- return len;
- }
-
- public boolean isDeprecated(){
- return deprecated;
- }
-
- public boolean isSynthetic(){
- return synthetic;
- }
-
- public String getAccess(){
- return Utils.getMethodAccess(access_flags);
- }
-
- public String toString(){
- StringBuffer sb = new StringBuffer();
- sb.append("Method: ").append(getAccess()).append(" ");
- sb.append(getFullSignature());
- sb.append(" synthetic:").append(synthetic);
- sb.append(" deprecated:").append(deprecated);
- return sb.toString();
- }
+public final class MethodInfo {
+ private int access_flags;
+ private int loc = -1;
+ private String name;
+ private String descriptor;
+
+ public MethodInfo() {
+ }
+
+ public void read(ConstantPool constantPool, DataInputStream dis) throws IOException {
+ access_flags = dis.readShort();
+
+ int name_index = dis.readShort();
+ name = Utils.getUTF8Value(constantPool, name_index);
+
+ int descriptor_index = dis.readShort();
+ descriptor = Utils.getUTF8Value(constantPool, descriptor_index);
+
+ int attributes_count = dis.readUnsignedShort();
+ for (int i = 0; i < attributes_count; i++) {
+ int attr_id = dis.readShort();
+ String attr_name = Utils.getUTF8Value(constantPool, attr_id);
+ int len = dis.readInt();
+ if (AttributeInfo.CODE.equals(attr_name)) {
+ readCode(constantPool, dis);
+ } else {
+ dis.skipBytes(len);
+ }
+ }
+
+ }
+
+ protected void readCode(ConstantPool constantPool, DataInputStream dis) throws IOException {
+ // skip max_stack (short), max_local (short)
+ dis.skipBytes(2*2);
+
+ // skip bytecode...
+ int bytecode_len = dis.readInt();
+ dis.skip(bytecode_len);
+
+ // skip exceptions... 1 exception = 4 short.
+ int exception_count = dis.readShort();
+ dis.skipBytes(exception_count * 4 * 2);
+
+ // read attributes...
+ int attributes_count = dis.readUnsignedShort();
+ for (int i = 0; i < attributes_count; i++) {
+ int attr_id = dis.readShort();
+ String attr_name = Utils.getUTF8Value(constantPool, attr_id);
+ int len = dis.readInt();
+ if (AttributeInfo.LINE_NUMBER_TABLE.equals(attr_name)) {
+ // we're only interested in lines of code...
+ loc = dis.readShort();
+ // skip the table which is 2*loc*short
+ dis.skip(loc * 2 * 2);
+ } else {
+ dis.skipBytes(len);
+ }
+ }
+ }
+
+ public int getAccessFlags() {
+ return access_flags;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getDescriptor() {
+ return descriptor;
+ }
+
+ public String getFullSignature() {
+ return getReturnType() + " " + getShortSignature();
+ }
+
+ public String getShortSignature() {
+ StringBuffer buf = new StringBuffer(getName());
+ buf.append("(");
+ String[] params = getParametersType();
+ for (int i = 0; i < params.length; i++) {
+ buf.append(params[i]);
+ if (i != params.length - 1) {
+ buf.append(", ");
+ }
+ }
+ buf.append(")");
+ return buf.toString();
+ }
+
+ public String getReturnType() {
+ return Utils.getMethodReturnType(getDescriptor());
+ }
+
+ public String[] getParametersType() {
+ return Utils.getMethodParams(getDescriptor());
+ }
+
+ public int getNumberOfLines() {
+ return loc;
+ }
+
+ public String getAccess() {
+ return Utils.getMethodAccess(access_flags);
+ }
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("Method: ").append(getAccess()).append(" ");
+ sb.append(getFullSignature());
+ return sb.toString();
+ }
}