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 */
9package com.vladium.emma;
10
11import java.io.File;
12
13import com.vladium.util.IProperties;
14import com.vladium.util.Strings;
15import com.vladium.emma.ant.*;
16import com.vladium.emma.instr.FilterCfg;
17import com.vladium.emma.instr.FilterCfg.filterElement;
18import com.vladium.emma.report.ReportCfg;
19import com.vladium.emma.report.IReportEnums.DepthAttribute;
20import com.vladium.emma.report.IReportEnums.UnitsTypeAttribute;
21import com.vladium.emma.report.ReportCfg.Element_HTML;
22import com.vladium.emma.report.ReportCfg.Element_LCOV;
23import com.vladium.emma.report.ReportCfg.Element_TXT;
24import com.vladium.emma.report.ReportCfg.Element_XML;
25
26import org.apache.tools.ant.BuildException;
27import org.apache.tools.ant.Project;
28import org.apache.tools.ant.taskdefs.Java;
29import org.apache.tools.ant.types.Commandline;
30import org.apache.tools.ant.types.Path;
31import org.apache.tools.ant.types.Reference;
32
33// ----------------------------------------------------------------------------
34/**
35 * @author Vlad Roubtsov, (C) 2003
36 */
37public
38class emmajavaTask extends Java
39{
40    // public: ................................................................
41
42
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
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
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
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
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
272    public void setClasspathRef (final Reference ref)
273    {
274        createClasspath ().setRefid (ref);
275    }
276
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     */
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     */
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     */
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
322    public void setEnabled (final boolean enabled)
323    {
324        m_enabled = enabled;
325    }
326
327    // .properties file attribute:
328
329    public final void setProperties (final File file)
330    {
331        m_genericCfg.setProperties (file);
332    }
333
334    // generic property element:
335
336    public final PropertyElement createProperty ()
337    {
338        return m_genericCfg.createProperty ();
339    }
340
341    // verbosity attribute:
342
343    public void setVerbosity (final VerbosityCfg.VerbosityAttribute verbosity)
344    {
345        m_verbosityCfg.setVerbosity (verbosity);
346    }
347
348    // verbosity class filter attribute:
349
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
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
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
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
382    public void setDumpsessiondata (final boolean dump)
383    {
384        m_dumpSessionData = dump;
385    }
386
387    // -out option:
388
389    // sessiondatafile|outfile attribute:
390
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
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
430    public void setMerge (final boolean merge)
431    {
432        m_outFileMerge = merge ? Boolean.TRUE : Boolean.FALSE;
433    }
434
435    // instr filter attribute/element:
436
437    public final void setFilter (final String filter)
438    {
439        m_filterCfg.setFilter (filter);
440    }
441
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
452    public final void setSourcepath (final Path path)
453    {
454        m_reportCfg.setSourcepath (path);
455    }
456
457    public final void setSourcepathRef (final Reference ref)
458    {
459        m_reportCfg.setSourcepathRef (ref);
460    }
461
462    public final Path createSourcepath ()
463    {
464        return m_reportCfg.createSourcepath ();
465    }
466
467
468    // generator elements:
469
470    public final Element_TXT createTxt ()
471    {
472        return m_reportCfg.createTxt ();
473    }
474
475    public final Element_LCOV createLcov ()
476    {
477        return m_reportCfg.createLcov ();
478    }
479
480    public final Element_HTML createHtml ()
481    {
482        return m_reportCfg.createHtml ();
483    }
484
485    public final Element_XML createXml ()
486    {
487        return m_reportCfg.createXml ();
488    }
489
490
491    // report properties [defaults for all report types]:
492
493    public final void setUnits (final UnitsTypeAttribute units)
494    {
495        m_reportCfg.setUnits (units);
496    }
497
498    public final void setDepth (final DepthAttribute depth)
499    {
500        m_reportCfg.setDepth (depth);
501    }
502
503    public final void setColumns (final String columns)
504    {
505        m_reportCfg.setColumns (columns);
506    }
507
508    public final void setSort (final String sort)
509    {
510        m_reportCfg.setSort (sort);
511    }
512
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
537    public void setEncoding (final String encoding)
538    {
539        m_reportCfg.setEncoding (encoding);
540    }
541
542    // protected: .............................................................
543
544
545    protected String getClassname ()
546    {
547        return m_classname;
548    }
549
550    protected File getJar ()
551    {
552        return m_jar;
553    }
554
555    protected Path getClasspath ()
556    {
557        return m_classpath;
558    }
559
560    // extended functionality:
561
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