1. /*
  2. * Copyright 2001-2004 The Apache Software Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *
  16. */
  17. package org.apache.tools.ant.taskdefs.optional.sitraka;
  18. import java.io.File;
  19. import java.io.IOException;
  20. import java.util.Vector;
  21. import javax.xml.transform.OutputKeys;
  22. import javax.xml.transform.Result;
  23. import javax.xml.transform.Source;
  24. import javax.xml.transform.Transformer;
  25. import javax.xml.transform.TransformerFactory;
  26. import javax.xml.transform.dom.DOMSource;
  27. import javax.xml.transform.stream.StreamResult;
  28. import org.apache.tools.ant.BuildException;
  29. import org.apache.tools.ant.Project;
  30. import org.apache.tools.ant.taskdefs.Execute;
  31. import org.apache.tools.ant.taskdefs.LogStreamHandler;
  32. import org.apache.tools.ant.types.Commandline;
  33. import org.apache.tools.ant.types.EnumeratedAttribute;
  34. import org.apache.tools.ant.types.Path;
  35. import org.w3c.dom.Document;
  36. /**
  37. * Runs the JProbe Coverage 3.0 snapshot merge utility.
  38. *
  39. * @ant.task name="jpcovreport" category="metrics"
  40. */
  41. public class CovReport extends CovBase {
  42. /*
  43. jpcoverport [options] -output=file -snapshot=snapshot.jpc
  44. jpcovreport [options] [-paramfile=file] -output=<fileName> -snapshot=<fileName>
  45. Generate a report based on the indicated snapshot
  46. -paramfile=file
  47. A text file containing the report generation options.
  48. -format=(html|text|xml) defaults to html
  49. The format of the generated report.
  50. -type=(executive|summary|detailed|verydetailed) defaults to detailed
  51. The type of report to be generated. For -format=xml,
  52. use -type=verydetailed to include source code lines.
  53. Note: A very detailed report can be VERY large.
  54. -percent=num Min 1 Max 101 Default 101
  55. An integer representing a percentage of coverage.
  56. Only methods with test case coverage less than the
  57. percentage are included in reports.
  58. -filters=string
  59. A comma-separated list of filters in the form
  60. <package>.<class>:V, where V can be I for Include or
  61. E for Exclude. For the default package, omit <package>.
  62. -filters_method=string
  63. Optional. A comma-separated list of methods that
  64. correspond one-to-one with the entries in -filters.
  65. -output=string Must be specified
  66. The absolute path and file name for the generated
  67. report file.
  68. -snapshot=string Must be specified
  69. The absolute path and file name of the snapshot file.
  70. -inc_src_text=(on|off) defaults to on
  71. Include text of the source code lines.
  72. Only applies for -format=xml and -type=verydetailed.
  73. -sourcepath=string defaults to .
  74. A semicolon-separated list of source paths.
  75. /*
  76. /** format of generated report, optional */
  77. private String format = null;
  78. /** the name of the output snapshot, mandatory */
  79. private File tofile = null;
  80. /** type of report, optional */
  81. private String type = null;
  82. /** threshold value for printing methods, optional */
  83. private Integer percent = null;
  84. /** comma separated list of filters (???)*/
  85. private String filters = null;
  86. /** name of the snapshot file to create report from */
  87. private File snapshot = null;
  88. /** sourcepath to use */
  89. private Path sourcePath = null;
  90. /** include the text for each line of code (xml report verydetailed)*/
  91. private boolean includeSource = true;
  92. private Path coveragePath = null;
  93. /** */
  94. private Reference reference = null;
  95. public static class ReportFormat extends EnumeratedAttribute {
  96. public String[] getValues() {
  97. return new String[]{"html", "text", "xml"};
  98. }
  99. }
  100. /**
  101. * set the format of the report: "html", "text", or "xml"
  102. */
  103. public void setFormat(ReportFormat value) {
  104. this.format = value.getValue();
  105. }
  106. public static class ReportType extends EnumeratedAttribute {
  107. public String[] getValues() {
  108. return new String[]{"executive", "summary", "detailed", "verydetailed"};
  109. }
  110. }
  111. /**
  112. * The type of report to be generated: "executive", "summary",
  113. * "detailed" or "verydetailed".
  114. */
  115. public void setType(ReportType value) {
  116. this.type = value.getValue();
  117. }
  118. /**
  119. * If true, include text of the source code lines.
  120. * Only applies to format="xml" and type="verydetailed"
  121. */
  122. public void setIncludesource(boolean value) {
  123. this.includeSource = value;
  124. }
  125. /**
  126. * A numeric value for the threshold for printing methods.
  127. * Must be between 0 and 100.
  128. */
  129. public void setPercent(Integer value) {
  130. this.percent = value;
  131. }
  132. /**
  133. * set the filters
  134. * @ant.attribute ignore="true"
  135. */
  136. public void setFilters(String values) {
  137. this.filters = values;
  138. }
  139. /**
  140. * Adds a path to source files.
  141. */
  142. public Path createSourcepath() {
  143. if (sourcePath == null) {
  144. sourcePath = new Path(getProject());
  145. }
  146. return sourcePath.createPath();
  147. }
  148. /**
  149. * The name of the snapshot file that is the source to the report.
  150. */
  151. public void setSnapshot(File value) {
  152. this.snapshot = value;
  153. }
  154. /**
  155. * The name of the generated output file.
  156. */
  157. public void setTofile(File value) {
  158. this.tofile = value;
  159. }
  160. /**
  161. * @todo needs to be removed
  162. * @ant.element ignore="true"
  163. */
  164. public Path createCoveragepath() {
  165. if (coveragePath == null) {
  166. coveragePath = new Path(getProject());
  167. }
  168. return coveragePath.createPath();
  169. }
  170. /**
  171. * Adds a set of classes whose coverage information will be
  172. * checked against.
  173. */
  174. public Reference createReference() {
  175. if (reference == null) {
  176. reference = new Reference();
  177. }
  178. return reference;
  179. }
  180. public CovReport() {
  181. }
  182. /** check for mandatory options */
  183. protected void checkOptions() throws BuildException {
  184. if (tofile == null) {
  185. throw new BuildException("'tofile' attribute must be set.");
  186. }
  187. if (snapshot == null) {
  188. throw new BuildException("'snapshot' attribute must be set.");
  189. }
  190. if (getHome() == null) {
  191. throw new BuildException("'home' attribute must be set to JProbe home directory");
  192. }
  193. File jar = findCoverageJar();
  194. if (!jar.exists()) {
  195. throw new BuildException("Cannot find Coverage directory: " + getHome());
  196. }
  197. if (reference != null && !"xml".equals(format)) {
  198. log("Ignored reference. It cannot be used in non XML report.");
  199. reference = null; // nullify it so that there is no ambiguity
  200. }
  201. }
  202. public void execute() throws BuildException {
  203. checkOptions();
  204. try {
  205. Commandline cmdl = new Commandline();
  206. // we need to run Coverage from his directory due to dll/jar issues
  207. cmdl.setExecutable(findExecutable("jpcovreport"));
  208. String[] params = getParameters();
  209. for (int i = 0; i < params.length; i++) {
  210. cmdl.createArgument().setValue(params[i]);
  211. }
  212. // use the custom handler for stdin issues
  213. LogStreamHandler handler
  214. = new LogStreamHandler(this, Project.MSG_INFO, Project.MSG_WARN);
  215. Execute exec = new Execute(handler);
  216. log(cmdl.describeCommand(), Project.MSG_VERBOSE);
  217. exec.setCommandline(cmdl.getCommandline());
  218. int exitValue = exec.execute();
  219. if (Execute.isFailure(exitValue)) {
  220. throw new BuildException("JProbe Coverage Report failed ("
  221. + exitValue + ")");
  222. }
  223. log("coveragePath: " + coveragePath, Project.MSG_VERBOSE);
  224. log("format: " + format, Project.MSG_VERBOSE);
  225. if (reference != null && "xml".equals(format)) {
  226. reference.createEnhancedXMLReport();
  227. }
  228. } catch (IOException e) {
  229. throw new BuildException("Failed to execute JProbe Coverage Report.", e);
  230. }
  231. }
  232. protected String[] getParameters() {
  233. Vector v = new Vector();
  234. if (format != null) {
  235. v.addElement("-format=" + format);
  236. }
  237. if (type != null) {
  238. v.addElement("-type=" + type);
  239. }
  240. if (percent != null) {
  241. v.addElement("-percent=" + percent);
  242. }
  243. if (filters != null) {
  244. v.addElement("-filters=" + filters);
  245. }
  246. v.addElement("-output=" + getProject().resolveFile(tofile.getPath()));
  247. v.addElement("-snapshot=" + getProject().resolveFile(snapshot.getPath()));
  248. // as a default -sourcepath use . in JProbe, so use project .
  249. if (sourcePath == null) {
  250. sourcePath = new Path(getProject());
  251. sourcePath.createPath().setLocation(getProject().resolveFile("."));
  252. }
  253. v.addElement("-sourcepath=" + sourcePath);
  254. if ("verydetailed".equalsIgnoreCase(format) && "xml".equalsIgnoreCase(type)) {
  255. v.addElement("-inc_src_text=" + (includeSource ? "on" : "off"));
  256. }
  257. String[] params = new String[v.size()];
  258. v.copyInto(params);
  259. return params;
  260. }
  261. public class Reference {
  262. protected Path classPath;
  263. protected ReportFilters filters;
  264. public Path createClasspath() {
  265. if (classPath == null) {
  266. classPath = new Path(CovReport.this.getProject());
  267. }
  268. return classPath.createPath();
  269. }
  270. public ReportFilters createFilters() {
  271. if (filters == null) {
  272. filters = new ReportFilters();
  273. }
  274. return filters;
  275. }
  276. protected void createEnhancedXMLReport() throws BuildException {
  277. // we need a classpath element
  278. if (classPath == null) {
  279. throw new BuildException("Need a 'classpath' element.");
  280. }
  281. // and a valid one...
  282. String[] paths = classPath.list();
  283. if (paths.length == 0) {
  284. throw new BuildException("Coverage path is invalid. It does not contain any existing path.");
  285. }
  286. // and we need at least one filter include/exclude.
  287. if (filters == null || filters.size() == 0) {
  288. createFilters();
  289. log("Adding default include filter to *.*()", Project.MSG_VERBOSE);
  290. ReportFilters.Include include = new ReportFilters.Include();
  291. filters.addInclude(include);
  292. }
  293. try {
  294. log("Creating enhanced XML report", Project.MSG_VERBOSE);
  295. XMLReport report = new XMLReport(CovReport.this, tofile);
  296. report.setReportFilters(filters);
  297. report.setJProbehome(new File(getHome().getParent()));
  298. Document doc = report.createDocument(paths);
  299. TransformerFactory tfactory = TransformerFactory.newInstance();
  300. Transformer transformer = tfactory.newTransformer();
  301. transformer.setOutputProperty(OutputKeys.INDENT, "yes");
  302. transformer.setOutputProperty(OutputKeys.METHOD, "xml");
  303. Source src = new DOMSource(doc);
  304. Result res = new StreamResult("file:///" + tofile.toString());
  305. transformer.transform(src, res);
  306. } catch (Exception e) {
  307. throw new BuildException("Error while performing enhanced XML "
  308. + "report from file " + tofile, e);
  309. }
  310. }
  311. }
  312. }