- Fix Audit messages to remove fullpath in it. It won't work on references though. - Fix MAudit handler to print stderr as well so that a missing agent or invalid options return a message. - Enhance options to reflect those available also in Webgain QA 2.1.2+ git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@271226 13f79535-47bb-0310-9956-ffa450edef68master
@@ -1,7 +1,7 @@ | |||||
/* | /* | ||||
* The Apache Software License, Version 1.1 | * The Apache Software License, Version 1.1 | ||||
* | * | ||||
* Copyright (c) 2001 The Apache Software Foundation. All rights | |||||
* Copyright (c) 2001-2002 The Apache Software Foundation. All rights | |||||
* reserved. | * reserved. | ||||
* | * | ||||
* Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | ||||
@@ -53,25 +53,25 @@ | |||||
*/ | */ | ||||
package org.apache.tools.ant.taskdefs.optional.metamata; | package org.apache.tools.ant.taskdefs.optional.metamata; | ||||
import java.io.File; | |||||
import java.io.FileWriter; | |||||
import java.io.IOException; | |||||
import java.io.PrintWriter; | |||||
import java.util.Enumeration; | |||||
import java.util.Hashtable; | |||||
import java.util.Vector; | |||||
import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||
import org.apache.tools.ant.DirectoryScanner; | |||||
import org.apache.tools.ant.Project; | import org.apache.tools.ant.Project; | ||||
import org.apache.tools.ant.Task; | import org.apache.tools.ant.Task; | ||||
import org.apache.tools.ant.taskdefs.ExecuteStreamHandler; | |||||
import org.apache.tools.ant.taskdefs.Execute; | import org.apache.tools.ant.taskdefs.Execute; | ||||
import org.apache.tools.ant.types.Path; | |||||
import org.apache.tools.ant.types.CommandlineJava; | |||||
import org.apache.tools.ant.taskdefs.ExecuteStreamHandler; | |||||
import org.apache.tools.ant.types.Commandline; | import org.apache.tools.ant.types.Commandline; | ||||
import org.apache.tools.ant.types.CommandlineJava; | |||||
import org.apache.tools.ant.types.FileSet; | import org.apache.tools.ant.types.FileSet; | ||||
import org.apache.tools.ant.DirectoryScanner; | |||||
import java.io.File; | |||||
import java.io.IOException; | |||||
import java.io.FileWriter; | |||||
import java.io.PrintWriter; | |||||
import java.util.Hashtable; | |||||
import java.util.Vector; | |||||
import java.util.Enumeration; | |||||
import java.util.Random; | |||||
import org.apache.tools.ant.types.Path; | |||||
import org.apache.tools.ant.util.FileUtils; | |||||
/** | /** | ||||
* Somewhat abstract framework to be used for other metama 2.0 tasks. | * Somewhat abstract framework to be used for other metama 2.0 tasks. | ||||
@@ -80,11 +80,9 @@ import java.util.Random; | |||||
* For more information, visit the website at | * For more information, visit the website at | ||||
* <a href="http://www.metamata.com">www.metamata.com</a> | * <a href="http://www.metamata.com">www.metamata.com</a> | ||||
* | * | ||||
* @author <a href="mailto:sbailliez@imediation.com">Stephane Bailliez</a> | |||||
* @author <a href="mailto:sbailliez@apache.org">Stephane Bailliez</a> | |||||
*/ | */ | ||||
public abstract class AbstractMetamataTask extends Task{ | |||||
//--------------------------- ATTRIBUTES ----------------------------------- | |||||
public abstract class AbstractMetamataTask extends Task { | |||||
/** | /** | ||||
* The user classpath to be provided. It matches the -classpath of the | * The user classpath to be provided. It matches the -classpath of the | ||||
@@ -116,7 +114,7 @@ public abstract class AbstractMetamataTask extends Task{ | |||||
// be set when calling scanFileSets(); | // be set when calling scanFileSets(); | ||||
protected Hashtable includedFiles = null; | protected Hashtable includedFiles = null; | ||||
public AbstractMetamataTask(){ | |||||
public AbstractMetamataTask() { | |||||
} | } | ||||
/** initialize the task with the classname of the task to run */ | /** initialize the task with the classname of the task to run */ | ||||
@@ -126,8 +124,12 @@ public abstract class AbstractMetamataTask extends Task{ | |||||
} | } | ||||
/** the metamata.home property to run all tasks. */ | /** the metamata.home property to run all tasks. */ | ||||
public void setMetamatahome(final File metamataHome){ | |||||
this.metamataHome = metamataHome; | |||||
public void setHome(final File value) { | |||||
this.metamataHome = value; | |||||
} | |||||
public void setMetamatahome(final File value) { | |||||
setHome(value); | |||||
} | } | ||||
/** user classpath */ | /** user classpath */ | ||||
@@ -139,8 +141,8 @@ public abstract class AbstractMetamataTask extends Task{ | |||||
} | } | ||||
/** create the source path for this task */ | /** create the source path for this task */ | ||||
public Path createSourcepath(){ | |||||
if (sourcePath == null){ | |||||
public Path createSourcepath() { | |||||
if (sourcePath == null) { | |||||
sourcePath = new Path(project); | sourcePath = new Path(project); | ||||
} | } | ||||
return sourcePath; | return sourcePath; | ||||
@@ -152,7 +154,7 @@ public abstract class AbstractMetamataTask extends Task{ | |||||
} | } | ||||
/** -mx or -Xmx depending on VM version */ | /** -mx or -Xmx depending on VM version */ | ||||
public void setMaxmemory(String max){ | |||||
public void setMaxmemory(String max) { | |||||
if (Project.getJavaVersion().startsWith("1.1")) { | if (Project.getJavaVersion().startsWith("1.1")) { | ||||
createJvmarg().setValue("-mx" + max); | createJvmarg().setValue("-mx" + max); | ||||
} else { | } else { | ||||
@@ -177,8 +179,6 @@ public abstract class AbstractMetamataTask extends Task{ | |||||
} | } | ||||
} | } | ||||
//--------------------- PRIVATE/PROTECTED METHODS -------------------------- | |||||
/** check the options and build the command line */ | /** check the options and build the command line */ | ||||
protected void setUp() throws BuildException { | protected void setUp() throws BuildException { | ||||
checkOptions(); | checkOptions(); | ||||
@@ -190,10 +190,12 @@ public abstract class AbstractMetamataTask extends Task{ | |||||
// set the metamata.home property | // set the metamata.home property | ||||
final Commandline.Argument vmArgs = cmdl.createVmArgument(); | final Commandline.Argument vmArgs = cmdl.createVmArgument(); | ||||
vmArgs.setValue("-Dmetamata.home=" + metamataHome.getAbsolutePath() ); | |||||
vmArgs.setValue("-Dmetamata.home=" + metamataHome.getAbsolutePath()); | |||||
// retrieve all the files we want to scan | // retrieve all the files we want to scan | ||||
includedFiles = scanFileSets(); | |||||
includedFiles = scanSources(new Hashtable()); | |||||
//String[] entries = sourcePath.list(); | |||||
//includedFiles = scanSources(new Hashtable(), entries); | |||||
log(includedFiles.size() + " files added for audit", Project.MSG_VERBOSE); | log(includedFiles.size() + " files added for audit", Project.MSG_VERBOSE); | ||||
// write all the options to a temp file and use it ro run the process | // write all the options to a temp file and use it ro run the process | ||||
@@ -220,34 +222,33 @@ public abstract class AbstractMetamataTask extends Task{ | |||||
if (process.execute() != 0) { | if (process.execute() != 0) { | ||||
throw new BuildException("Metamata task failed."); | throw new BuildException("Metamata task failed."); | ||||
} | } | ||||
} catch (IOException e){ | |||||
throw new BuildException("Failed to launch Metamata task: " + e); | |||||
} catch (IOException e) { | |||||
throw new BuildException("Failed to launch Metamata task", e); | |||||
} | } | ||||
} | } | ||||
/** clean up all the mess that we did with temporary objects */ | /** clean up all the mess that we did with temporary objects */ | ||||
protected void cleanUp(){ | |||||
if (optionsFile != null){ | |||||
protected void cleanUp() { | |||||
if (optionsFile != null) { | |||||
optionsFile.delete(); | optionsFile.delete(); | ||||
optionsFile = null; | optionsFile = null; | ||||
} | } | ||||
} | } | ||||
/** return the location of the jar file used to run */ | /** return the location of the jar file used to run */ | ||||
protected final File getMetamataJar(File home){ | |||||
return new File(new File(home.getAbsolutePath()), "lib/metamata.jar"); | |||||
protected final File getMetamataJar(File home) { | |||||
return new File(home, "lib/metamata.jar"); | |||||
} | } | ||||
/** validate options set */ | /** validate options set */ | ||||
protected void checkOptions() throws BuildException { | protected void checkOptions() throws BuildException { | ||||
// do some validation first | // do some validation first | ||||
if (metamataHome == null || !metamataHome.exists()){ | |||||
throw new BuildException("'metamatahome' must point to Metamata home directory."); | |||||
if (metamataHome == null || !metamataHome.exists()) { | |||||
throw new BuildException("'home' must point to Metamata home directory."); | |||||
} | } | ||||
metamataHome = project.resolveFile(metamataHome.getPath()); | |||||
File jar = getMetamataJar(metamataHome); | File jar = getMetamataJar(metamataHome); | ||||
if (!jar.exists()){ | |||||
throw new BuildException( jar + " does not exist. Check your metamata installation."); | |||||
if (!jar.exists()) { | |||||
throw new BuildException(jar + " does not exist. Check your metamata installation."); | |||||
} | } | ||||
} | } | ||||
@@ -261,65 +262,94 @@ public abstract class AbstractMetamataTask extends Task{ | |||||
fw = new FileWriter(tofile); | fw = new FileWriter(tofile); | ||||
PrintWriter pw = new PrintWriter(fw); | PrintWriter pw = new PrintWriter(fw); | ||||
final int size = options.size(); | final int size = options.size(); | ||||
for (int i = 0; i < size; i++){ | |||||
pw.println( options.elementAt(i) ); | |||||
for (int i = 0; i < size; i++) { | |||||
pw.println(options.elementAt(i)); | |||||
} | } | ||||
pw.flush(); | pw.flush(); | ||||
} catch (IOException e){ | |||||
} catch (IOException e) { | |||||
throw new BuildException("Error while writing options file " + tofile, e); | throw new BuildException("Error while writing options file " + tofile, e); | ||||
} finally { | } finally { | ||||
if (fw != null){ | |||||
if (fw != null) { | |||||
try { | try { | ||||
fw.close(); | fw.close(); | ||||
} catch (IOException ignored){} | |||||
} catch (IOException ignored) { | |||||
} | |||||
} | } | ||||
} | } | ||||
} | } | ||||
protected Hashtable getFileMapping(){ | |||||
protected Hashtable getFileMapping() { | |||||
return includedFiles; | return includedFiles; | ||||
} | } | ||||
/** | /** | ||||
* convenient method for JDK 1.1. Will copy all elements from src to dest | * convenient method for JDK 1.1. Will copy all elements from src to dest | ||||
*/ | */ | ||||
protected static final void addAllVector(Vector dest, Enumeration files){ | |||||
protected static final void addAllVector(Vector dest, Enumeration files) { | |||||
while (files.hasMoreElements()) { | while (files.hasMoreElements()) { | ||||
dest.addElement( files.nextElement() ); | |||||
dest.addElement(files.nextElement()); | |||||
} | } | ||||
} | } | ||||
protected static final File createTmpFile(){ | |||||
// must be compatible with JDK 1.1 !!!! | |||||
final long rand = (new Random(System.currentTimeMillis())).nextLong(); | |||||
File file = new File("metamata" + rand + ".tmp"); | |||||
return file; | |||||
protected final File createTmpFile() { | |||||
return FileUtils.newFileUtils().createTempFile("metamata", ".tmp", getProject().getBaseDir()); | |||||
} | } | ||||
/** | /** | ||||
* @return the list of .java files (as their absolute path) that should | * @return the list of .java files (as their absolute path) that should | ||||
* be audited. | * be audited. | ||||
*/ | */ | ||||
protected Hashtable scanFileSets(){ | |||||
protected Hashtable scanSources(Hashtable map) { | |||||
Hashtable files = new Hashtable(); | Hashtable files = new Hashtable(); | ||||
for (int i = 0; i < fileSets.size(); i++){ | |||||
for (int i = 0; i < fileSets.size(); i++) { | |||||
FileSet fs = (FileSet) fileSets.elementAt(i); | FileSet fs = (FileSet) fileSets.elementAt(i); | ||||
DirectoryScanner ds = fs.getDirectoryScanner(project); | DirectoryScanner ds = fs.getDirectoryScanner(project); | ||||
ds.scan(); | ds.scan(); | ||||
String[] f = ds.getIncludedFiles(); | String[] f = ds.getIncludedFiles(); | ||||
log(i + ") Adding " + f.length + " files from directory " + ds.getBasedir(), Project.MSG_VERBOSE); | log(i + ") Adding " + f.length + " files from directory " + ds.getBasedir(), Project.MSG_VERBOSE); | ||||
for (int j = 0; j < f.length; j++){ | |||||
for (int j = 0; j < f.length; j++) { | |||||
String pathname = f[j]; | String pathname = f[j]; | ||||
if ( pathname.endsWith(".java") ){ | |||||
File file = new File( ds.getBasedir(), pathname); | |||||
if (pathname.endsWith(".java")) { | |||||
File file = new File(ds.getBasedir(), pathname); | |||||
// file = project.resolveFile(file.getAbsolutePath()); | // file = project.resolveFile(file.getAbsolutePath()); | ||||
String classname = pathname.substring(0, pathname.length()-".java".length()); | |||||
String classname = pathname.substring(0, pathname.length() - ".java".length()); | |||||
classname = classname.replace(File.separatorChar, '.'); | classname = classname.replace(File.separatorChar, '.'); | ||||
files.put( file.getAbsolutePath(), classname ); // it's a java file, add it. | |||||
files.put(file.getAbsolutePath(), classname); // it's a java file, add it. | |||||
} | } | ||||
} | } | ||||
} | } | ||||
return files; | return files; | ||||
} | } | ||||
protected Hashtable scanSources(final Hashtable mapping, final String[] entries) { | |||||
final Vector javaFiles = new Vector(512); | |||||
for (int i = 0; i < entries.length; i++) { | |||||
final File f = new File(entries[i]); | |||||
if (f.isDirectory()) { | |||||
DirectoryScanner ds = new DirectoryScanner(); | |||||
ds.setBasedir(f); | |||||
ds.setIncludes(new String[]{"**/*.java"}); | |||||
ds.scan(); | |||||
String[] included = ds.getIncludedFiles(); | |||||
for (int j = 0; j < included.length; j++) { | |||||
javaFiles.addElement(new File(f, included[j])); | |||||
} | |||||
} else if (entries[i].endsWith(".java")) { | |||||
javaFiles.addElement(f); | |||||
} | |||||
} | |||||
// do the mapping paths/classname | |||||
final int count = javaFiles.size(); | |||||
for (int i = 0; i < count; i++) { | |||||
File file = (File) javaFiles.elementAt(i); | |||||
String pathname = Path.translateFile(file.getAbsolutePath()); | |||||
String classname = pathname.substring(0, pathname.length() - ".java".length()); | |||||
classname = classname.replace(File.separatorChar, '.'); | |||||
mapping.put(pathname, classname); | |||||
} | |||||
return mapping; | |||||
} | |||||
} | } |
@@ -1,7 +1,7 @@ | |||||
/* | /* | ||||
* The Apache Software License, Version 1.1 | * The Apache Software License, Version 1.1 | ||||
* | * | ||||
* Copyright (c) 2001 The Apache Software Foundation. All rights | |||||
* Copyright (c) 2001-2002 The Apache Software Foundation. All rights | |||||
* reserved. | * reserved. | ||||
* | * | ||||
* Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | ||||
@@ -53,21 +53,19 @@ | |||||
*/ | */ | ||||
package org.apache.tools.ant.taskdefs.optional.metamata; | package org.apache.tools.ant.taskdefs.optional.metamata; | ||||
import java.io.File; | |||||
import java.io.FileOutputStream; | |||||
import java.io.IOException; | |||||
import java.io.OutputStream; | |||||
import java.util.Vector; | |||||
import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||
import org.apache.tools.ant.Project; | import org.apache.tools.ant.Project; | ||||
import org.apache.tools.ant.taskdefs.ExecuteStreamHandler; | import org.apache.tools.ant.taskdefs.ExecuteStreamHandler; | ||||
import org.apache.tools.ant.taskdefs.LogStreamHandler; | import org.apache.tools.ant.taskdefs.LogStreamHandler; | ||||
import org.apache.tools.ant.types.FileSet; | |||||
import org.apache.tools.ant.types.Path; | import org.apache.tools.ant.types.Path; | ||||
import java.io.File; | |||||
import java.io.OutputStream; | |||||
import java.io.FileOutputStream; | |||||
import java.io.IOException; | |||||
import java.util.Vector; | |||||
/** | /** | ||||
* Metamata Audit evaluates Java code for programming errors, weaknesses, and | * Metamata Audit evaluates Java code for programming errors, weaknesses, and | ||||
* style violation. | * style violation. | ||||
@@ -81,7 +79,7 @@ import java.util.Vector; | |||||
* For more information, visit the website at | * For more information, visit the website at | ||||
* <a href="http://www.metamata.com">www.metamata.com</a> | * <a href="http://www.metamata.com">www.metamata.com</a> | ||||
* | * | ||||
* @author <a href="mailto:sbailliez@imediation.com">Stephane Bailliez</a> | |||||
* @author <a href="mailto:sbailliez@apache.org">Stephane Bailliez</a> | |||||
*/ | */ | ||||
public class MAudit extends AbstractMetamataTask { | public class MAudit extends AbstractMetamataTask { | ||||
@@ -119,15 +117,24 @@ public class MAudit extends AbstractMetamataTask { | |||||
// (?:file:)?((?#filepath).+):((?#line)\\d+)\\s*:\\s+((?#message).*) | // (?:file:)?((?#filepath).+):((?#line)\\d+)\\s*:\\s+((?#message).*) | ||||
final static String AUDIT_PATTERN = "(?:file:)?(.+):(\\d+)\\s*:\\s+(.*)"; | final static String AUDIT_PATTERN = "(?:file:)?(.+):(\\d+)\\s*:\\s+(.*)"; | ||||
protected File outFile = null; | |||||
protected Path searchPath = null; | |||||
protected boolean fix = false; | |||||
protected boolean list = false; | |||||
protected boolean unused = false; | |||||
private File outFile = null; | |||||
private Path searchPath = null; | |||||
private Path rulesPath = null; | |||||
private boolean fix = false; | |||||
private boolean list = false; | |||||
private boolean unused = false; | |||||
// add a bunch of undocumented options for the task | |||||
private boolean quiet = false; | |||||
private boolean exit = false; | |||||
private boolean offsets = false; | |||||
private boolean verbose = false; | |||||
private boolean fullsemanticize = false; | |||||
/** default constructor */ | /** default constructor */ | ||||
public MAudit() { | public MAudit() { | ||||
@@ -135,49 +142,101 @@ public class MAudit extends AbstractMetamataTask { | |||||
} | } | ||||
/** set the destination file which should be an xml file */ | /** set the destination file which should be an xml file */ | ||||
public void setTofile(File outFile){ | |||||
public void setTofile(File outFile) { | |||||
this.outFile = outFile; | this.outFile = outFile; | ||||
} | } | ||||
public void setFix(boolean flag){ | |||||
public void setFix(boolean flag) { | |||||
this.fix = flag; | this.fix = flag; | ||||
} | } | ||||
public void setList(boolean flag){ | |||||
public void setList(boolean flag) { | |||||
this.list = flag; | this.list = flag; | ||||
} | } | ||||
public void setUnused(boolean flag){ | |||||
public void setUnused(boolean flag) { | |||||
this.unused = flag; | this.unused = flag; | ||||
} | } | ||||
public Path createSearchpath(){ | |||||
if (searchPath == null){ | |||||
searchPath = new Path(project); | |||||
public void setQuiet(boolean flag) { | |||||
this.quiet = flag; | |||||
} | |||||
public void setExit(boolean flag) { | |||||
this.exit = flag; | |||||
} | |||||
public void setOffsets(boolean flag) { | |||||
this.offsets = flag; | |||||
} | |||||
public void setVerbose(boolean flag) { | |||||
this.verbose = flag; | |||||
} | |||||
public void setFullsemanticize(boolean flag) { | |||||
this.fullsemanticize = flag; | |||||
} | |||||
/** one or more path for rules that must be placed before metamata.jar !! */ | |||||
public Path createRulespath() { | |||||
if (rulesPath == null) { | |||||
rulesPath = new Path(getProject()); | |||||
} | |||||
return rulesPath; | |||||
} | |||||
/** search path to use for unused global declarations */ | |||||
public Path createSearchpath() { | |||||
if (searchPath == null) { | |||||
searchPath = new Path(getProject()); | |||||
} | } | ||||
return searchPath; | return searchPath; | ||||
} | } | ||||
protected Vector getOptions(){ | |||||
protected Vector getOptions() { | |||||
Vector options = new Vector(512); | Vector options = new Vector(512); | ||||
// add the source path automatically from the fileset. | |||||
// to avoid redundancy... | |||||
for (int i = 0; i < fileSets.size(); i++) { | |||||
FileSet fs = (FileSet) fileSets.elementAt(i); | |||||
Path path = createSourcepath(); | |||||
File dir = fs.getDir(getProject()); | |||||
path.setLocation(dir); | |||||
} | |||||
// there is a bug in Metamata 2.0 build 37. The sourcepath argument does | // there is a bug in Metamata 2.0 build 37. The sourcepath argument does | ||||
// not work. So we will use the sourcepath prepended to classpath. (order | // not work. So we will use the sourcepath prepended to classpath. (order | ||||
// is important since Metamata looks at .class and .java) | // is important since Metamata looks at .class and .java) | ||||
if (sourcePath != null){ | |||||
if (sourcePath != null) { | |||||
sourcePath.append(classPath); // srcpath is prepended | sourcePath.append(classPath); // srcpath is prepended | ||||
classPath = sourcePath; | classPath = sourcePath; | ||||
sourcePath = null; // prevent from using -sourcepath | sourcePath = null; // prevent from using -sourcepath | ||||
} | |||||
} | |||||
// don't forget to modify the pattern if you change the options reporting | // don't forget to modify the pattern if you change the options reporting | ||||
if (classPath != null){ | |||||
if (classPath != null) { | |||||
options.addElement("-classpath"); | options.addElement("-classpath"); | ||||
options.addElement(classPath.toString()); | options.addElement(classPath.toString()); | ||||
} | } | ||||
// suppress copyright msg when running, we will let it so that this | // suppress copyright msg when running, we will let it so that this | ||||
// will be the only output to the console if in xml mode | // will be the only output to the console if in xml mode | ||||
// options.addElement("-quiet"); | |||||
if (fix){ | |||||
if (quiet) { | |||||
options.addElement("-quiet"); | |||||
} | |||||
if (fullsemanticize) { | |||||
options.addElement("-full-semanticize"); | |||||
} | |||||
if (verbose) { | |||||
options.addElement("-verbose"); | |||||
} | |||||
if (offsets) { | |||||
options.addElement("-offsets"); | |||||
} | |||||
if (exit) { | |||||
options.addElement("-exit"); | |||||
} | |||||
if (fix) { | |||||
options.addElement("-fix"); | options.addElement("-fix"); | ||||
} | } | ||||
options.addElement("-fullpath"); | options.addElement("-fullpath"); | ||||
@@ -185,43 +244,45 @@ public class MAudit extends AbstractMetamataTask { | |||||
// generate .maudit files much more detailed than the report | // generate .maudit files much more detailed than the report | ||||
// I don't like it very much, I think it could be interesting | // I don't like it very much, I think it could be interesting | ||||
// to get all .maudit files and include them in the XML. | // to get all .maudit files and include them in the XML. | ||||
if (list){ | |||||
if (list) { | |||||
options.addElement("-list"); | options.addElement("-list"); | ||||
} | } | ||||
if (sourcePath != null){ | |||||
if (sourcePath != null) { | |||||
options.addElement("-sourcepath"); | options.addElement("-sourcepath"); | ||||
options.addElement(sourcePath.toString()); | options.addElement(sourcePath.toString()); | ||||
} | } | ||||
if (unused){ | |||||
addAllVector(options, includedFiles.keys()); | |||||
if (unused) { | |||||
options.addElement("-unused"); | options.addElement("-unused"); | ||||
options.addElement(searchPath.toString()); | options.addElement(searchPath.toString()); | ||||
} | } | ||||
addAllVector(options, includedFiles.keys()); | |||||
return options; | return options; | ||||
} | } | ||||
protected void checkOptions() throws BuildException { | protected void checkOptions() throws BuildException { | ||||
super.checkOptions(); | super.checkOptions(); | ||||
if (unused && searchPath == null){ | |||||
if (unused && searchPath == null) { | |||||
throw new BuildException("'searchpath' element must be set when looking for 'unused' declarations."); | throw new BuildException("'searchpath' element must be set when looking for 'unused' declarations."); | ||||
} | } | ||||
if (!unused && searchPath != null){ | |||||
if (!unused && searchPath != null) { | |||||
log("'searchpath' element ignored. 'unused' attribute is disabled.", Project.MSG_WARN); | log("'searchpath' element ignored. 'unused' attribute is disabled.", Project.MSG_WARN); | ||||
} | } | ||||
if (rulesPath != null) { | |||||
cmdl.createClasspath(getProject()).addExisting(rulesPath); | |||||
} | |||||
} | } | ||||
protected ExecuteStreamHandler createStreamHandler() throws BuildException { | protected ExecuteStreamHandler createStreamHandler() throws BuildException { | ||||
ExecuteStreamHandler handler = null; | ExecuteStreamHandler handler = null; | ||||
// if we didn't specify a file, then use a screen report | // if we didn't specify a file, then use a screen report | ||||
if (outFile == null){ | |||||
handler = new LogStreamHandler(this, Project.MSG_INFO, Project.MSG_INFO); | |||||
if (outFile == null) { | |||||
handler = new LogStreamHandler(this, Project.MSG_INFO, Project.MSG_INFO); | |||||
} else { | } else { | ||||
try { | try { | ||||
//XXX | //XXX | ||||
OutputStream out = new FileOutputStream( outFile ); | |||||
OutputStream out = new FileOutputStream(outFile); | |||||
handler = new MAuditStreamHandler(this, out); | handler = new MAuditStreamHandler(this, out); | ||||
} catch (IOException e){ | |||||
} catch (IOException e) { | |||||
throw new BuildException(e); | throw new BuildException(e); | ||||
} | } | ||||
} | } | ||||
@@ -242,18 +303,9 @@ public class MAudit extends AbstractMetamataTask { | |||||
/** the inner class used to report violation information */ | /** the inner class used to report violation information */ | ||||
final static class Violation { | final static class Violation { | ||||
int line; | |||||
String line; | |||||
String error; | String error; | ||||
} | } | ||||
/** handy factory to create a violation */ | |||||
static final Violation createViolation(int line, String msg){ | |||||
Violation violation = new Violation(); | |||||
violation.line = line; | |||||
violation.error = msg; | |||||
return violation; | |||||
} | |||||
} | } | ||||
@@ -1,7 +1,7 @@ | |||||
/* | /* | ||||
* The Apache Software License, Version 1.1 | * The Apache Software License, Version 1.1 | ||||
* | * | ||||
* Copyright (c) 2001 The Apache Software Foundation. All rights | |||||
* Copyright (c) 2001-2002 The Apache Software Foundation. All rights | |||||
* reserved. | * reserved. | ||||
* | * | ||||
* Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | ||||
@@ -53,31 +53,34 @@ | |||||
*/ | */ | ||||
package org.apache.tools.ant.taskdefs.optional.metamata; | package org.apache.tools.ant.taskdefs.optional.metamata; | ||||
import org.apache.tools.ant.Project; | |||||
import org.apache.tools.ant.taskdefs.ExecuteStreamHandler; | |||||
import org.apache.tools.ant.util.regexp.RegexpMatcher; | |||||
import org.apache.tools.ant.util.regexp.RegexpMatcherFactory; | |||||
import org.apache.tools.ant.util.DOMElementWriter; | |||||
import org.w3c.dom.Document; | |||||
import org.w3c.dom.Element; | |||||
import java.io.BufferedReader; | import java.io.BufferedReader; | ||||
import java.io.OutputStream; | |||||
import java.io.InputStream; | |||||
import java.io.File; | |||||
import java.io.IOException; | import java.io.IOException; | ||||
import java.io.InputStream; | |||||
import java.io.InputStreamReader; | import java.io.InputStreamReader; | ||||
import java.io.Writer; | |||||
import java.io.OutputStream; | |||||
import java.io.OutputStreamWriter; | import java.io.OutputStreamWriter; | ||||
import java.util.Hashtable; | |||||
import java.io.Writer; | |||||
import java.util.Date; | |||||
import java.util.Enumeration; | import java.util.Enumeration; | ||||
import java.util.Hashtable; | |||||
import java.util.Vector; | import java.util.Vector; | ||||
import javax.xml.parsers.DocumentBuilder; | import javax.xml.parsers.DocumentBuilder; | ||||
import javax.xml.parsers.DocumentBuilderFactory; | import javax.xml.parsers.DocumentBuilderFactory; | ||||
import org.w3c.dom.Document; | |||||
import org.w3c.dom.Element; | |||||
import org.apache.tools.ant.Project; | |||||
import org.apache.tools.ant.taskdefs.ExecuteStreamHandler; | |||||
import org.apache.tools.ant.taskdefs.LogOutputStream; | |||||
import org.apache.tools.ant.taskdefs.StreamPumper; | |||||
import org.apache.tools.ant.util.DOMElementWriter; | |||||
import org.apache.tools.ant.util.DateUtils; | |||||
import org.apache.tools.ant.util.StringUtils; | |||||
import org.apache.tools.ant.util.regexp.RegexpMatcher; | |||||
import org.apache.tools.ant.util.regexp.RegexpMatcherFactory; | |||||
/** | /** | ||||
* This is a very bad stream handler for the MAudit task. | * This is a very bad stream handler for the MAudit task. | ||||
@@ -93,31 +96,41 @@ import javax.xml.parsers.DocumentBuilderFactory; | |||||
* <li>it does not report error that goes to stderr. | * <li>it does not report error that goes to stderr. | ||||
* </ul> | * </ul> | ||||
* | * | ||||
* @author <a href="sbailliez@imediation.com">Stephane Bailliez</a> | |||||
* @author <a href="mailto:sbailliez@apache.org">Stephane Bailliez</a> | |||||
*/ | */ | ||||
class MAuditStreamHandler implements ExecuteStreamHandler { | class MAuditStreamHandler implements ExecuteStreamHandler { | ||||
protected MAudit task; | |||||
/** parent task */ | |||||
private MAudit task; | |||||
/** reader for stdout */ | /** reader for stdout */ | ||||
protected BufferedReader br; | |||||
private BufferedReader br; | |||||
/** matcher that will be used to extract the info from the line */ | /** matcher that will be used to extract the info from the line */ | ||||
protected RegexpMatcher matcher; | |||||
private RegexpMatcher matcher; | |||||
/** | /** | ||||
* this is where the XML output will go, should mostly be a file | * this is where the XML output will go, should mostly be a file | ||||
* the caller is responsible for flushing and closing this stream | * the caller is responsible for flushing and closing this stream | ||||
*/ | */ | ||||
protected OutputStream xmlOut = null; | |||||
private OutputStream xmlOut = null; | |||||
/** error stream, might be useful to spit out error messages */ | |||||
private OutputStream errStream; | |||||
/** thread pumping out error stream */ | |||||
private Thread errThread; | |||||
/** | /** | ||||
* the multimap. The key in the map is the filepath that caused the audit | * the multimap. The key in the map is the filepath that caused the audit | ||||
* error and the value is a vector of MAudit.Violation entries. | * error and the value is a vector of MAudit.Violation entries. | ||||
*/ | */ | ||||
protected Hashtable auditedFiles = new Hashtable(); | |||||
private Hashtable auditedFiles = new Hashtable(); | |||||
MAuditStreamHandler(MAudit task, OutputStream xmlOut){ | |||||
/** program start timestamp for reporting purpose */ | |||||
private Date program_start; | |||||
MAuditStreamHandler(MAudit task, OutputStream xmlOut) { | |||||
this.task = task; | this.task = task; | ||||
this.xmlOut = xmlOut; | this.xmlOut = xmlOut; | ||||
/** the matcher should be the Oro one. I don't know about the other one */ | /** the matcher should be the Oro one. I don't know about the other one */ | ||||
@@ -126,10 +139,14 @@ class MAuditStreamHandler implements ExecuteStreamHandler { | |||||
} | } | ||||
/** Ignore. */ | /** Ignore. */ | ||||
public void setProcessInputStream(OutputStream os) {} | |||||
public void setProcessInputStream(OutputStream os) { | |||||
} | |||||
/** Ignore. */ | /** Ignore. */ | ||||
public void setProcessErrorStream(InputStream is) {} | |||||
public void setProcessErrorStream(InputStream is) { | |||||
errStream = new LogOutputStream(task, Project.MSG_ERR); | |||||
errThread = createPump(is, errStream); | |||||
} | |||||
/** Set the inputstream */ | /** Set the inputstream */ | ||||
public void setProcessOutputStream(InputStream is) throws IOException { | public void setProcessOutputStream(InputStream is) throws IOException { | ||||
@@ -138,6 +155,8 @@ class MAuditStreamHandler implements ExecuteStreamHandler { | |||||
/** Invokes parseOutput. This will block until the end :-(*/ | /** Invokes parseOutput. This will block until the end :-(*/ | ||||
public void start() throws IOException { | public void start() throws IOException { | ||||
program_start = new Date(); | |||||
errThread.start(); | |||||
parseOutput(br); | parseOutput(br); | ||||
} | } | ||||
@@ -146,19 +165,32 @@ class MAuditStreamHandler implements ExecuteStreamHandler { | |||||
* the MAudit output and write it to the output. | * the MAudit output and write it to the output. | ||||
*/ | */ | ||||
public void stop() { | public void stop() { | ||||
// make sure to flush err stream | |||||
try { | |||||
errThread.join(); | |||||
} catch (InterruptedException e) { | |||||
} | |||||
try { | |||||
errStream.flush(); | |||||
} catch (IOException e) { | |||||
} | |||||
// serialize the content as XML, move this to another method | // serialize the content as XML, move this to another method | ||||
// this is the only code that could be needed to be overrided | |||||
// this is the only code that could be needed to be overriden | |||||
Document doc = getDocumentBuilder().newDocument(); | Document doc = getDocumentBuilder().newDocument(); | ||||
Element rootElement = doc.createElement("classes"); | Element rootElement = doc.createElement("classes"); | ||||
Enumeration keys = auditedFiles.keys(); | Enumeration keys = auditedFiles.keys(); | ||||
Hashtable filemapping = task.getFileMapping(); | Hashtable filemapping = task.getFileMapping(); | ||||
final Date now = new Date(); | |||||
rootElement.setAttribute("snapshot_created", DateUtils.format(now, DateUtils.ISO8601_DATETIME_PATTERN)); | |||||
rootElement.setAttribute("elapsed_time", String.valueOf(now.getTime() - program_start.getTime())); | |||||
rootElement.setAttribute("program_start", DateUtils.format(now, DateUtils.ISO8601_DATETIME_PATTERN)); | |||||
rootElement.setAttribute("audited", String.valueOf(filemapping.size())); | rootElement.setAttribute("audited", String.valueOf(filemapping.size())); | ||||
rootElement.setAttribute("reported", String.valueOf(auditedFiles.size())); | rootElement.setAttribute("reported", String.valueOf(auditedFiles.size())); | ||||
int errors = 0; | int errors = 0; | ||||
while (keys.hasMoreElements()){ | |||||
String filepath = (String)keys.nextElement(); | |||||
Vector v = (Vector)auditedFiles.get(filepath); | |||||
String fullclassname = (String)filemapping.get(filepath); | |||||
while (keys.hasMoreElements()) { | |||||
String filepath = (String) keys.nextElement(); | |||||
Vector v = (Vector) auditedFiles.get(filepath); | |||||
String fullclassname = (String) filemapping.get(filepath); | |||||
if (fullclassname == null) { | if (fullclassname == null) { | ||||
task.getProject().log("Could not find class mapping for " + filepath, Project.MSG_WARN); | task.getProject().log("Could not find class mapping for " + filepath, Project.MSG_WARN); | ||||
continue; | continue; | ||||
@@ -169,12 +201,13 @@ class MAuditStreamHandler implements ExecuteStreamHandler { | |||||
Element clazz = doc.createElement("class"); | Element clazz = doc.createElement("class"); | ||||
clazz.setAttribute("package", pkg); | clazz.setAttribute("package", pkg); | ||||
clazz.setAttribute("name", clazzname); | clazz.setAttribute("name", clazzname); | ||||
clazz.setAttribute("violations", String.valueOf(v.size())); | |||||
errors += v.size(); | |||||
for (int i = 0; i < v.size(); i++){ | |||||
MAudit.Violation violation = (MAudit.Violation)v.elementAt(i); | |||||
final int violationCount = v.size(); | |||||
clazz.setAttribute("violations", String.valueOf(violationCount)); | |||||
errors += violationCount; | |||||
for (int i = 0; i < violationCount; i++) { | |||||
MAudit.Violation violation = (MAudit.Violation) v.elementAt(i); | |||||
Element error = doc.createElement("violation"); | Element error = doc.createElement("violation"); | ||||
error.setAttribute("line", String.valueOf(violation.line)); | |||||
error.setAttribute("line", violation.line); | |||||
error.setAttribute("message", violation.error); | error.setAttribute("message", violation.error); | ||||
clazz.appendChild(error); | clazz.appendChild(error); | ||||
} | } | ||||
@@ -183,54 +216,67 @@ class MAuditStreamHandler implements ExecuteStreamHandler { | |||||
rootElement.setAttribute("violations", String.valueOf(errors)); | rootElement.setAttribute("violations", String.valueOf(errors)); | ||||
// now write it to the outputstream, not very nice code | // now write it to the outputstream, not very nice code | ||||
if (xmlOut != null) { | |||||
Writer wri = null; | |||||
try { | |||||
wri = new OutputStreamWriter(xmlOut, "UTF-8"); | |||||
wri.write("<?xml version=\"1.0\"?>\n"); | |||||
(new DOMElementWriter()).write(rootElement, wri, 0, " "); | |||||
wri.flush(); | |||||
} catch(IOException exc) { | |||||
task.log("Unable to write log file", Project.MSG_ERR); | |||||
} finally { | |||||
if (xmlOut != System.out && xmlOut != System.err) { | |||||
if (wri != null) { | |||||
try { | |||||
wri.close(); | |||||
} catch (IOException e) {} | |||||
} | |||||
Writer wri = null; | |||||
try { | |||||
wri = new OutputStreamWriter(xmlOut, "UTF-8"); | |||||
wri.write("<?xml version=\"1.0\"?>\n"); | |||||
(new DOMElementWriter()).write(rootElement, wri, 0, " "); | |||||
wri.flush(); | |||||
} catch (IOException exc) { | |||||
task.log("Unable to write log file", Project.MSG_ERR); | |||||
} finally { | |||||
if (wri != null) { | |||||
try { | |||||
wri.close(); | |||||
} catch (IOException e) { | |||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
protected static DocumentBuilder getDocumentBuilder() { | protected static DocumentBuilder getDocumentBuilder() { | ||||
try { | try { | ||||
return DocumentBuilderFactory.newInstance().newDocumentBuilder(); | return DocumentBuilderFactory.newInstance().newDocumentBuilder(); | ||||
} | |||||
catch(Exception exc) { | |||||
} catch (Exception exc) { | |||||
throw new ExceptionInInitializerError(exc); | throw new ExceptionInInitializerError(exc); | ||||
} | } | ||||
} | } | ||||
/** | |||||
* Creates a stream pumper to copy the given input stream to the given output stream. | |||||
*/ | |||||
protected Thread createPump(InputStream is, OutputStream os) { | |||||
final Thread result = new Thread(new StreamPumper(is, os)); | |||||
result.setDaemon(true); | |||||
return result; | |||||
} | |||||
/** read each line and process it */ | /** read each line and process it */ | ||||
protected void parseOutput(BufferedReader br) throws IOException { | protected void parseOutput(BufferedReader br) throws IOException { | ||||
String line = null; | String line = null; | ||||
while ( (line = br.readLine()) != null ){ | |||||
while ((line = br.readLine()) != null) { | |||||
processLine(line); | processLine(line); | ||||
} | } | ||||
} | } | ||||
// we suppose here that there is only one report / line. | // we suppose here that there is only one report / line. | ||||
// There will obviouslly be a problem if the message is on several lines... | // There will obviouslly be a problem if the message is on several lines... | ||||
protected void processLine(String line){ | |||||
protected void processLine(String line) { | |||||
Vector matches = matcher.getGroups(line); | Vector matches = matcher.getGroups(line); | ||||
if (matches != null) { | if (matches != null) { | ||||
String file = (String)matches.elementAt(1); | |||||
int lineNum = Integer.parseInt((String)matches.elementAt(2)); | |||||
String msg = (String)matches.elementAt(3); | |||||
addViolationEntry(file, MAudit.createViolation(lineNum, msg) ); | |||||
String file = (String) matches.elementAt(1); | |||||
MAudit.Violation violation = new MAudit.Violation(); | |||||
violation.line = (String) matches.elementAt(2); | |||||
violation.error = (String) matches.elementAt(3); | |||||
// remove the pathname from any messages and let the classname only. | |||||
final int pos = file.lastIndexOf(File.separatorChar); | |||||
if ((pos != -1) && (pos != file.length() - 1)) { | |||||
String filename = file.substring(pos + 1); | |||||
violation.error = StringUtils.replace(violation.error, | |||||
"file:" + file, filename); | |||||
} | |||||
addViolationEntry(file, violation); | |||||
} else { | } else { | ||||
// this doesn't match..report it as info, it could be | // this doesn't match..report it as info, it could be | ||||
// either the copyright, summary or a multiline message (damn !) | // either the copyright, summary or a multiline message (damn !) | ||||
@@ -239,14 +285,14 @@ class MAuditStreamHandler implements ExecuteStreamHandler { | |||||
} | } | ||||
/** add a violation entry for the file */ | /** add a violation entry for the file */ | ||||
protected void addViolationEntry(String file, MAudit.Violation entry){ | |||||
Vector violations = (Vector)auditedFiles.get(file); | |||||
// if there is no decl for this file yet, create it. | |||||
if (violations == null){ | |||||
violations = new Vector(); | |||||
auditedFiles.put(file, violations); | |||||
} | |||||
violations.add( entry ); | |||||
protected void addViolationEntry(String file, MAudit.Violation entry) { | |||||
Vector violations = (Vector) auditedFiles.get(file); | |||||
// if there is no decl for this file yet, create it. | |||||
if (violations == null) { | |||||
violations = new Vector(); | |||||
auditedFiles.put(file, violations); | |||||
} | |||||
violations.addElement(entry); | |||||
} | } | ||||
} | } |
@@ -53,21 +53,19 @@ | |||||
*/ | */ | ||||
package org.apache.tools.ant.taskdefs.optional.metamata; | package org.apache.tools.ant.taskdefs.optional.metamata; | ||||
import java.io.File; | |||||
import java.io.FileInputStream; | |||||
import java.io.FileOutputStream; | |||||
import java.io.IOException; | |||||
import java.util.Vector; | |||||
import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||
import org.apache.tools.ant.Project; | import org.apache.tools.ant.Project; | ||||
import org.apache.tools.ant.taskdefs.ExecuteStreamHandler; | import org.apache.tools.ant.taskdefs.ExecuteStreamHandler; | ||||
import org.apache.tools.ant.taskdefs.LogStreamHandler; | import org.apache.tools.ant.taskdefs.LogStreamHandler; | ||||
import org.apache.tools.ant.types.EnumeratedAttribute; | |||||
import org.apache.tools.ant.types.Path; | import org.apache.tools.ant.types.Path; | ||||
import java.io.File; | |||||
import java.io.FileInputStream; | |||||
import java.io.IOException; | |||||
import java.io.FileOutputStream; | |||||
import java.util.Vector; | |||||
/** | /** | ||||
* Calculates global complexity and quality metrics on Java source code. | * Calculates global complexity and quality metrics on Java source code. | ||||
* | * | ||||
@@ -114,15 +112,15 @@ Format Options | |||||
*/ | */ | ||||
/** the granularity mode. Should be one of 'files', 'methods' and 'types'. */ | /** the granularity mode. Should be one of 'files', 'methods' and 'types'. */ | ||||
protected String granularity = null; | |||||
private String granularity = null; | |||||
/** the XML output file */ | /** the XML output file */ | ||||
protected File outFile = null; | |||||
private File outFile = null; | |||||
/** the location of the temporary txt report */ | /** the location of the temporary txt report */ | ||||
protected File tmpFile = createTmpFile(); | |||||
private File tmpFile; | |||||
protected Path path = null; | |||||
private Path path = null; | |||||
//--------------------------- PUBLIC METHODS ------------------------------- | //--------------------------- PUBLIC METHODS ------------------------------- | ||||
@@ -131,20 +129,29 @@ Format Options | |||||
super("com.metamata.sc.MMetrics"); | super("com.metamata.sc.MMetrics"); | ||||
} | } | ||||
/** | |||||
* Attributes for granularity. | |||||
*/ | |||||
public static class GranularityAttribute extends EnumeratedAttribute { | |||||
public String[] getValues() { | |||||
return new String[]{"compilation-units", "files", "methods", "types", "packages"}; | |||||
} | |||||
} | |||||
/** | /** | ||||
* set the granularity of the audit. Should be one of 'files', 'methods' | * set the granularity of the audit. Should be one of 'files', 'methods' | ||||
* or 'types'. | * or 'types'. | ||||
* @param granularity the audit reporting mode. | * @param granularity the audit reporting mode. | ||||
*/ | */ | ||||
public void setGranularity(String granularity){ | |||||
this.granularity = granularity; | |||||
public void setGranularity(GranularityAttribute granularity) { | |||||
this.granularity = granularity.getValue(); | |||||
} | } | ||||
/** | /** | ||||
* Set the output XML file | * Set the output XML file | ||||
* @param file the xml file to write the XML report to. | * @param file the xml file to write the XML report to. | ||||
*/ | */ | ||||
public void setTofile(File file){ | |||||
public void setTofile(File file) { | |||||
this.outFile = file; | this.outFile = file; | ||||
} | } | ||||
@@ -152,7 +159,7 @@ Format Options | |||||
* Set a new path (directory) to measure metrics from. | * Set a new path (directory) to measure metrics from. | ||||
* @return the path instance to use. | * @return the path instance to use. | ||||
*/ | */ | ||||
public Path createPath(){ | |||||
public Path createPath() { | |||||
if (path == null) { | if (path == null) { | ||||
path = new Path(project); | path = new Path(project); | ||||
} | } | ||||
@@ -167,27 +174,24 @@ Format Options | |||||
protected void checkOptions() throws BuildException { | protected void checkOptions() throws BuildException { | ||||
super.checkOptions(); | super.checkOptions(); | ||||
if ( !"files".equals(granularity) && !"methods".equals(granularity) | |||||
&& !"types".equals(granularity) ){ | |||||
throw new BuildException("Metrics reporting granularity is invalid. Must be one of 'files', 'methods', 'types'"); | |||||
} | |||||
if (outFile == null){ | |||||
if (outFile == null) { | |||||
throw new BuildException("Output XML file must be set via 'tofile' attribute."); | throw new BuildException("Output XML file must be set via 'tofile' attribute."); | ||||
} | } | ||||
if (path == null && fileSets.size() == 0){ | |||||
if (path == null && fileSets.size() == 0) { | |||||
throw new BuildException("Must set either paths (path element) or files (fileset element)"); | throw new BuildException("Must set either paths (path element) or files (fileset element)"); | ||||
} | } | ||||
// I don't accept dirs and files at the same time, I cannot recognize the semantic in the result | // I don't accept dirs and files at the same time, I cannot recognize the semantic in the result | ||||
if (path != null && fileSets.size() > 0){ | |||||
if (path != null && fileSets.size() > 0) { | |||||
throw new BuildException("Cannot set paths (path element) and files (fileset element) at the same time"); | throw new BuildException("Cannot set paths (path element) and files (fileset element) at the same time"); | ||||
} | } | ||||
tmpFile = createTmpFile(); | |||||
} | } | ||||
protected void execute0(ExecuteStreamHandler handler) throws BuildException { | protected void execute0(ExecuteStreamHandler handler) throws BuildException { | ||||
super.execute0(handler); | super.execute0(handler); | ||||
transformFile(); | transformFile(); | ||||
} | } | ||||
/** | /** | ||||
* transform the generated file via the handler | * transform the generated file via the handler | ||||
* This function can either be called if the result is written to the output | * This function can either be called if the result is written to the output | ||||
@@ -197,8 +201,8 @@ Format Options | |||||
protected void transformFile() throws BuildException { | protected void transformFile() throws BuildException { | ||||
FileInputStream tmpStream = null; | FileInputStream tmpStream = null; | ||||
try { | try { | ||||
tmpStream = new FileInputStream( tmpFile ); | |||||
} catch (IOException e){ | |||||
tmpStream = new FileInputStream(tmpFile); | |||||
} catch (IOException e) { | |||||
throw new BuildException("Error reading temporary file: " + tmpFile, e); | throw new BuildException("Error reading temporary file: " + tmpFile, e); | ||||
} | } | ||||
FileOutputStream xmlStream = null; | FileOutputStream xmlStream = null; | ||||
@@ -208,29 +212,31 @@ Format Options | |||||
xmlHandler.setProcessOutputStream(tmpStream); | xmlHandler.setProcessOutputStream(tmpStream); | ||||
xmlHandler.start(); | xmlHandler.start(); | ||||
xmlHandler.stop(); | xmlHandler.stop(); | ||||
} catch (IOException e){ | |||||
} catch (IOException e) { | |||||
throw new BuildException("Error creating output file: " + outFile, e); | throw new BuildException("Error creating output file: " + outFile, e); | ||||
} finally { | } finally { | ||||
if (xmlStream != null){ | |||||
if (xmlStream != null) { | |||||
try { | try { | ||||
xmlStream.close(); | xmlStream.close(); | ||||
} catch (IOException ignored){} | |||||
} catch (IOException ignored) { | |||||
} | |||||
} | } | ||||
if (tmpStream != null){ | |||||
if (tmpStream != null) { | |||||
try { | try { | ||||
tmpStream.close(); | tmpStream.close(); | ||||
} catch (IOException ignored){} | |||||
} catch (IOException ignored) { | |||||
} | |||||
} | } | ||||
} | } | ||||
} | } | ||||
/** cleanup the temporary txt report */ | /** cleanup the temporary txt report */ | ||||
protected void cleanUp() throws BuildException { | protected void cleanUp() throws BuildException { | ||||
try { | try { | ||||
super.cleanUp(); | super.cleanUp(); | ||||
} finally { | } finally { | ||||
if (tmpFile != null){ | |||||
if (tmpFile != null) { | |||||
tmpFile.delete(); | tmpFile.delete(); | ||||
tmpFile = null; | tmpFile = null; | ||||
} | } | ||||
@@ -242,52 +248,52 @@ Format Options | |||||
* a normal logger here, otherwise we could use the metrics handler | * a normal logger here, otherwise we could use the metrics handler | ||||
* directly to capture and transform the output on stdout to XML. | * directly to capture and transform the output on stdout to XML. | ||||
*/ | */ | ||||
protected ExecuteStreamHandler createStreamHandler(){ | |||||
protected ExecuteStreamHandler createStreamHandler() { | |||||
// write the report directtly to an XML stream | // write the report directtly to an XML stream | ||||
// return new MMetricsStreamHandler(this, xmlStream); | // return new MMetricsStreamHandler(this, xmlStream); | ||||
return new LogStreamHandler(this, Project.MSG_INFO, Project.MSG_INFO); | return new LogStreamHandler(this, Project.MSG_INFO, Project.MSG_INFO); | ||||
} | } | ||||
protected Vector getOptions(){ | |||||
protected Vector getOptions() { | |||||
Vector options = new Vector(512); | Vector options = new Vector(512); | ||||
// there is a bug in Metamata 2.0 build 37. The sourcepath argument does | // there is a bug in Metamata 2.0 build 37. The sourcepath argument does | ||||
// not work. So we will use the sourcepath prepended to classpath. (order | // not work. So we will use the sourcepath prepended to classpath. (order | ||||
// is important since Metamata looks at .class and .java) | // is important since Metamata looks at .class and .java) | ||||
if (sourcePath != null){ | |||||
if (sourcePath != null) { | |||||
sourcePath.append(classPath); // srcpath is prepended | sourcePath.append(classPath); // srcpath is prepended | ||||
classPath = sourcePath; | classPath = sourcePath; | ||||
sourcePath = null; // prevent from using -sourcepath | sourcePath = null; // prevent from using -sourcepath | ||||
} | } | ||||
// don't forget to modify the pattern if you change the options reporting | // don't forget to modify the pattern if you change the options reporting | ||||
if (classPath != null){ | |||||
if (classPath != null) { | |||||
options.addElement("-classpath"); | options.addElement("-classpath"); | ||||
options.addElement(classPath); | |||||
options.addElement(classPath.toString()); | |||||
} | } | ||||
options.addElement( "-output" ); | |||||
options.addElement( tmpFile.toString() ); | |||||
options.addElement( "-" + granularity); | |||||
options.addElement("-output"); | |||||
options.addElement(tmpFile.toString()); | |||||
options.addElement("-" + granularity); | |||||
// display the metamata copyright | // display the metamata copyright | ||||
// options.addElement( "-quiet"); | // options.addElement( "-quiet"); | ||||
options.addElement( "-format"); | |||||
options.addElement("-format"); | |||||
// need this because that's what the handler is using, it's | // need this because that's what the handler is using, it's | ||||
// way easier to process than any other separator | // way easier to process than any other separator | ||||
options.addElement( "tab"); | |||||
options.addElement("tab"); | |||||
// specify a / as the indent character, used by the handler. | // specify a / as the indent character, used by the handler. | ||||
options.addElement( "-i"); | |||||
options.addElement( "/"); | |||||
options.addElement("-i"); | |||||
options.addElement("/"); | |||||
// directories | // directories | ||||
String[] dirs = path.list(); | String[] dirs = path.list(); | ||||
for (int i = 0; i < dirs.length; i++){ | |||||
options.addElement( dirs[i] ); | |||||
for (int i = 0; i < dirs.length; i++) { | |||||
options.addElement(dirs[i]); | |||||
} | } | ||||
// files next. | |||||
// files next. | |||||
addAllVector(options, includedFiles.keys()); | addAllVector(options, includedFiles.keys()); | ||||
return options; | return options; | ||||
} | } | ||||
@@ -54,32 +54,36 @@ | |||||
package org.apache.tools.ant.taskdefs.optional.metamata; | package org.apache.tools.ant.taskdefs.optional.metamata; | ||||
import org.xml.sax.SAXException; | |||||
import org.xml.sax.Attributes; | |||||
import org.xml.sax.helpers.AttributesImpl; | |||||
import javax.xml.transform.TransformerFactory; | |||||
import javax.xml.transform.Transformer; | |||||
import javax.xml.transform.OutputKeys; | |||||
import javax.xml.transform.stream.StreamResult; | |||||
import javax.xml.transform.sax.TransformerHandler; | |||||
import javax.xml.transform.sax.SAXTransformerFactory; | |||||
import java.util.Stack; | |||||
import java.util.EmptyStackException; | |||||
import java.util.Enumeration; | |||||
import java.util.Vector; | |||||
import java.io.BufferedReader; | |||||
import java.io.IOException; | |||||
import java.io.InputStream; | import java.io.InputStream; | ||||
import java.io.InputStreamReader; | |||||
import java.io.OutputStream; | import java.io.OutputStream; | ||||
import java.io.IOException; | |||||
import java.io.OutputStreamWriter; | import java.io.OutputStreamWriter; | ||||
import java.io.BufferedReader; | |||||
import java.io.InputStreamReader; | |||||
import java.text.ParseException; | |||||
import java.text.NumberFormat; | |||||
import java.text.DecimalFormat; | import java.text.DecimalFormat; | ||||
import java.text.NumberFormat; | |||||
import java.text.ParseException; | |||||
import java.util.Date; | |||||
import java.util.EmptyStackException; | |||||
import java.util.Enumeration; | |||||
import java.util.Stack; | |||||
import java.util.Vector; | |||||
import javax.xml.transform.OutputKeys; | |||||
import javax.xml.transform.Transformer; | |||||
import javax.xml.transform.TransformerFactory; | |||||
import javax.xml.transform.sax.SAXTransformerFactory; | |||||
import javax.xml.transform.sax.TransformerHandler; | |||||
import javax.xml.transform.stream.StreamResult; | |||||
import org.apache.tools.ant.taskdefs.ExecuteStreamHandler; | |||||
import org.apache.tools.ant.Task; | |||||
import org.xml.sax.Attributes; | |||||
import org.xml.sax.SAXException; | |||||
import org.xml.sax.helpers.AttributesImpl; | |||||
import org.apache.tools.ant.BuildException; | |||||
import org.apache.tools.ant.Project; | import org.apache.tools.ant.Project; | ||||
import org.apache.tools.ant.Task; | |||||
import org.apache.tools.ant.taskdefs.ExecuteStreamHandler; | |||||
import org.apache.tools.ant.util.DateUtils; | |||||
/** | /** | ||||
* A handy metrics handler. Most of this code was done only with the | * A handy metrics handler. Most of this code was done only with the | ||||
@@ -95,44 +99,44 @@ import org.apache.tools.ant.Project; | |||||
public class MMetricsStreamHandler implements ExecuteStreamHandler { | public class MMetricsStreamHandler implements ExecuteStreamHandler { | ||||
/** CLASS construct, it should be named something like 'MyClass' */ | /** CLASS construct, it should be named something like 'MyClass' */ | ||||
protected final static String CLASS = "class"; | |||||
private final static String CLASS = "class"; | |||||
/** package construct, it should be look like 'com.mycompany.something' */ | /** package construct, it should be look like 'com.mycompany.something' */ | ||||
protected final static String PACKAGE = "package"; | |||||
private final static String PACKAGE = "package"; | |||||
/** FILE construct, it should look like something 'MyClass.java' or 'MyClass.class' */ | /** FILE construct, it should look like something 'MyClass.java' or 'MyClass.class' */ | ||||
protected final static String FILE = "file"; | |||||
private final static String FILE = "file"; | |||||
/** METHOD construct, it should looke like something 'doSomething(...)' or 'doSomething()' */ | /** METHOD construct, it should looke like something 'doSomething(...)' or 'doSomething()' */ | ||||
protected final static String METHOD = "method"; | |||||
private final static String METHOD = "method"; | |||||
protected final static String[] ATTRIBUTES = { "name", "vg", "loc", | |||||
"dit", "noa", "nrm", "nlm", "wmc", "rfc", "dac", "fanout", "cbo", "lcom", "nocl" | |||||
}; | |||||
private final static String[] ATTRIBUTES = { | |||||
"name", "vg", "loc", "dit", "noa", "nrm", "nlm", "wmc", | |||||
"rfc", "dac", "fanout", "cbo", "lcom", "nocl"}; | |||||
/** reader for stdout */ | /** reader for stdout */ | ||||
protected InputStream metricsOutput; | |||||
private InputStream metricsOutput; | |||||
/** | /** | ||||
* this is where the XML output will go, should mostly be a file | * this is where the XML output will go, should mostly be a file | ||||
* the caller is responsible for flushing and closing this stream | * the caller is responsible for flushing and closing this stream | ||||
*/ | */ | ||||
protected OutputStream xmlOutputStream; | |||||
private OutputStream xmlOutputStream; | |||||
/** metrics handler */ | /** metrics handler */ | ||||
protected TransformerHandler metricsHandler; | |||||
private TransformerHandler metricsHandler; | |||||
/** the task */ | /** the task */ | ||||
protected Task task; | |||||
private Task task; | |||||
/** | /** | ||||
* the stack where are stored the metrics element so that they we can | * the stack where are stored the metrics element so that they we can | ||||
* know if we have to close an element or not. | * know if we have to close an element or not. | ||||
*/ | */ | ||||
protected Stack stack = new Stack(); | |||||
private Stack stack = new Stack(); | |||||
/** initialize this handler */ | /** initialize this handler */ | ||||
MMetricsStreamHandler(Task task, OutputStream xmlOut){ | |||||
MMetricsStreamHandler(Task task, OutputStream xmlOut) { | |||||
this.task = task; | this.task = task; | ||||
this.xmlOutputStream = xmlOut; | this.xmlOutputStream = xmlOut; | ||||
} | } | ||||
@@ -147,34 +151,39 @@ public class MMetricsStreamHandler implements ExecuteStreamHandler { | |||||
/** Set the inputstream */ | /** Set the inputstream */ | ||||
public void setProcessOutputStream(InputStream is) throws IOException { | public void setProcessOutputStream(InputStream is) throws IOException { | ||||
metricsOutput = is; | |||||
metricsOutput = is; | |||||
} | } | ||||
public void start() throws IOException { | public void start() throws IOException { | ||||
// create the transformer handler that will be used to serialize | // create the transformer handler that will be used to serialize | ||||
// the output. | // the output. | ||||
TransformerFactory factory = TransformerFactory.newInstance(); | TransformerFactory factory = TransformerFactory.newInstance(); | ||||
if ( !factory.getFeature(SAXTransformerFactory.FEATURE) ){ | |||||
if (!factory.getFeature(SAXTransformerFactory.FEATURE)) { | |||||
throw new IllegalStateException("Invalid Transformer factory feature"); | throw new IllegalStateException("Invalid Transformer factory feature"); | ||||
} | } | ||||
try { | try { | ||||
metricsHandler = ((SAXTransformerFactory)factory).newTransformerHandler(); | |||||
metricsHandler.setResult( new StreamResult( new OutputStreamWriter(xmlOutputStream, "UTF-8")) ); | |||||
metricsHandler = ((SAXTransformerFactory) factory).newTransformerHandler(); | |||||
metricsHandler.setResult(new StreamResult(new OutputStreamWriter(xmlOutputStream, "UTF-8"))); | |||||
Transformer transformer = metricsHandler.getTransformer(); | Transformer transformer = metricsHandler.getTransformer(); | ||||
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); | transformer.setOutputProperty(OutputKeys.INDENT, "yes"); | ||||
// start the document with a 'metrics' root | // start the document with a 'metrics' root | ||||
final Date now = new Date(); | |||||
metricsHandler.startDocument(); | metricsHandler.startDocument(); | ||||
AttributesImpl attr = new AttributesImpl(); | AttributesImpl attr = new AttributesImpl(); | ||||
attr.addAttribute("", "company", "company", "CDATA", "metamata"); | attr.addAttribute("", "company", "company", "CDATA", "metamata"); | ||||
attr.addAttribute("", "snapshot_created", "snapshot_created", "CDATA", | |||||
DateUtils.format(now, DateUtils.ISO8601_DATETIME_PATTERN)); | |||||
// attr.addAttribute("", "elapsed_time", "elapsed_time", "CDATA", String.valueOf(now.getTime() - program_start.getTime())); | |||||
attr.addAttribute("", "program_start", "program_start", "CDATA", | |||||
DateUtils.format(new Date(), DateUtils.ISO8601_DATETIME_PATTERN)); | |||||
metricsHandler.startElement("", "metrics", "metrics", attr); | metricsHandler.startElement("", "metrics", "metrics", attr); | ||||
// now parse the whole thing | // now parse the whole thing | ||||
parseOutput(); | parseOutput(); | ||||
} catch (Exception e){ | |||||
e.printStackTrace(); | |||||
throw new IOException(e.getMessage()); | |||||
} catch (Exception e) { | |||||
throw new BuildException(e); | |||||
} | } | ||||
} | } | ||||
@@ -185,15 +194,15 @@ public class MMetricsStreamHandler implements ExecuteStreamHandler { | |||||
try { | try { | ||||
// we need to pop everything and close elements that have not been | // we need to pop everything and close elements that have not been | ||||
// closed yet. | // closed yet. | ||||
while ( stack.size() > 0){ | |||||
ElementEntry elem = (ElementEntry)stack.pop(); | |||||
while (stack.size() > 0) { | |||||
ElementEntry elem = (ElementEntry) stack.pop(); | |||||
metricsHandler.endElement("", elem.getType(), elem.getType()); | metricsHandler.endElement("", elem.getType(), elem.getType()); | ||||
} | } | ||||
// close the root | // close the root | ||||
metricsHandler.endElement("", "metrics", "metrics"); | metricsHandler.endElement("", "metrics", "metrics"); | ||||
// document is finished for good | // document is finished for good | ||||
metricsHandler.endDocument(); | metricsHandler.endDocument(); | ||||
} catch (SAXException e){ | |||||
} catch (SAXException e) { | |||||
e.printStackTrace(); | e.printStackTrace(); | ||||
throw new IllegalStateException(e.getMessage()); | throw new IllegalStateException(e.getMessage()); | ||||
} | } | ||||
@@ -203,7 +212,7 @@ public class MMetricsStreamHandler implements ExecuteStreamHandler { | |||||
protected void parseOutput() throws IOException, SAXException { | protected void parseOutput() throws IOException, SAXException { | ||||
BufferedReader br = new BufferedReader(new InputStreamReader(metricsOutput)); | BufferedReader br = new BufferedReader(new InputStreamReader(metricsOutput)); | ||||
String line = null; | String line = null; | ||||
while ( (line = br.readLine()) != null ){ | |||||
while ((line = br.readLine()) != null) { | |||||
processLine(line); | processLine(line); | ||||
} | } | ||||
} | } | ||||
@@ -214,16 +223,16 @@ public class MMetricsStreamHandler implements ExecuteStreamHandler { | |||||
* @param line the line to process, it is normally a line full of metrics. | * @param line the line to process, it is normally a line full of metrics. | ||||
*/ | */ | ||||
protected void processLine(String line) throws SAXException { | protected void processLine(String line) throws SAXException { | ||||
if ( line.startsWith("Construct\tV(G)\tLOC\tDIT\tNOA\tNRM\tNLM\tWMC\tRFC\tDAC\tFANOUT\tCBO\tLCOM\tNOCL") ){ | |||||
if (line.startsWith("Construct\tV(G)\tLOC\tDIT\tNOA\tNRM\tNLM\tWMC\tRFC\tDAC\tFANOUT\tCBO\tLCOM\tNOCL")) { | |||||
return; | return; | ||||
} | } | ||||
try { | try { | ||||
MetricsElement elem = MetricsElement.parse(line); | MetricsElement elem = MetricsElement.parse(line); | ||||
startElement(elem); | startElement(elem); | ||||
} catch (ParseException e) { | } catch (ParseException e) { | ||||
e.printStackTrace(); | |||||
//e.printStackTrace(); | |||||
// invalid lines are sent to the output as information, it might be anything, | // invalid lines are sent to the output as information, it might be anything, | ||||
task.log(line, Project.MSG_INFO); | |||||
task.log(line, Project.MSG_INFO); | |||||
} | } | ||||
} | } | ||||
@@ -238,16 +247,17 @@ public class MMetricsStreamHandler implements ExecuteStreamHandler { | |||||
// if there are elements in the stack we possibly need to close one or | // if there are elements in the stack we possibly need to close one or | ||||
// more elements previous to this one until we got its parent | // more elements previous to this one until we got its parent | ||||
int indent = elem.getIndent(); | int indent = elem.getIndent(); | ||||
if ( stack.size() > 0 ){ | |||||
ElementEntry previous = (ElementEntry)stack.peek(); | |||||
if (stack.size() > 0) { | |||||
ElementEntry previous = (ElementEntry) stack.peek(); | |||||
// close nodes until you got the parent. | // close nodes until you got the parent. | ||||
try { | try { | ||||
while ( indent <= previous.getIndent() && stack.size() > 0){ | |||||
while (indent <= previous.getIndent() && stack.size() > 0) { | |||||
stack.pop(); | stack.pop(); | ||||
metricsHandler.endElement("", previous.getType(), previous.getType()); | metricsHandler.endElement("", previous.getType(), previous.getType()); | ||||
previous = (ElementEntry)stack.peek(); | |||||
previous = (ElementEntry) stack.peek(); | |||||
} | } | ||||
} catch (EmptyStackException ignored){} | |||||
} catch (EmptyStackException ignored) { | |||||
} | |||||
} | } | ||||
// ok, now start the new construct | // ok, now start the new construct | ||||
@@ -256,7 +266,7 @@ public class MMetricsStreamHandler implements ExecuteStreamHandler { | |||||
metricsHandler.startElement("", type, type, attrs); | metricsHandler.startElement("", type, type, attrs); | ||||
// make sure we keep track of what we did, that's history | // make sure we keep track of what we did, that's history | ||||
stack.push( new ElementEntry(type, indent) ); | |||||
stack.push(new ElementEntry(type, indent)); | |||||
} | } | ||||
/** | /** | ||||
@@ -267,36 +277,36 @@ public class MMetricsStreamHandler implements ExecuteStreamHandler { | |||||
* @return the type of the metrics element, either PACKAGE, FILE, CLASS or | * @return the type of the metrics element, either PACKAGE, FILE, CLASS or | ||||
* METHOD. | * METHOD. | ||||
*/ | */ | ||||
protected String getConstructType(MetricsElement elem){ | |||||
protected String getConstructType(MetricsElement elem) { | |||||
// ok no doubt, it's a file | // ok no doubt, it's a file | ||||
if ( elem.isCompilationUnit() ){ | |||||
if (elem.isCompilationUnit()) { | |||||
return FILE; | return FILE; | ||||
} | } | ||||
// same, we're sure it's a method | // same, we're sure it's a method | ||||
if ( elem.isMethod() ){ | |||||
if (elem.isMethod()) { | |||||
return METHOD; | return METHOD; | ||||
} | } | ||||
// if it's empty, and none of the above it should be a package | // if it's empty, and none of the above it should be a package | ||||
if ( stack.size() == 0 ){ | |||||
if (stack.size() == 0) { | |||||
return PACKAGE; | return PACKAGE; | ||||
} | } | ||||
// ok, this is now black magic time, we will guess the type based on | // ok, this is now black magic time, we will guess the type based on | ||||
// the previous type and its indent... | // the previous type and its indent... | ||||
final ElementEntry previous = (ElementEntry)stack.peek(); | |||||
final ElementEntry previous = (ElementEntry) stack.peek(); | |||||
final String prevType = previous.getType(); | final String prevType = previous.getType(); | ||||
final int prevIndent = previous.getIndent(); | final int prevIndent = previous.getIndent(); | ||||
final int indent = elem.getIndent(); | final int indent = elem.getIndent(); | ||||
// we're just under a file with a bigger indent so it's a class | // we're just under a file with a bigger indent so it's a class | ||||
if ( prevType.equals(FILE) && indent > prevIndent ){ | |||||
if (prevType.equals(FILE) && indent > prevIndent) { | |||||
return CLASS; | return CLASS; | ||||
} | } | ||||
// we're just under a class with a greater or equals indent, it's a class | // we're just under a class with a greater or equals indent, it's a class | ||||
// (there might be several classes in a compilation unit and inner classes as well) | // (there might be several classes in a compilation unit and inner classes as well) | ||||
if ( prevType.equals(CLASS) && indent >= prevIndent ){ | |||||
if (prevType.equals(CLASS) && indent >= prevIndent) { | |||||
return CLASS; | return CLASS; | ||||
} | } | ||||
@@ -308,17 +318,16 @@ public class MMetricsStreamHandler implements ExecuteStreamHandler { | |||||
/** | /** | ||||
* Create all attributes of a MetricsElement skipping those who have an | * Create all attributes of a MetricsElement skipping those who have an | ||||
* empty string | * empty string | ||||
* @param elem | |||||
*/ | */ | ||||
protected Attributes createAttributes(MetricsElement elem){ | |||||
protected Attributes createAttributes(MetricsElement elem) { | |||||
AttributesImpl impl = new AttributesImpl(); | AttributesImpl impl = new AttributesImpl(); | ||||
int i = 0; | int i = 0; | ||||
String name = ATTRIBUTES[i++]; | String name = ATTRIBUTES[i++]; | ||||
impl.addAttribute("", name, name, "CDATA", elem.getName()); | impl.addAttribute("", name, name, "CDATA", elem.getName()); | ||||
Enumeration metrics = elem.getMetrics(); | Enumeration metrics = elem.getMetrics(); | ||||
for (; metrics.hasMoreElements(); i++){ | |||||
String value = (String)metrics.nextElement(); | |||||
if ( value.length() > 0 ){ | |||||
for (; metrics.hasMoreElements(); i++) { | |||||
String value = (String) metrics.nextElement(); | |||||
if (value.length() > 0) { | |||||
name = ATTRIBUTES[i]; | name = ATTRIBUTES[i]; | ||||
impl.addAttribute("", name, name, "CDATA", value); | impl.addAttribute("", name, name, "CDATA", value); | ||||
} | } | ||||
@@ -333,13 +342,16 @@ public class MMetricsStreamHandler implements ExecuteStreamHandler { | |||||
private final static class ElementEntry { | private final static class ElementEntry { | ||||
private String type; | private String type; | ||||
private int indent; | private int indent; | ||||
ElementEntry(String type, int indent){ | |||||
ElementEntry(String type, int indent) { | |||||
this.type = type; | this.type = type; | ||||
this.indent = indent; | this.indent = indent; | ||||
} | } | ||||
public String getType(){ | |||||
public String getType() { | |||||
return type; | return type; | ||||
} | } | ||||
public int getIndent() { | public int getIndent() { | ||||
return indent; | return indent; | ||||
} | } | ||||
@@ -351,6 +363,7 @@ class MetricsElement { | |||||
private final static NumberFormat METAMATA_NF; | private final static NumberFormat METAMATA_NF; | ||||
private final static NumberFormat NEUTRAL_NF; | private final static NumberFormat NEUTRAL_NF; | ||||
static { | static { | ||||
METAMATA_NF = NumberFormat.getInstance(); | METAMATA_NF = NumberFormat.getInstance(); | ||||
METAMATA_NF.setMaximumFractionDigits(1); | METAMATA_NF.setMaximumFractionDigits(1); | ||||
@@ -367,30 +380,30 @@ class MetricsElement { | |||||
private Vector metrics; | private Vector metrics; | ||||
MetricsElement(int indent, String construct, Vector metrics){ | |||||
MetricsElement(int indent, String construct, Vector metrics) { | |||||
this.indent = indent; | this.indent = indent; | ||||
this.construct = construct; | this.construct = construct; | ||||
this.metrics = metrics; | this.metrics = metrics; | ||||
} | } | ||||
public int getIndent(){ | |||||
public int getIndent() { | |||||
return indent; | return indent; | ||||
} | } | ||||
public String getName(){ | |||||
public String getName() { | |||||
return construct; | return construct; | ||||
} | } | ||||
public Enumeration getMetrics(){ | |||||
public Enumeration getMetrics() { | |||||
return metrics.elements(); | return metrics.elements(); | ||||
} | } | ||||
public boolean isCompilationUnit(){ | |||||
return ( construct.endsWith(".java") || construct.endsWith(".class") ); | |||||
public boolean isCompilationUnit() { | |||||
return (construct.endsWith(".java") || construct.endsWith(".class")); | |||||
} | } | ||||
public boolean isMethod(){ | |||||
return ( construct.endsWith("(...)") || construct.endsWith("()") ); | |||||
public boolean isMethod() { | |||||
return (construct.endsWith("(...)") || construct.endsWith("()")); | |||||
} | } | ||||
public static MetricsElement parse(String line) throws ParseException { | public static MetricsElement parse(String line) throws ParseException { | ||||
@@ -399,32 +412,32 @@ class MetricsElement { | |||||
// i'm using indexOf since I need to know if there are empty strings | // i'm using indexOf since I need to know if there are empty strings | ||||
// between tabs and I find it easier than with StringTokenizer | // between tabs and I find it easier than with StringTokenizer | ||||
while ( (pos = line.indexOf('\t')) != -1 ){ | |||||
while ((pos = line.indexOf('\t')) != -1) { | |||||
String token = line.substring(0, pos); | String token = line.substring(0, pos); | ||||
// only parse what coudl be a valid number. ie not constructs nor no value | // only parse what coudl be a valid number. ie not constructs nor no value | ||||
/*if (metrics.size() != 0 || token.length() != 0){ | /*if (metrics.size() != 0 || token.length() != 0){ | ||||
Number num = METAMATA_NF.parse(token); // parse with Metamata NF | Number num = METAMATA_NF.parse(token); // parse with Metamata NF | ||||
token = NEUTRAL_NF.format(num.doubleValue()); // and format with a neutral NF | token = NEUTRAL_NF.format(num.doubleValue()); // and format with a neutral NF | ||||
}*/ | }*/ | ||||
metrics.addElement( token ); | |||||
metrics.addElement(token); | |||||
line = line.substring(pos + 1); | line = line.substring(pos + 1); | ||||
} | } | ||||
metrics.addElement( line ); | |||||
metrics.addElement(line); | |||||
// there should be exactly 14 tokens (1 name + 13 metrics), if not, there is a problem ! | // there should be exactly 14 tokens (1 name + 13 metrics), if not, there is a problem ! | ||||
if ( metrics.size() != 14 ){ | |||||
throw new ParseException("Could not parse the following line as a metrics: -->" + line +"<--", -1); | |||||
if (metrics.size() != 14) { | |||||
throw new ParseException("Could not parse the following line as a metrics: -->" + line + "<--", -1); | |||||
} | } | ||||
// remove the first token it's made of the indentation string and the | // remove the first token it's made of the indentation string and the | ||||
// construct name, we'll need all this to figure out what type of | // construct name, we'll need all this to figure out what type of | ||||
// construct it is since we lost all semantics :( | // construct it is since we lost all semantics :( | ||||
// (#indent[/]*)(#construct.*) | // (#indent[/]*)(#construct.*) | ||||
String name = (String)metrics.elementAt(0); | |||||
String name = (String) metrics.elementAt(0); | |||||
metrics.removeElementAt(0); | metrics.removeElementAt(0); | ||||
int indent = 0; | int indent = 0; | ||||
pos = name.lastIndexOf('/'); | pos = name.lastIndexOf('/'); | ||||
if (pos != -1){ | |||||
if (pos != -1) { | |||||
name = name.substring(pos + 1); | name = name.substring(pos + 1); | ||||
indent = pos + 1; // indentation is last position of token + 1 | indent = pos + 1; // indentation is last position of token + 1 | ||||
} | } | ||||