/* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved. * * This program and the accompanying materials are made available under * the terms of the Common Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/cpl-v10.html * * $Id: emmajavaTask.java,v 1.1.1.1.2.2 2004/07/16 23:32:04 vlad_r Exp $ */ package com.vladium.emma; import java.io.File; import com.vladium.util.IProperties; import com.vladium.util.Strings; import com.vladium.emma.ant.*; import com.vladium.emma.instr.FilterCfg; import com.vladium.emma.instr.FilterCfg.filterElement; import com.vladium.emma.report.ReportCfg; import com.vladium.emma.report.IReportEnums.DepthAttribute; import com.vladium.emma.report.IReportEnums.UnitsTypeAttribute; import com.vladium.emma.report.ReportCfg.Element_HTML; import com.vladium.emma.report.ReportCfg.Element_LCOV; import com.vladium.emma.report.ReportCfg.Element_TXT; import com.vladium.emma.report.ReportCfg.Element_XML; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; import org.apache.tools.ant.taskdefs.Java; import org.apache.tools.ant.types.Commandline; import org.apache.tools.ant.types.Path; import org.apache.tools.ant.types.Reference; // ---------------------------------------------------------------------------- /** * @author Vlad Roubtsov, (C) 2003 */ public class emmajavaTask extends Java { // public: ................................................................ public void init () throws BuildException { super.init (); m_verbosityCfg = new VerbosityCfg (); m_genericCfg = new GenericCfg (this); m_filterCfg = new FilterCfg (this); m_reportCfg = new ReportCfg (project, this); setEnabled (true); } public void execute () throws BuildException { log (IAppConstants.APP_VERBOSE_BUILD_ID, Project.MSG_VERBOSE); if (getClasspath () == null) throw (BuildException) SuppressableTask.newBuildException (getTaskName () + ": this task requires 'classpath' attribute to be set", location).fillInStackTrace (); if (isEnabled ()) { // fork: if (m_forkUserOverride && ! m_fork) log (getTaskName () + ": 'fork=\"false\"' attribute setting ignored (this task always forks)", Project.MSG_WARN); super.setFork (true); // always fork // add emma libs to the parent task's classpath [to support non-extdir deployment]: final Path libClasspath = m_libClasspath; if ((libClasspath != null) && (libClasspath.size () > 0)) { super.createClasspath ().append (libClasspath); } // classname|jar (1/2): super.setClassname ("emmarun"); // <emmajava> extensions: { // report types: { String reportTypes = Strings.toListForm (m_reportCfg.getReportTypes (), ','); if ((reportTypes == null) || (reportTypes.length () == 0)) reportTypes = "txt"; super.createArg ().setValue ("-r"); super.createArg ().setValue (reportTypes); } // full classpath scan flag: { if (m_scanCoveragePath) { super.createArg ().setValue ("-f"); } } // dump raw data flag and options: { if (m_dumpSessionData) { super.createArg ().setValue ("-raw"); if (m_outFile != null) { super.createArg ().setValue ("-out"); super.createArg ().setValue (m_outFile.getAbsolutePath ()); } if (m_outFileMerge != null) { super.createArg ().setValue ("-merge"); super.createArg ().setValue (m_outFileMerge.booleanValue () ? "y" : "n"); } } else { if (m_outFile != null) log (getTaskName () + ": output file attribute ignored ('fullmetadata=\"true\"' not specified)", Project.MSG_WARN); if (m_outFileMerge != null) log (getTaskName () + ": merge attribute setting ignored ('fullmetadata=\"true\"' not specified)", Project.MSG_WARN); } } // instr filter: { final String [] specs = m_filterCfg.getFilterSpecs (); if ((specs != null) && (specs.length > 0)) { super.createArg ().setValue ("-ix"); super.createArg ().setValue (Strings.toListForm (specs, ',')); } } // sourcepath: { final Path srcpath = m_reportCfg.getSourcepath (); if (srcpath != null) { super.createArg ().setValue ("-sp"); super.createArg ().setValue (Strings.toListForm (srcpath.list (), ',')); } } // all other generic settings: { final IProperties reportSettings = m_reportCfg.getReportSettings (); final IProperties genericSettings = m_genericCfg.getGenericSettings (); // TODO: another options is to read this file in the forked JVM [use '-props' pass-through] // the best option depends on how ANT resolves relative file names final IProperties fileSettings = m_genericCfg.getFileSettings (); // verbosity settings use dedicated attributes and hence are more specific // than anything generic: final IProperties verbositySettings = m_verbosityCfg.getSettings (); // (1) file settings have lower priority than any explicitly named overrides // (2) named report settings override generic named settings // (3) verbosity settings use dedicated attributes (not overlapping with report // cfg) and hence are more specific than anything generic final IProperties settings = IProperties.Factory.combine (reportSettings, IProperties.Factory.combine (verbositySettings, IProperties.Factory.combine (genericSettings, fileSettings))); final String [] argForm = settings.toAppArgsForm ("-D"); if (argForm.length > 0) { for (int a = 0; a < argForm.length; ++ a) super.createArg ().setValue (argForm [a]); } } } // [assertion: getClasspath() is not null] // classpath: super.createArg ().setValue ("-cp"); super.createArg ().setPath (getClasspath ()); // classname|jar (2/2): if (getClassname () != null) super.createArg ().setValue (getClassname ()); else if (getJar () != null) { super.createArg ().setValue ("-jar"); super.createArg ().setValue (getJar ().getAbsolutePath ()); } else throw (BuildException) SuppressableTask.newBuildException (getTaskName () + "either 'jar' or 'classname' attribute must be set", location).fillInStackTrace (); // main class args: if (m_appArgs != null) { final String [] args = m_appArgs.getArguments (); for (int a = 0; a < args.length; ++ a) { super.createArg ().setValue (args [a]); // note: spaces etc are escaped correctly by ANT libs } } } else { // fork: super.setFork (m_fork); // [assertion: getClasspath() is not null] // classpath: super.createClasspath ().append (getClasspath ()); // can't use setClasspath() for obvious reasons // classname|jar: if (getClassname () != null) super.setClassname (getClassname ()); else if (getJar () != null) super.setJar (getJar ()); else throw (BuildException) SuppressableTask.newBuildException (getTaskName () + "either 'jar' or 'classname' attribute must be set", location).fillInStackTrace (); // main class args: if (m_appArgs != null) { final String [] args = m_appArgs.getArguments (); for (int a = 0; a < args.length; ++ a) { super.createArg ().setValue (args [a]); // note: spaces etc are escaped correctly by ANT libs } } } super.execute (); } // <java> overrides [ANT 1.4]: public void setClassname (final String classname) { if (getJar () != null) throw (BuildException) SuppressableTask.newBuildException (getTaskName () + "'jar' and 'classname' attributes cannot be set at the same time", location).fillInStackTrace (); m_classname = classname; } public void setJar (final File file) { if (getClassname () != null) throw (BuildException) SuppressableTask.newBuildException (getTaskName () + "'jar' and 'classname' attributes cannot be set at the same time", location).fillInStackTrace (); m_jar = file; } public void setClasspath (final Path path) { if (m_classpath == null) m_classpath = path; else m_classpath.append (path); } public void setClasspathRef (final Reference ref) { createClasspath ().setRefid (ref); } public Path createClasspath () { if (m_classpath == null) m_classpath = new Path (project); return m_classpath.createPath (); } /** * This is already deprecated in ANT v1.4. However, it is still supported by * the parent task so I do likewise. */ public void setArgs (final String args) { throw (BuildException) SuppressableTask.newBuildException (getTaskName () + ": disallows using <java>'s deprecated 'args' attribute", location).fillInStackTrace (); } /** * Not overridable. */ public final void setFork (final boolean fork) { m_fork = fork; m_forkUserOverride = true; } /** * Not overridable [due to limitations in ANT's Commandline]. */ public final Commandline.Argument createArg () { if (m_appArgs == null) m_appArgs = new Commandline (); return m_appArgs.createArgument (); } // <java> overrides [ANT 1.5]: // [nothing at this point] // <emmajava> extensions: public void setEnabled (final boolean enabled) { m_enabled = enabled; } // .properties file attribute: public final void setProperties (final File file) { m_genericCfg.setProperties (file); } // generic property element: public final PropertyElement createProperty () { return m_genericCfg.createProperty (); } // verbosity attribute: public void setVerbosity (final VerbosityCfg.VerbosityAttribute verbosity) { m_verbosityCfg.setVerbosity (verbosity); } // verbosity class filter attribute: public void setVerbosityfilter (final String filter) { m_verbosityCfg.setVerbosityfilter (filter); } // lib classpath attribute [to support non-extdir deployment]: public final void setLibclasspath (final Path classpath) { if (m_libClasspath == null) m_libClasspath = classpath; else m_libClasspath.append (classpath); } public final void setLibclasspathRef (final Reference ref) { if (m_libClasspath == null) m_libClasspath = new Path (project); m_libClasspath.createPath ().setRefid (ref); } // -f flag: public void setFullmetadata (final boolean full) { m_scanCoveragePath = full; // defaults to false TODO: maintain the default in a central location } // -raw flag: public void setDumpsessiondata (final boolean dump) { m_dumpSessionData = dump; } // -out option: // sessiondatafile|outfile attribute: public void setSessiondatafile (final File file) { if (m_outFile != null) throw (BuildException) SuppressableTask.newBuildException (getTaskName () + ": session data file attribute already set", location).fillInStackTrace (); m_outFile = file; } public void setOutfile (final File file) { if (m_outFile != null) throw (BuildException) SuppressableTask.newBuildException (getTaskName () + ": session data file attribute already set", location).fillInStackTrace (); m_outFile = file; } // public void setTofile (final File file) // { // if (m_outFile != null) // throw (BuildException) SuppressableTask.newBuildException (getTaskName () // + ": session data file attribute already set", location).fillInStackTrace (); // // m_outFile = file; // } // // public void setFile (final File file) // { // if (m_outFile != null) // throw (BuildException) SuppressableTask.newBuildException (getTaskName () // + ": session data file attribute already set", location).fillInStackTrace (); // // m_outFile = file; // } // merge attribute: public void setMerge (final boolean merge) { m_outFileMerge = merge ? Boolean.TRUE : Boolean.FALSE; } // instr filter attribute/element: public final void setFilter (final String filter) { m_filterCfg.setFilter (filter); } public final filterElement createFilter () { return m_filterCfg.createFilter (); } // TODO: should what's below go inside <report></report> ? // sourcepath attribute/element: public final void setSourcepath (final Path path) { m_reportCfg.setSourcepath (path); } public final void setSourcepathRef (final Reference ref) { m_reportCfg.setSourcepathRef (ref); } public final Path createSourcepath () { return m_reportCfg.createSourcepath (); } // generator elements: public final Element_TXT createTxt () { return m_reportCfg.createTxt (); } public final Element_LCOV createLcov () { return m_reportCfg.createLcov (); } public final Element_HTML createHtml () { return m_reportCfg.createHtml (); } public final Element_XML createXml () { return m_reportCfg.createXml (); } // report properties [defaults for all report types]: public final void setUnits (final UnitsTypeAttribute units) { m_reportCfg.setUnits (units); } public final void setDepth (final DepthAttribute depth) { m_reportCfg.setDepth (depth); } public final void setColumns (final String columns) { m_reportCfg.setColumns (columns); } public final void setSort (final String sort) { m_reportCfg.setSort (sort); } public final void setMetrics (final String metrics) { m_reportCfg.setMetrics (metrics); } // these are not supported anymore // public final void setOutdir (final File dir) // { // m_reportCfg.setOutdir (dir); // } // // public final void setDestdir (final File dir) // { // m_reportCfg.setDestdir (dir); // } // should be set at this level [and conflicts with raw data opts]: // public void setOutfile (final String fileName) // { // m_reportCfg.setOutfile (fileName); // } public void setEncoding (final String encoding) { m_reportCfg.setEncoding (encoding); } // protected: ............................................................. protected String getClassname () { return m_classname; } protected File getJar () { return m_jar; } protected Path getClasspath () { return m_classpath; } // extended functionality: protected boolean isEnabled () { return m_enabled; } // package: ............................................................... // private: ............................................................... // <java> overrides: private Path m_classpath; private String m_classname; private File m_jar; private Commandline m_appArgs; private boolean m_fork, m_forkUserOverride; // <emmajava> extensions: private boolean m_enabled; private Path m_libClasspath; private /*final*/ VerbosityCfg m_verbosityCfg; private /*final*/ GenericCfg m_genericCfg; private /*final*/ FilterCfg m_filterCfg; private /*final*/ ReportCfg m_reportCfg; private boolean m_scanCoveragePath; // defaults to false private boolean m_dumpSessionData; //defaults to false private File m_outFile; private Boolean m_outFileMerge; } // end of class // ----------------------------------------------------------------------------