~ubuntu-branches/ubuntu/jaunty/ant/jaunty-proposed

« back to all changes in this revision

Viewing changes to src/main/org/apache/tools/ant/taskdefs/optional/jdepend/JDependTask.java

  • Committer: Bazaar Package Importer
  • Author(s): Stefan Gybas
  • Date: 2002-02-14 14:28:48 UTC
  • Revision ID: james.westby@ubuntu.com-20020214142848-2ww7ynmqkj31vlmn
Tags: upstream-1.4.1
ImportĀ upstreamĀ versionĀ 1.4.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * The Apache Software License, Version 1.1
 
3
 *
 
4
 * Copyright (c) 2000 The Apache Software Foundation.  All rights
 
5
 * reserved.
 
6
 *
 
7
 * Redistribution and use in source and binary forms, with or without
 
8
 * modification, are permitted provided that the following conditions
 
9
 * are met:
 
10
 *
 
11
 * 1. Redistributions of source code must retain the above copyright
 
12
 *    notice, this list of conditions and the following disclaimer.
 
13
 *
 
14
 * 2. Redistributions in binary form must reproduce the above copyright
 
15
 *    notice, this list of conditions and the following disclaimer in
 
16
 *    the documentation and/or other materials provided with the
 
17
 *    distribution.
 
18
 *
 
19
 * 3. The end-user documentation included with the redistribution, if
 
20
 *    any, must include the following acknowlegement:
 
21
 *       "This product includes software developed by the
 
22
 *        Apache Software Foundation (http://www.apache.org/)."
 
23
 *    Alternately, this acknowlegement may appear in the software itself,
 
24
 *    if and wherever such third-party acknowlegements normally appear.
 
25
 *
 
26
 * 4. The names "The Jakarta Project", "Ant", and "Apache Software
 
27
 *    Foundation" must not be used to endorse or promote products derived
 
28
 *    from this software without prior written permission. For written
 
29
 *    permission, please contact apache@apache.org.
 
30
 *
 
31
 * 5. Products derived from this software may not be called "Apache"
 
32
 *    nor may "Apache" appear in their names without prior written
 
33
 *    permission of the Apache Group.
 
34
 *
 
35
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 
36
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 
37
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
38
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 
39
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
40
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
41
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 
42
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 
43
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 
44
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 
45
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
46
 * SUCH DAMAGE.
 
47
 * ====================================================================
 
48
 *
 
49
 * This software consists of voluntary contributions made by many
 
50
 * individuals on behalf of the Apache Software Foundation.  For more
 
51
 * information on the Apache Software Foundation, please see
 
52
 * <http://www.apache.org/>.
 
53
 */
 
54
 
 
55
package org.apache.tools.ant.taskdefs.optional.jdepend;
 
56
 
 
57
import java.io.File;
 
58
import java.io.FileWriter;
 
59
import java.io.IOException;
 
60
import java.io.PrintWriter;
 
61
import java.util.Enumeration;
 
62
import java.util.Vector;
 
63
import org.apache.tools.ant.BuildException;
 
64
import org.apache.tools.ant.PathTokenizer;
 
65
import org.apache.tools.ant.Project;
 
66
import org.apache.tools.ant.Task;
 
67
import org.apache.tools.ant.taskdefs.Execute;
 
68
import org.apache.tools.ant.taskdefs.ExecuteWatchdog;
 
69
import org.apache.tools.ant.taskdefs.LogStreamHandler;
 
70
import org.apache.tools.ant.types.Commandline;
 
71
import org.apache.tools.ant.types.CommandlineJava;
 
72
import org.apache.tools.ant.types.Path;
 
73
import org.apache.tools.ant.types.Reference;
 
74
 
 
75
/**
 
76
 * Ant task to run JDepend tests.
 
77
 *
 
78
 * <p>JDepend is a tool to generate design quality metrics for each Java package.
 
79
 * It has been initially created by Mike Clark. JDepend can be found at <a
 
80
 * href="http://www.clarkware.com/software/JDepend.html">http://www.clarkware.com/software/JDepend.html</a>.
 
81
 *
 
82
 * The current implementation spawn a new Java VM.
 
83
 *
 
84
 * @author <a href="mailto:Jerome@jeromelacoste.com">Jerome Lacoste</a>
 
85
 */
 
86
public class JDependTask extends Task {
 
87
    private CommandlineJava commandline = new CommandlineJava();       
 
88
        
 
89
    // required attributes
 
90
    private Path _sourcesPath;
 
91
 
 
92
    // optional attributes
 
93
    private File _outputFile;
 
94
    private File _dir;
 
95
    private Path _compileClasspath;
 
96
    private boolean _haltonerror = false;
 
97
    private boolean _fork = false;    
 
98
    //private Integer _timeout = null;
 
99
    
 
100
    public JDependTask() {
 
101
        commandline.setClassname("jdepend.textui.JDepend");
 
102
    }
 
103
 
 
104
/*
 
105
    public void setTimeout(Integer value) {
 
106
        _timeout = value;
 
107
    }
 
108
    
 
109
    public Integer getTimeout() {
 
110
        return _timeout;
 
111
    }
 
112
*/
 
113
    
 
114
    public void setOutputFile(File outputFile) {
 
115
        _outputFile = outputFile;
 
116
    }
 
117
 
 
118
    public File getOutputFile() {
 
119
        return _outputFile;
 
120
    }
 
121
 
 
122
    /**
 
123
     * Halt on Failure? default: false.
 
124
     */
 
125
    public void setHaltonerror(boolean value) {
 
126
        _haltonerror = value;
 
127
    }
 
128
 
 
129
    public boolean getHaltonerror() {
 
130
        return _haltonerror;
 
131
    }
 
132
 
 
133
    /**
 
134
     * Tells whether a JVM should be forked for the task. Default: false.
 
135
     * @param   value   <tt>true</tt> if a JVM should be forked, otherwise <tt>false<tt>
 
136
     */
 
137
    public void setFork(boolean value) {    
 
138
        _fork = value;            
 
139
    }    
 
140
 
 
141
    public boolean getFork() {
 
142
        return _fork;
 
143
    }
 
144
 
 
145
    /**
 
146
     * Set a new VM to execute the task. Default is <tt>java</tt>. Ignored if no JVM is forked.
 
147
     * @param   value   the new VM to use instead of <tt>java</tt>
 
148
     * @see #setFork(boolean)
 
149
     */
 
150
    public void setJvm(String value) {
 
151
        commandline.setVm(value);
 
152
    }
 
153
    
 
154
    /**
 
155
     * Maybe creates a nested classpath element.
 
156
     */
 
157
    public Path createSourcespath() {
 
158
        if (_sourcesPath == null) {
 
159
            _sourcesPath = new Path(project);
 
160
        }
 
161
        return _sourcesPath.createPath();
 
162
    }
 
163
 
 
164
    /** Gets the sourcepath. */
 
165
    public Path getSourcespath() {
 
166
        return _sourcesPath;
 
167
    }
 
168
 
 
169
    /**
 
170
     * The directory to invoke the VM in. Ignored if no JVM is forked.
 
171
     * @param   dir     the directory to invoke the JVM from.
 
172
     * @see #setFork(boolean)
 
173
     */
 
174
    public void setDir(File dir) {
 
175
        _dir = dir;
 
176
    }
 
177
 
 
178
    public File getDir() {
 
179
        return _dir;
 
180
    }
 
181
 
 
182
    /**
 
183
     * Set the classpath to be used for this compilation.
 
184
     */
 
185
    public void setClasspath(Path classpath) {
 
186
        if (_compileClasspath == null) {
 
187
            _compileClasspath = classpath;
 
188
        } else {
 
189
            _compileClasspath.append(classpath);
 
190
        }
 
191
    }
 
192
 
 
193
    /** Gets the classpath to be used for this compilation. */
 
194
    public Path getClasspath() {
 
195
        return _compileClasspath;
 
196
    }
 
197
 
 
198
    /**
 
199
     * Maybe creates a nested classpath element.
 
200
     */
 
201
    public Path createClasspath() {
 
202
        if (_compileClasspath == null) {
 
203
            _compileClasspath = new Path(project);
 
204
        }
 
205
        return _compileClasspath.createPath();
 
206
    }
 
207
 
 
208
    /**
 
209
     * Create a new JVM argument. Ignored if no JVM is forked.
 
210
     * @return  create a new JVM argument so that any argument can be passed to the JVM.
 
211
     * @see #setFork(boolean)
 
212
     */
 
213
    public Commandline.Argument createJvmarg() {
 
214
        return commandline.createVmArgument();
 
215
    }
 
216
 
 
217
    /**
 
218
     * Adds a reference to a CLASSPATH defined elsewhere.
 
219
     */
 
220
    public void setClasspathRef(Reference r) {
 
221
        createClasspath().setRefid(r);
 
222
    }
 
223
 
 
224
    /**
 
225
     * No problems with this test.
 
226
     */
 
227
    private static final int SUCCESS = 0;    
 
228
    /**
 
229
     * An error occured.
 
230
     */    
 
231
    private static final int ERRORS = 1;
 
232
    
 
233
    public void execute() throws BuildException {
 
234
        if (getSourcespath() == null)
 
235
            throw new BuildException("Missing Sourcepath required argument");
 
236
            
 
237
        // execute the test and get the return code
 
238
        int exitValue = JDependTask.ERRORS;
 
239
        boolean wasKilled = false;
 
240
        if (! getFork()) {
 
241
            exitValue = executeInVM();
 
242
        } else {
 
243
            ExecuteWatchdog watchdog = createWatchdog();                
 
244
            exitValue = executeAsForked(watchdog);
 
245
            // null watchdog means no timeout, you'd better not check with null
 
246
            if (watchdog != null) {
 
247
                //info will be used in later version do nothing for now
 
248
                //wasKilled = watchdog.killedProcess();
 
249
            }
 
250
        }
 
251
 
 
252
        // if there is an error/failure and that it should halt, stop everything otherwise
 
253
        // just log a statement
 
254
        boolean errorOccurred = exitValue == JDependTask.ERRORS;
 
255
 
 
256
        if (errorOccurred) {
 
257
            if  (getHaltonerror())
 
258
                throw new BuildException("JDepend failed",
 
259
                                         location);
 
260
            else
 
261
                log("JDepend FAILED", Project.MSG_ERR);
 
262
        }
 
263
    }        
 
264
 
 
265
 
 
266
            
 
267
    // this comment extract from JUnit Task may also apply here
 
268
    // "in VM is not very nice since it could probably hang the
 
269
    // whole build. IMHO this method should be avoided and it would be best
 
270
    // to remove it in future versions. TBD. (SBa)"    
 
271
        
 
272
    /**
 
273
     * Execute inside VM.
 
274
     */
 
275
    public int executeInVM() throws BuildException {
 
276
        jdepend.textui.JDepend jdepend = new jdepend.textui.JDepend();
 
277
       
 
278
        if (getOutputFile() != null) {
 
279
            FileWriter fw;
 
280
            try {
 
281
                fw = new FileWriter(getOutputFile().getPath());
 
282
            }
 
283
            catch (IOException e) {
 
284
                String msg = "JDepend Failed when creating the output file: " + e.getMessage();
 
285
                log(msg);
 
286
                throw new BuildException(msg);
 
287
            }
 
288
            jdepend.setWriter(new PrintWriter(fw));
 
289
            log("Ouptut to be stored in " + getOutputFile().getPath());
 
290
        }
 
291
 
 
292
        PathTokenizer sourcesPath = new PathTokenizer(getSourcespath().toString());
 
293
        while (sourcesPath.hasMoreTokens()) {
 
294
            File f = new File(sourcesPath.nextToken());
 
295
            
 
296
            // not necessary as JDepend would fail, but why loose some time?                    
 
297
            if (! f.exists() || !f.isDirectory()) {
 
298
                String msg = "\""+ f.getPath() + "\" does not represent a valid directory. JDepend would fail.";
 
299
                log(msg);
 
300
                throw new BuildException(msg);
 
301
            }
 
302
            try {                  
 
303
                jdepend.addDirectory(f.getPath());                  
 
304
            }
 
305
            catch (IOException e) {
 
306
                String msg = "JDepend Failed when adding a source directory: " + e.getMessage();
 
307
                log(msg);
 
308
                throw new BuildException(msg);
 
309
            }
 
310
        }
 
311
        jdepend.analyze();
 
312
        return SUCCESS;
 
313
    }
 
314
    
 
315
 
 
316
    /**
 
317
     * Execute the task by forking a new JVM. The command will block until
 
318
     * it finishes. To know if the process was destroyed or not, use the
 
319
     * <tt>killedProcess()</tt> method of the watchdog class.
 
320
     * @param  watchdog   the watchdog in charge of cancelling the test if it
 
321
     * exceeds a certain amount of time. Can be <tt>null</tt>, in this case
 
322
     * the test could probably hang forever.
 
323
     */
 
324
    // JL: comment extracted from JUnitTask (and slightly modified)
 
325
    public int executeAsForked(ExecuteWatchdog watchdog) throws BuildException {      
 
326
        // if not set, auto-create the ClassPath from the project
 
327
        createClasspath();
 
328
 
 
329
        // not sure whether this test is needed but cost nothing to put.
 
330
        // hope it will be reviewed by anybody competent
 
331
        if (getClasspath().toString().length() > 0) {
 
332
            createJvmarg().setValue("-classpath");
 
333
            createJvmarg().setValue(getClasspath().toString());
 
334
        }
 
335
 
 
336
        if (getOutputFile() != null) {
 
337
            // having a space between the file and its path causes commandline to add quotes "
 
338
            // around the argument thus making JDepend not taking it into account. Thus we split it in two
 
339
            commandline.createArgument().setValue("-file");
 
340
            commandline.createArgument().setValue(_outputFile.getPath());
 
341
            // we have to find a cleaner way to put this output
 
342
        }
 
343
 
 
344
        PathTokenizer sourcesPath = new PathTokenizer(getSourcespath().toString());
 
345
        while (sourcesPath.hasMoreTokens()) {
 
346
            File f = new File(sourcesPath.nextToken());
 
347
            
 
348
            // not necessary as JDepend would fail, but why loose some time?
 
349
            if (! f.exists() || !f.isDirectory())
 
350
                throw new BuildException("\""+ f.getPath() + "\" does not represent a valid directory. JDepend would fail.");
 
351
            commandline.createArgument().setValue(f.getPath());
 
352
        }
 
353
        
 
354
        Execute execute = new Execute(new LogStreamHandler(this, Project.MSG_INFO, Project.MSG_WARN), watchdog);        
 
355
        execute.setCommandline(commandline.getCommandline());
 
356
        if (getDir() != null) {
 
357
            execute.setWorkingDirectory(getDir());
 
358
            execute.setAntRun(project);
 
359
        }
 
360
 
 
361
        if (getOutputFile() != null) 
 
362
            log("Ouptut to be stored in " + getOutputFile().getPath());
 
363
        log("Executing: "+commandline.toString(), Project.MSG_VERBOSE);
 
364
        try {
 
365
            return execute.execute();
 
366
        } catch (IOException e) {
 
367
            throw new BuildException("Process fork failed.", e, location);
 
368
        }
 
369
    }
 
370
 
 
371
    /**
 
372
     * @return <tt>null</tt> if there is a timeout value, otherwise the
 
373
     * watchdog instance.
 
374
     */
 
375
    protected ExecuteWatchdog createWatchdog() throws BuildException {
 
376
 
 
377
        return null;
 
378
        /*
 
379
          if (getTimeout() == null){
 
380
          return null;
 
381
          }
 
382
          return new ExecuteWatchdog(getTimeout().intValue());
 
383
        */
 
384
    }
 
385
}