FileDocCategorySizeDatePackage
JDependTask.javaAPI DocApache Ant 1.7022963Wed Dec 13 06:16:20 GMT 2006org.apache.tools.ant.taskdefs.optional.jdepend

JDependTask

public class JDependTask extends org.apache.tools.ant.Task
Runs JDepend tests.

JDepend is a tool to generate design quality metrics for each Java package. It has been initially created by Mike Clark. JDepend can be found at http://www.clarkware.com/software/JDepend.html. The current implementation spawn a new Java VM.

Fields Summary
private org.apache.tools.ant.types.Path
sourcesPath
private org.apache.tools.ant.types.Path
classesPath
private File
outputFile
private File
dir
private org.apache.tools.ant.types.Path
compileClasspath
private boolean
haltonerror
private boolean
fork
private Long
timeout
private String
jvm
private String
format
private org.apache.tools.ant.types.PatternSet
defaultPatterns
private static Constructor
packageFilterC
private static Method
setFilter
private boolean
includeRuntime
private org.apache.tools.ant.types.Path
runtimeClasses
private static final int
SUCCESS
No problems with this test.
private static final int
ERRORS
An error occurred.
Constructors Summary
Methods Summary
private voidaddClasspathEntry(java.lang.String resource)
Search for the given resource and add the directory or archive that contains it to the classpath.

Doesn't work for archives in JDK 1.1 as the URL returned by getResource doesn't contain the name of the archive.

param
resource resource that one wants to lookup
since
Ant 1.6


                                                         
        
        /*
         * pre Ant 1.6 this method used to call getClass().getResource
         * while Ant 1.6 will call ClassLoader.getResource().
         *
         * The difference is that Class.getResource expects a leading
         * slash for "absolute" resources and will strip it before
         * delegating to ClassLoader.getResource - so we now have to
         * emulate Class's behavior.
         */
        if (resource.startsWith("/")) {
            resource = resource.substring(1);
        } else {
            resource = "org/apache/tools/ant/taskdefs/optional/jdepend/"
                + resource;
        }

        File f = LoaderUtils.getResourceSource(getClass().getClassLoader(),
                                               resource);
        if (f != null) {
            log("Found " + f.getAbsolutePath(), Project.MSG_DEBUG);
            runtimeClasses.createPath().setLocation(f);
        } else {
            log("Couldn\'t find " + resource, Project.MSG_DEBUG);
        }
    
public org.apache.tools.ant.types.PathcreateClassespath()
Adds a path to class code to analyze.

return
a classes path

        if (classesPath == null) {
            classesPath = new Path(getProject());
        }
        return classesPath.createPath();
    
public org.apache.tools.ant.types.PathcreateClasspath()
Adds a path to the classpath.

return
a classpath

        if (compileClasspath == null) {
            compileClasspath = new Path(getProject());
        }
        return compileClasspath.createPath();
    
public PatternSet.NameEntrycreateExclude()
add a name entry on the exclude list

return
a pattern for the excludes

        return defaultPatterns.createExclude();
    
public Commandline.ArgumentcreateJvmarg(org.apache.tools.ant.types.CommandlineJava commandline)
Create a new JVM argument. Ignored if no JVM is forked.

param
commandline the commandline to create the argument on
return
create a new JVM argument so that any argument can be passed to the JVM.
see
#setFork(boolean)

        return commandline.createVmArgument();
    
public org.apache.tools.ant.types.PathcreateSourcespath()
Adds a path to source code to analyze.

return
a source path
deprecated
since 1.6.x.

        if (sourcesPath == null) {
            sourcesPath = new Path(getProject());
        }
        return sourcesPath.createPath();
    
protected org.apache.tools.ant.taskdefs.ExecuteWatchdogcreateWatchdog()

return
null if there is a timeout value, otherwise the watchdog instance.
throws
BuildException in case of error

        if (getTimeout() == null) {
            return null;
        }
        return new ExecuteWatchdog(getTimeout().longValue());
    
public voidexecute()
execute the task

exception
BuildException if an error occurs


        CommandlineJava commandline = new CommandlineJava();

        if ("text".equals(format)) {
            commandline.setClassname("jdepend.textui.JDepend");
        } else
            if ("xml".equals(format)) {
                commandline.setClassname("jdepend.xmlui.JDepend");
            }

        if (jvm != null) {
            commandline.setVm(jvm);
        }
        if (getSourcespath() == null && getClassespath() == null) {
            throw new BuildException("Missing classespath required argument");
        } else if (getClassespath() == null) {
            String msg =
                "sourcespath is deprecated in JDepend >= 2.5 "
                + "- please convert to classespath";
            log(msg);
        }

        // execute the test and get the return code
        int exitValue = JDependTask.ERRORS;
        boolean wasKilled = false;
        if (!getFork()) {
            exitValue = executeInVM(commandline);
        } else {
            ExecuteWatchdog watchdog = createWatchdog();
            exitValue = executeAsForked(commandline, watchdog);
            // null watchdog means no timeout, you'd better not check with null
            if (watchdog != null) {
                wasKilled = watchdog.killedProcess();
            }
        }

        // if there is an error/failure and that it should halt, stop
        // everything otherwise just log a statement
        boolean errorOccurred = exitValue == JDependTask.ERRORS || wasKilled;

        if (errorOccurred) {
            String errorMessage = "JDepend FAILED"
                + (wasKilled ? " - Timed out" : "");

            if  (getHaltonerror()) {
                throw new BuildException(errorMessage, getLocation());
            } else {
                log(errorMessage, Project.MSG_ERR);
            }
        }
    
public intexecuteAsForked(org.apache.tools.ant.types.CommandlineJava commandline, org.apache.tools.ant.taskdefs.ExecuteWatchdog watchdog)
Execute the task by forking a new JVM. The command will block until it finishes. To know if the process was destroyed or not, use the killedProcess() method of the watchdog class.

param
commandline the commandline for forked jvm
param
watchdog the watchdog in charge of cancelling the test if it exceeds a certain amount of time. Can be null.
return
the result of running the jdepend
throws
BuildException in case of error

        runtimeClasses = new Path(getProject());
        addClasspathEntry("/jdepend/textui/JDepend.class");

        // if not set, auto-create the ClassPath from the project
        createClasspath();

        // not sure whether this test is needed but cost nothing to put.
        // hope it will be reviewed by anybody competent
        if (getClasspath().toString().length() > 0) {
            createJvmarg(commandline).setValue("-classpath");
            createJvmarg(commandline).setValue(getClasspath().toString());
        }

        if (includeRuntime) {
            Vector v = Execute.getProcEnvironment();
            Enumeration e = v.elements();
            while (e.hasMoreElements()) {
                String s = (String) e.nextElement();
                if (s.startsWith("CLASSPATH=")) {
                    commandline.createClasspath(getProject()).createPath()
                        .append(new Path(getProject(),
                                         s.substring("CLASSPATH=".length()
                                                     )));
                }
            }
            log("Implicitly adding " + runtimeClasses + " to CLASSPATH",
                Project.MSG_VERBOSE);
            commandline.createClasspath(getProject()).createPath()
                .append(runtimeClasses);
        }

        if (getOutputFile() != null) {
            // having a space between the file and its path causes commandline
            // to add quotes around the argument thus making JDepend not taking
            // it into account. Thus we split it in two
            commandline.createArgument().setValue("-file");
            commandline.createArgument().setValue(outputFile.getPath());
            // we have to find a cleaner way to put this output
        }

        if (getSourcespath() != null) {
            // This is deprecated - use classespath in the future
            String[] sP = getSourcespath().list();
            for (int i = 0; i < sP.length; i++) {
                File f = new File(sP[i]);

                // not necessary as JDepend would fail, but why loose
                // some time?
                if (!f.exists() || !f.isDirectory()) {
                    throw new BuildException("\"" + f.getPath()
                                             + "\" does not represent a valid"
                                             + " directory. JDepend would"
                                             + " fail.");
                }
                commandline.createArgument().setValue(f.getPath());
            }
        }

        if (getClassespath() != null) {
            // This is the new way - use classespath - code is the
            // same for now
            String[] cP = getClassespath().list();
            for (int i = 0; i < cP.length; i++) {
                File f = new File(cP[i]);
                // not necessary as JDepend would fail, but why loose
                // some time?
                if (!f.exists()) {
                    throw new BuildException("\"" + f.getPath()
                                             + "\" does not represent a valid"
                                             + " file or directory. JDepend would"
                                             + " fail.");
                }
                commandline.createArgument().setValue(f.getPath());
            }
        }

        Execute execute = new Execute(new LogStreamHandler(this,
            Project.MSG_INFO, Project.MSG_WARN), watchdog);
        execute.setCommandline(commandline.getCommandline());
        if (getDir() != null) {
            execute.setWorkingDirectory(getDir());
            execute.setAntRun(getProject());
        }

        if (getOutputFile() != null) {
            log("Output to be stored in " + getOutputFile().getPath());
        }
        log(commandline.describeCommand(), Project.MSG_VERBOSE);
        try {
            return execute.execute();
        } catch (IOException e) {
            throw new BuildException("Process fork failed.", e, getLocation());
        }
    
public intexecuteInVM(org.apache.tools.ant.types.CommandlineJava commandline)
Execute inside VM.

param
commandline the command line
return
the return value of the mvm
exception
BuildException if an error occurs

        jdepend.textui.JDepend jdepend;

        if ("xml".equals(format)) {
            jdepend = new jdepend.xmlui.JDepend();
        } else {
            jdepend = new jdepend.textui.JDepend();
        }

        FileWriter fw = null;
        if (getOutputFile() != null) {
            try {
                fw = new FileWriter(getOutputFile().getPath());
            } catch (IOException e) {
                String msg = "JDepend Failed when creating the output file: "
                    + e.getMessage();
                log(msg);
                throw new BuildException(msg);
            }
            jdepend.setWriter(new PrintWriter(fw));
            log("Output to be stored in " + getOutputFile().getPath());
        }


        try {
            if (getClassespath() != null) {
                // This is the new, better way - use classespath instead
                // of sourcespath.  The code is currently the same - you
                // need class files in a directory to use this or jar files.
                String[] cP = getClassespath().list();
                for (int i = 0; i < cP.length; i++) {
                    File f = new File(cP[i]);
                    // not necessary as JDepend would fail, but why loose
                    // some time?
                    if (!f.exists()) {
                        String msg = "\""
                            + f.getPath()
                            + "\" does not represent a valid"
                            + " file or directory. JDepend would fail.";
                        log(msg);
                        throw new BuildException(msg);
                    }
                    try {
                        jdepend.addDirectory(f.getPath());
                    } catch (IOException e) {
                        String msg =
                            "JDepend Failed when adding a class directory: "
                            + e.getMessage();
                        log(msg);
                        throw new BuildException(msg);
                    }
                }

            } else if (getSourcespath() != null) {

                // This is the old way and is deprecated - classespath is
                // the right way to do this and is above
                String[] sP = getSourcespath().list();
                for (int i = 0; i < sP.length; i++) {
                    File f = new File(sP[i]);

                    // not necessary as JDepend would fail, but why loose
                    // some time?
                    if (!f.exists() || !f.isDirectory()) {
                        String msg = "\""
                            + f.getPath()
                            + "\" does not represent a valid"
                            + " directory. JDepend would fail.";
                        log(msg);
                        throw new BuildException(msg);
                    }
                    try {
                        jdepend.addDirectory(f.getPath());
                    } catch (IOException e) {
                        String msg =
                            "JDepend Failed when adding a source directory: "
                            + e.getMessage();
                        log(msg);
                        throw new BuildException(msg);
                    }
                }
            }

            // This bit turns <exclude> child tags into patters to ignore
            String[] patterns = defaultPatterns.getExcludePatterns(getProject());
            if (patterns != null && patterns.length > 0) {
                if (setFilter != null) {
                    Vector v = new Vector();
                    for (int i = 0; i < patterns.length; i++) {
                        v.addElement(patterns[i]);
                    }
                    try {
                        Object o = packageFilterC.newInstance(new Object[] {v});
                        setFilter.invoke(jdepend, new Object[] {o});
                    } catch (Throwable e) {
                        log("excludes will be ignored as JDepend doesn't like me: "
                            + e.getMessage(), Project.MSG_WARN);
                    }
                } else {
                    log("Sorry, your version of JDepend doesn't support excludes",
                        Project.MSG_WARN);
                }
            }

            jdepend.analyze();
        } finally {
            FileUtils.close(fw);
        }
        return SUCCESS;
    
public org.apache.tools.ant.types.PathgetClassespath()
Gets the classespath.

return
the classes path

        return classesPath;
    
public org.apache.tools.ant.types.PathgetClasspath()
Gets the classpath to be used for this compilation.

return
the class path used for compilation

        return compileClasspath;
    
public java.io.FilegetDir()

return
the dir attribute

        return dir;
    
public org.apache.tools.ant.types.PatternSetgetExcludes()

return
the excludes patterns

        return defaultPatterns;
    
public booleangetFork()

return
the value of the fork attribute

        return fork;
    
public booleangetHaltonerror()

return
the value of the haltonerror attribute

        return haltonerror;
    
public java.io.FilegetOutputFile()

return
the output file name

        return outputFile;
    
public org.apache.tools.ant.types.PathgetSourcespath()
Gets the sourcepath.

return
the sources path
deprecated
since 1.6.x.

        return sourcesPath;
    
public java.lang.LonggetTimeout()

return
the timeout value

        return timeout;
    
public voidsetClasspath(org.apache.tools.ant.types.Path classpath)
Set the classpath to be used for this compilation.

param
classpath a class path to be used

        if (compileClasspath == null) {
            compileClasspath = classpath;
        } else {
            compileClasspath.append(classpath);
        }
    
public voidsetClasspathRef(org.apache.tools.ant.types.Reference r)
Adds a reference to a classpath defined elsewhere.

param
r a classpath reference

        createClasspath().setRefid(r);
    
public voidsetDir(java.io.File dir)
The directory to invoke the VM in. Ignored if no JVM is forked.

param
dir the directory to invoke the JVM from.
see
#setFork(boolean)

        this.dir = dir;
    
public voidsetFork(boolean value)
If true, forks into a new JVM. Default: false.

param
value true if a JVM should be forked, otherwise false

        fork = value;
    
public voidsetFormat(org.apache.tools.ant.taskdefs.optional.jdepend.JDependTask$FormatAttribute ea)
The format to write the output in, "xml" or "text".

param
ea xml or text

        format = ea.getValue();
    
public voidsetHaltonerror(boolean haltonerror)
Whether or not to halt on failure. Default: false.

param
haltonerror the value to set

        this.haltonerror = haltonerror;
    
public voidsetIncluderuntime(boolean b)
If true, include jdepend.jar in the forked VM.

param
b include ant run time yes or no
since
Ant 1.6


     
        try {
            Class packageFilter =
                Class.forName("jdepend.framework.PackageFilter");
            packageFilterC =
                packageFilter.getConstructor(new Class[] {java.util.Collection.class});
            setFilter =
                jdepend.textui.JDepend.class.getDeclaredMethod("setFilter",
                                                               new Class[] {packageFilter});
        } catch (Throwable t) {
            if (setFilter == null) {
                packageFilterC = null;
            }
        }
    
        includeRuntime = b;
    
public voidsetJvm(java.lang.String value)
The command used to invoke a forked Java Virtual Machine. Default is java. Ignored if no JVM is forked.

param
value the new VM to use instead of java
see
#setFork(boolean)

        jvm = value;

    
public voidsetOutputFile(java.io.File outputFile)
The output file name.

param
outputFile the output file name

        this.outputFile = outputFile;
    
public voidsetTimeout(java.lang.Long value)
Set the timeout value (in milliseconds).

If the operation is running for more than this value, the jdepend will be canceled. (works only when in 'fork' mode).

param
value the maximum time (in milliseconds) allowed before declaring the test as 'timed-out'
see
#setFork(boolean)

        timeout = value;