1 /* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved. 2 * 3 * This program and the accompanying materials are made available under 4 * the terms of the Common Public License v1.0 which accompanies this distribution, 5 * and is available at http://www.eclipse.org/legal/cpl-v10.html 6 * 7 * $Id: emmajavaTask.java,v 1.1.1.1.2.2 2004/07/16 23:32:04 vlad_r Exp $ 8 */ 9 package com.vladium.emma; 10 11 import java.io.File; 12 13 import com.vladium.util.IProperties; 14 import com.vladium.util.Strings; 15 import com.vladium.emma.ant.*; 16 import com.vladium.emma.instr.FilterCfg; 17 import com.vladium.emma.instr.FilterCfg.filterElement; 18 import com.vladium.emma.report.ReportCfg; 19 import com.vladium.emma.report.IReportEnums.DepthAttribute; 20 import com.vladium.emma.report.IReportEnums.UnitsTypeAttribute; 21 import com.vladium.emma.report.ReportCfg.Element_HTML; 22 import com.vladium.emma.report.ReportCfg.Element_LCOV; 23 import com.vladium.emma.report.ReportCfg.Element_TXT; 24 import com.vladium.emma.report.ReportCfg.Element_XML; 25 26 import org.apache.tools.ant.BuildException; 27 import org.apache.tools.ant.Project; 28 import org.apache.tools.ant.taskdefs.Java; 29 import org.apache.tools.ant.types.Commandline; 30 import org.apache.tools.ant.types.Path; 31 import org.apache.tools.ant.types.Reference; 32 33 // ---------------------------------------------------------------------------- 34 /** 35 * @author Vlad Roubtsov, (C) 2003 36 */ 37 public 38 class emmajavaTask extends Java 39 { 40 // public: ................................................................ 41 42 init()43 public void init () throws BuildException 44 { 45 super.init (); 46 47 m_verbosityCfg = new VerbosityCfg (); 48 m_genericCfg = new GenericCfg (this); 49 m_filterCfg = new FilterCfg (this); 50 m_reportCfg = new ReportCfg (project, this); 51 setEnabled (true); 52 } 53 54 execute()55 public void execute () throws BuildException 56 { 57 log (IAppConstants.APP_VERBOSE_BUILD_ID, Project.MSG_VERBOSE); 58 59 if (getClasspath () == null) 60 throw (BuildException) SuppressableTask.newBuildException (getTaskName () 61 + ": this task requires 'classpath' attribute to be set", location).fillInStackTrace (); 62 63 64 if (isEnabled ()) 65 { 66 // fork: 67 if (m_forkUserOverride && ! m_fork) 68 log (getTaskName () + ": 'fork=\"false\"' attribute setting ignored (this task always forks)", Project.MSG_WARN); 69 70 super.setFork (true); // always fork 71 72 // add emma libs to the parent task's classpath [to support non-extdir deployment]: 73 final Path libClasspath = m_libClasspath; 74 if ((libClasspath != null) && (libClasspath.size () > 0)) 75 { 76 super.createClasspath ().append (libClasspath); 77 } 78 79 // classname|jar (1/2): 80 super.setClassname ("emmarun"); 81 82 // <emmajava> extensions: 83 { 84 // report types: 85 { 86 String reportTypes = Strings.toListForm (m_reportCfg.getReportTypes (), ','); 87 if ((reportTypes == null) || (reportTypes.length () == 0)) reportTypes = "txt"; 88 89 super.createArg ().setValue ("-r"); 90 super.createArg ().setValue (reportTypes); 91 } 92 93 // full classpath scan flag: 94 { 95 if (m_scanCoveragePath) 96 { 97 super.createArg ().setValue ("-f"); 98 } 99 } 100 101 // dump raw data flag and options: 102 { 103 if (m_dumpSessionData) 104 { 105 super.createArg ().setValue ("-raw"); 106 107 if (m_outFile != null) 108 { 109 super.createArg ().setValue ("-out"); 110 super.createArg ().setValue (m_outFile.getAbsolutePath ()); 111 } 112 113 if (m_outFileMerge != null) 114 { 115 super.createArg ().setValue ("-merge"); 116 super.createArg ().setValue (m_outFileMerge.booleanValue () ? "y" : "n"); 117 } 118 } 119 else 120 { 121 if (m_outFile != null) 122 log (getTaskName () + ": output file attribute ignored ('fullmetadata=\"true\"' not specified)", Project.MSG_WARN); 123 124 if (m_outFileMerge != null) 125 log (getTaskName () + ": merge attribute setting ignored ('fullmetadata=\"true\"' not specified)", Project.MSG_WARN); 126 } 127 } 128 129 // instr filter: 130 { 131 final String [] specs = m_filterCfg.getFilterSpecs (); 132 if ((specs != null) && (specs.length > 0)) 133 { 134 super.createArg ().setValue ("-ix"); 135 super.createArg ().setValue (Strings.toListForm (specs, ',')); 136 } 137 } 138 139 // sourcepath: 140 { 141 final Path srcpath = m_reportCfg.getSourcepath (); 142 if (srcpath != null) 143 { 144 super.createArg ().setValue ("-sp"); 145 super.createArg ().setValue (Strings.toListForm (srcpath.list (), ',')); 146 } 147 } 148 149 // all other generic settings: 150 { 151 final IProperties reportSettings = m_reportCfg.getReportSettings (); 152 final IProperties genericSettings = m_genericCfg.getGenericSettings (); 153 154 // TODO: another options is to read this file in the forked JVM [use '-props' pass-through] 155 // the best option depends on how ANT resolves relative file names 156 final IProperties fileSettings = m_genericCfg.getFileSettings (); 157 158 // verbosity settings use dedicated attributes and hence are more specific 159 // than anything generic: 160 final IProperties verbositySettings = m_verbosityCfg.getSettings (); 161 162 // (1) file settings have lower priority than any explicitly named overrides 163 // (2) named report settings override generic named settings 164 // (3) verbosity settings use dedicated attributes (not overlapping with report 165 // cfg) and hence are more specific than anything generic 166 final IProperties settings = IProperties.Factory.combine (reportSettings, 167 IProperties.Factory.combine (verbositySettings, 168 IProperties.Factory.combine (genericSettings, 169 fileSettings))); 170 171 final String [] argForm = settings.toAppArgsForm ("-D"); 172 if (argForm.length > 0) 173 { 174 for (int a = 0; a < argForm.length; ++ a) 175 super.createArg ().setValue (argForm [a]); 176 } 177 } 178 } 179 180 // [assertion: getClasspath() is not null] 181 182 // classpath: 183 super.createArg ().setValue ("-cp"); 184 super.createArg ().setPath (getClasspath ()); 185 186 // classname|jar (2/2): 187 if (getClassname () != null) 188 super.createArg ().setValue (getClassname ()); 189 else if (getJar () != null) 190 { 191 super.createArg ().setValue ("-jar"); 192 super.createArg ().setValue (getJar ().getAbsolutePath ()); 193 } 194 else 195 throw (BuildException) SuppressableTask.newBuildException (getTaskName () 196 + "either 'jar' or 'classname' attribute must be set", location).fillInStackTrace (); 197 198 // main class args: 199 if (m_appArgs != null) 200 { 201 final String [] args = m_appArgs.getArguments (); 202 for (int a = 0; a < args.length; ++ a) 203 { 204 super.createArg ().setValue (args [a]); // note: spaces etc are escaped correctly by ANT libs 205 } 206 } 207 } 208 else 209 { 210 // fork: 211 super.setFork (m_fork); 212 213 // [assertion: getClasspath() is not null] 214 215 // classpath: 216 super.createClasspath ().append (getClasspath ()); // can't use setClasspath() for obvious reasons 217 218 // classname|jar: 219 if (getClassname () != null) 220 super.setClassname (getClassname ()); 221 else if (getJar () != null) 222 super.setJar (getJar ()); 223 else 224 throw (BuildException) SuppressableTask.newBuildException (getTaskName () 225 + "either 'jar' or 'classname' attribute must be set", location).fillInStackTrace (); 226 227 // main class args: 228 if (m_appArgs != null) 229 { 230 final String [] args = m_appArgs.getArguments (); 231 for (int a = 0; a < args.length; ++ a) 232 { 233 super.createArg ().setValue (args [a]); // note: spaces etc are escaped correctly by ANT libs 234 } 235 } 236 } 237 238 super.execute (); 239 } 240 241 242 243 // <java> overrides [ANT 1.4]: 244 setClassname(final String classname)245 public void setClassname (final String classname) 246 { 247 if (getJar () != null) 248 throw (BuildException) SuppressableTask.newBuildException (getTaskName () 249 + "'jar' and 'classname' attributes cannot be set at the same time", location).fillInStackTrace (); 250 251 m_classname = classname; 252 } 253 setJar(final File file)254 public void setJar (final File file) 255 { 256 if (getClassname () != null) 257 throw (BuildException) SuppressableTask.newBuildException (getTaskName () 258 + "'jar' and 'classname' attributes cannot be set at the same time", location).fillInStackTrace (); 259 260 m_jar = file; 261 } 262 263 setClasspath(final Path path)264 public void setClasspath (final Path path) 265 { 266 if (m_classpath == null) 267 m_classpath = path; 268 else 269 m_classpath.append (path); 270 } 271 setClasspathRef(final Reference ref)272 public void setClasspathRef (final Reference ref) 273 { 274 createClasspath ().setRefid (ref); 275 } 276 createClasspath()277 public Path createClasspath () 278 { 279 if (m_classpath == null) 280 m_classpath = new Path (project); 281 282 return m_classpath.createPath (); 283 } 284 285 /** 286 * This is already deprecated in ANT v1.4. However, it is still supported by 287 * the parent task so I do likewise. 288 */ setArgs(final String args)289 public void setArgs (final String args) 290 { 291 throw (BuildException) SuppressableTask.newBuildException (getTaskName () 292 + ": disallows using <java>'s deprecated 'args' attribute", location).fillInStackTrace (); 293 } 294 295 /** 296 * Not overridable. 297 */ setFork(final boolean fork)298 public final void setFork (final boolean fork) 299 { 300 m_fork = fork; 301 m_forkUserOverride = true; 302 } 303 304 /** 305 * Not overridable [due to limitations in ANT's Commandline]. 306 */ createArg()307 public final Commandline.Argument createArg () 308 { 309 if (m_appArgs == null) 310 m_appArgs = new Commandline (); 311 312 return m_appArgs.createArgument (); 313 } 314 315 // <java> overrides [ANT 1.5]: 316 317 // [nothing at this point] 318 319 320 // <emmajava> extensions: 321 setEnabled(final boolean enabled)322 public void setEnabled (final boolean enabled) 323 { 324 m_enabled = enabled; 325 } 326 327 // .properties file attribute: 328 setProperties(final File file)329 public final void setProperties (final File file) 330 { 331 m_genericCfg.setProperties (file); 332 } 333 334 // generic property element: 335 createProperty()336 public final PropertyElement createProperty () 337 { 338 return m_genericCfg.createProperty (); 339 } 340 341 // verbosity attribute: 342 setVerbosity(final VerbosityCfg.VerbosityAttribute verbosity)343 public void setVerbosity (final VerbosityCfg.VerbosityAttribute verbosity) 344 { 345 m_verbosityCfg.setVerbosity (verbosity); 346 } 347 348 // verbosity class filter attribute: 349 setVerbosityfilter(final String filter)350 public void setVerbosityfilter (final String filter) 351 { 352 m_verbosityCfg.setVerbosityfilter (filter); 353 } 354 355 // lib classpath attribute [to support non-extdir deployment]: 356 setLibclasspath(final Path classpath)357 public final void setLibclasspath (final Path classpath) 358 { 359 if (m_libClasspath == null) 360 m_libClasspath = classpath; 361 else 362 m_libClasspath.append (classpath); 363 } 364 setLibclasspathRef(final Reference ref)365 public final void setLibclasspathRef (final Reference ref) 366 { 367 if (m_libClasspath == null) 368 m_libClasspath = new Path (project); 369 370 m_libClasspath.createPath ().setRefid (ref); 371 } 372 373 // -f flag: 374 setFullmetadata(final boolean full)375 public void setFullmetadata (final boolean full) 376 { 377 m_scanCoveragePath = full; // defaults to false TODO: maintain the default in a central location 378 } 379 380 // -raw flag: 381 setDumpsessiondata(final boolean dump)382 public void setDumpsessiondata (final boolean dump) 383 { 384 m_dumpSessionData = dump; 385 } 386 387 // -out option: 388 389 // sessiondatafile|outfile attribute: 390 setSessiondatafile(final File file)391 public void setSessiondatafile (final File file) 392 { 393 if (m_outFile != null) 394 throw (BuildException) SuppressableTask.newBuildException (getTaskName () 395 + ": session data file attribute already set", location).fillInStackTrace (); 396 397 m_outFile = file; 398 } 399 setOutfile(final File file)400 public void setOutfile (final File file) 401 { 402 if (m_outFile != null) 403 throw (BuildException) SuppressableTask.newBuildException (getTaskName () 404 + ": session data file attribute already set", location).fillInStackTrace (); 405 406 m_outFile = file; 407 } 408 409 // public void setTofile (final File file) 410 // { 411 // if (m_outFile != null) 412 // throw (BuildException) SuppressableTask.newBuildException (getTaskName () 413 // + ": session data file attribute already set", location).fillInStackTrace (); 414 // 415 // m_outFile = file; 416 // } 417 // 418 // public void setFile (final File file) 419 // { 420 // if (m_outFile != null) 421 // throw (BuildException) SuppressableTask.newBuildException (getTaskName () 422 // + ": session data file attribute already set", location).fillInStackTrace (); 423 // 424 // m_outFile = file; 425 // } 426 427 428 // merge attribute: 429 setMerge(final boolean merge)430 public void setMerge (final boolean merge) 431 { 432 m_outFileMerge = merge ? Boolean.TRUE : Boolean.FALSE; 433 } 434 435 // instr filter attribute/element: 436 setFilter(final String filter)437 public final void setFilter (final String filter) 438 { 439 m_filterCfg.setFilter (filter); 440 } 441 createFilter()442 public final filterElement createFilter () 443 { 444 return m_filterCfg.createFilter (); 445 } 446 447 448 // TODO: should what's below go inside <report></report> ? 449 450 // sourcepath attribute/element: 451 setSourcepath(final Path path)452 public final void setSourcepath (final Path path) 453 { 454 m_reportCfg.setSourcepath (path); 455 } 456 setSourcepathRef(final Reference ref)457 public final void setSourcepathRef (final Reference ref) 458 { 459 m_reportCfg.setSourcepathRef (ref); 460 } 461 createSourcepath()462 public final Path createSourcepath () 463 { 464 return m_reportCfg.createSourcepath (); 465 } 466 467 468 // generator elements: 469 createTxt()470 public final Element_TXT createTxt () 471 { 472 return m_reportCfg.createTxt (); 473 } 474 createLcov()475 public final Element_LCOV createLcov () 476 { 477 return m_reportCfg.createLcov (); 478 } 479 createHtml()480 public final Element_HTML createHtml () 481 { 482 return m_reportCfg.createHtml (); 483 } 484 createXml()485 public final Element_XML createXml () 486 { 487 return m_reportCfg.createXml (); 488 } 489 490 491 // report properties [defaults for all report types]: 492 setUnits(final UnitsTypeAttribute units)493 public final void setUnits (final UnitsTypeAttribute units) 494 { 495 m_reportCfg.setUnits (units); 496 } 497 setDepth(final DepthAttribute depth)498 public final void setDepth (final DepthAttribute depth) 499 { 500 m_reportCfg.setDepth (depth); 501 } 502 setColumns(final String columns)503 public final void setColumns (final String columns) 504 { 505 m_reportCfg.setColumns (columns); 506 } 507 setSort(final String sort)508 public final void setSort (final String sort) 509 { 510 m_reportCfg.setSort (sort); 511 } 512 setMetrics(final String metrics)513 public final void setMetrics (final String metrics) 514 { 515 m_reportCfg.setMetrics (metrics); 516 } 517 518 // these are not supported anymore 519 520 // public final void setOutdir (final File dir) 521 // { 522 // m_reportCfg.setOutdir (dir); 523 // } 524 // 525 // public final void setDestdir (final File dir) 526 // { 527 // m_reportCfg.setDestdir (dir); 528 // } 529 530 // should be set at this level [and conflicts with raw data opts]: 531 532 // public void setOutfile (final String fileName) 533 // { 534 // m_reportCfg.setOutfile (fileName); 535 // } 536 setEncoding(final String encoding)537 public void setEncoding (final String encoding) 538 { 539 m_reportCfg.setEncoding (encoding); 540 } 541 542 // protected: ............................................................. 543 544 getClassname()545 protected String getClassname () 546 { 547 return m_classname; 548 } 549 getJar()550 protected File getJar () 551 { 552 return m_jar; 553 } 554 getClasspath()555 protected Path getClasspath () 556 { 557 return m_classpath; 558 } 559 560 // extended functionality: 561 isEnabled()562 protected boolean isEnabled () 563 { 564 return m_enabled; 565 } 566 567 // package: ............................................................... 568 569 // private: ............................................................... 570 571 // <java> overrides: 572 573 private Path m_classpath; 574 private String m_classname; 575 private File m_jar; 576 private Commandline m_appArgs; 577 private boolean m_fork, m_forkUserOverride; 578 579 // <emmajava> extensions: 580 581 private boolean m_enabled; 582 private Path m_libClasspath; 583 private /*final*/ VerbosityCfg m_verbosityCfg; 584 private /*final*/ GenericCfg m_genericCfg; 585 private /*final*/ FilterCfg m_filterCfg; 586 private /*final*/ ReportCfg m_reportCfg; 587 private boolean m_scanCoveragePath; // defaults to false 588 private boolean m_dumpSessionData; //defaults to false 589 private File m_outFile; 590 private Boolean m_outFileMerge; 591 592 } // end of class 593 // ---------------------------------------------------------------------------- 594