Clover coverage report - Ant Coverage
Coverage timestamp: Tue Apr 8 2003 20:43:55 EST
file stats: LOC: 450   Methods: 21
NCLOC: 212   Classes: 2
 
 Source file Conditionals Statements Methods TOTAL
Javah.java 0% 0% 0% 0%
 1   
 /*
 2   
  * The Apache Software License, Version 1.1
 3   
  *
 4   
  * Copyright (c) 2000-2003 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 "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;
 56   
 
 57   
 import java.io.File;
 58   
 import java.util.Enumeration;
 59   
 import java.util.StringTokenizer;
 60   
 import java.util.Vector;
 61   
 import org.apache.tools.ant.BuildException;
 62   
 import org.apache.tools.ant.Project;
 63   
 import org.apache.tools.ant.Task;
 64   
 import org.apache.tools.ant.types.Commandline;
 65   
 import org.apache.tools.ant.types.Path;
 66   
 import org.apache.tools.ant.types.Reference;
 67   
 import org.apache.tools.ant.util.JavaEnvUtils;
 68   
 
 69   
 /**
 70   
  * Generates JNI header files using javah.
 71   
  *
 72   
  * This task can take the following arguments:
 73   
  * <ul>
 74   
  * <li>classname - the fully-qualified name of a class</li>
 75   
  * <li>outputFile - Concatenates the resulting header or source files for all
 76   
  *     the classes listed into this file</li>
 77   
  * <li>destdir - Sets the directory where javah saves the header files or the
 78   
  *     stub files</li>
 79   
  * <li>classpath</li>
 80   
  * <li>bootclasspath</li>
 81   
  * <li>force - Specifies that output files should always be written
 82   
        (JDK1.2 only)</li>
 83   
  * <li>old - Specifies that old JDK1.0-style header files should be generated
 84   
  *     (otherwise output file contain JNI-style native method
 85   
  *      function prototypes) (JDK1.2 only)</li>
 86   
  * <li>stubs - generate C declarations from the Java object file (used with old)</li>
 87   
  * <li>verbose - causes javah to print a message to stdout concerning the status
 88   
  *     of the generated files</li>
 89   
  * <li>extdirs - Override location of installed extensions</li>
 90   
  * </ul>
 91   
  * Of these arguments, either <b>outputFile</b> or <b>destdir</b> is required,
 92   
  * but not both. More than one classname may be specified, using a comma-separated
 93   
  * list or by using <code>&lt;class name="xxx"&gt;</code> elements within the task.
 94   
  * <p>
 95   
  * When this task executes, it will generate C header and source files that
 96   
  * are needed to implement native methods.
 97   
  *
 98   
  * @author Rick Beton <a href="mailto:richard.beton@physics.org">richard.beton@physics.org</a>
 99   
  */
 100   
 
 101   
 public class Javah extends Task {
 102   
 
 103   
     private Vector classes = new Vector(2);
 104   
     private String cls;
 105   
     private File destDir;
 106   
     private Path classpath = null;
 107   
     private File outputFile = null;
 108   
     private boolean verbose = false;
 109   
     private boolean force   = false;
 110   
     private boolean old     = false;
 111   
     private boolean stubs   = false;
 112   
     private Path bootclasspath;
 113   
     //private Path extdirs;
 114   
     private static String lSep = System.getProperty("line.separator");
 115   
 
 116   
     /**
 117   
      * the fully-qualified name of the class (or classes, separated by commas).
 118   
      */
 119  0
     public void setClass(String cls) {
 120  0
         this.cls = cls;
 121   
     }
 122   
 
 123   
     /**
 124   
      * Adds class to process.
 125   
      */
 126  0
     public ClassArgument createClass() {
 127  0
         ClassArgument ga = new ClassArgument();
 128  0
         classes.addElement(ga);
 129  0
         return ga;
 130   
     }
 131   
 
 132   
     public class ClassArgument {
 133   
         private String name;
 134   
 
 135  0
         public ClassArgument() {
 136   
         }
 137   
 
 138  0
         public void setName(String name) {
 139  0
             this.name = name;
 140  0
             log("ClassArgument.name=" + name);
 141   
         }
 142   
 
 143  0
         public String getName() {
 144  0
             return name;
 145   
         }
 146   
     }
 147   
 
 148   
     /**
 149   
      * Set the destination directory into which the Java source
 150   
      * files should be compiled.
 151   
      */
 152  0
     public void setDestdir(File destDir) {
 153  0
         this.destDir = destDir;
 154   
     }
 155   
 
 156   
     /**
 157   
      * the classpath to use.
 158   
      */
 159  0
     public void setClasspath(Path src) {
 160  0
         if (classpath == null) {
 161  0
             classpath = src;
 162   
         } else {
 163  0
             classpath.append(src);
 164   
         }
 165   
     }
 166   
 
 167   
     /**
 168   
      * Path to use for classpath.
 169   
      */
 170  0
     public Path createClasspath() {
 171  0
         if (classpath == null) {
 172  0
             classpath = new Path(getProject());
 173   
         }
 174  0
         return classpath.createPath();
 175   
     }
 176   
 
 177   
     /**
 178   
      * Adds a reference to a classpath defined elsewhere.
 179   
      * @todo this needs to be documented in the HTML docs
 180   
      */
 181  0
     public void setClasspathRef(Reference r) {
 182  0
         createClasspath().setRefid(r);
 183   
     }
 184   
 
 185   
     /**
 186   
      * location of bootstrap class files.
 187   
      */
 188  0
     public void setBootclasspath(Path src) {
 189  0
         if (bootclasspath == null) {
 190  0
             bootclasspath = src;
 191   
         } else {
 192  0
             bootclasspath.append(src);
 193   
         }
 194   
     }
 195   
 
 196   
     /**
 197   
      * Adds path to bootstrap class files.
 198   
      */
 199  0
     public Path createBootclasspath() {
 200  0
         if (bootclasspath == null) {
 201  0
             bootclasspath = new Path(getProject());
 202   
         }
 203  0
         return bootclasspath.createPath();
 204   
     }
 205   
 
 206   
     /**
 207   
      * Adds a reference to a classpath defined elsewhere.
 208   
      * @todo this needs to be documented in the HTML
 209   
      */
 210  0
     public void setBootClasspathRef(Reference r) {
 211  0
         createBootclasspath().setRefid(r);
 212   
     }
 213   
 
 214   
     ///**
 215   
     // * Sets the extension directories that will be used during the
 216   
     // * compilation.
 217   
     // */
 218   
     //public void setExtdirs(Path extdirs) {
 219   
     //    if (this.extdirs == null) {
 220   
     //        this.extdirs = extdirs;
 221   
     //    } else {
 222   
     //        this.extdirs.append(extdirs);
 223   
     //    }
 224   
     //}
 225   
 
 226   
     ///**
 227   
     // * Maybe creates a nested classpath element.
 228   
     // */
 229   
     //public Path createExtdirs() {
 230   
     //    if (extdirs == null) {
 231   
     //        extdirs = new Path(project);
 232   
     //    }
 233   
     //    return extdirs.createPath();
 234   
     //}
 235   
 
 236   
     /**
 237   
      * Concatenates the resulting header or source files for all
 238   
      * the classes listed into this file.
 239   
      */
 240  0
     public void setOutputFile(File outputFile) {
 241  0
         this.outputFile = outputFile;
 242   
     }
 243   
 
 244   
     /**
 245   
      * If true, output files should always be written (JDK1.2 only).
 246   
      */
 247  0
     public void setForce(boolean force) {
 248  0
         this.force = force;
 249   
     }
 250   
 
 251   
     /**
 252   
      * If true, specifies that old JDK1.0-style header files should be
 253   
      * generated.
 254   
      * (otherwise output file contain JNI-style native method function prototypes) (JDK1.2 only)
 255   
      */
 256  0
     public void setOld(boolean old) {
 257  0
         this.old = old;
 258   
     }
 259   
 
 260   
     /**
 261   
      * If true, generate C declarations from the Java object file (used with old).
 262   
      */
 263  0
     public void setStubs(boolean stubs) {
 264  0
         this.stubs = stubs;
 265   
     }
 266   
 
 267   
     /**
 268   
      * If true, causes Javah to print a message concerning
 269   
      * the status of the generated files.
 270   
      */
 271  0
     public void setVerbose(boolean verbose) {
 272  0
         this.verbose = verbose;
 273   
     }
 274   
 
 275   
     /**
 276   
      * Executes the task.
 277   
      */
 278  0
     public void execute() throws BuildException {
 279   
         // first off, make sure that we've got a srcdir
 280   
 
 281  0
         if ((cls == null) && (classes.size() == 0)) {
 282  0
             throw new BuildException("class attribute must be set!", getLocation());
 283   
         }
 284   
 
 285  0
         if ((cls != null) && (classes.size() > 0)) {
 286  0
             throw new BuildException("set class attribute or class element, not both.", getLocation());
 287   
         }
 288   
 
 289  0
         if (destDir != null) {
 290  0
             if (!destDir.isDirectory()) {
 291  0
                 throw new BuildException("destination directory \"" + destDir + "\" does not exist or is not a directory", getLocation());
 292   
             }
 293  0
             if (outputFile != null) {
 294  0
                 throw new BuildException("destdir and outputFile are mutually exclusive", getLocation());
 295   
             }
 296   
         }
 297   
 
 298  0
         if (classpath == null) {
 299  0
             classpath = (new Path(getProject())).concatSystemClasspath("last");
 300   
         } else {
 301  0
             classpath = classpath.concatSystemClasspath("ignore");
 302   
         }
 303   
 
 304  0
         String compiler = getProject().getProperty("build.compiler");
 305  0
         if (compiler == null) {
 306  0
             if (!JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_1) &&
 307   
                 !JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_2)) {
 308  0
                 compiler = "modern";
 309   
             } else {
 310  0
                 compiler = "classic";
 311   
             }
 312   
         }
 313   
 
 314  0
         doClassicCompile();
 315   
     }
 316   
 
 317   
     // XXX
 318   
     // we need a way to not use the current classpath.
 319   
 
 320   
     /**
 321   
      * Peforms a compile using the classic compiler that shipped with
 322   
      * JDK 1.1 and 1.2.
 323   
      */
 324   
 
 325  0
     private void doClassicCompile() throws BuildException {
 326  0
         Commandline cmd = setupJavahCommand();
 327   
 
 328   
         // Use reflection to be able to build on all JDKs
 329   
         /*
 330   
         // provide the compiler a different message sink - namely our own
 331   
         sun.tools.javac.Main compiler =
 332   
                 new sun.tools.javac.Main(new LogOutputStream(this, Project.MSG_WARN), "javac");
 333   
 
 334   
         if (!compiler.compile(cmd.getArguments())) {
 335   
             throw new BuildException("Compile failed");
 336   
         }
 337   
         */
 338  0
         try {
 339   
             // Javac uses logstr to change the output stream and calls
 340   
             // the constructor's invoke method to create a compiler instance
 341   
             // dynamically. However, javah has a different interface and this
 342   
             // makes it harder, so here's a simple alternative.
 343   
             //------------------------------------------------------------------
 344  0
             com.sun.tools.javah.Main main 
 345   
                 = new com.sun.tools.javah.Main(cmd.getArguments());
 346  0
             main.run();
 347   
         } catch (Exception ex) {
 348  0
             if (ex instanceof BuildException) {
 349  0
                 throw (BuildException) ex;
 350   
             } else {
 351  0
                 throw new BuildException("Error starting javah: " + ex, ex, getLocation());
 352   
             }
 353   
         }
 354   
     }
 355   
 
 356   
     /**
 357   
      * Does the command line argument processing common to classic and
 358   
      * modern.
 359   
      */
 360  0
     private Commandline setupJavahCommand() {
 361  0
         Commandline cmd = new Commandline();
 362   
 
 363  0
         if (destDir != null) {
 364  0
             cmd.createArgument().setValue("-d");
 365  0
             cmd.createArgument().setFile(destDir);
 366   
         }
 367   
 
 368  0
         if (outputFile != null) {
 369  0
             cmd.createArgument().setValue("-o");
 370  0
             cmd.createArgument().setFile(outputFile);
 371   
         }
 372   
 
 373  0
         if (classpath != null) {
 374  0
             cmd.createArgument().setValue("-classpath");
 375  0
             cmd.createArgument().setPath(classpath);
 376   
         }
 377   
 
 378   
         // JDK1.1 is rather simpler than JDK1.2
 379  0
         if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_1)) {
 380  0
             if (verbose) {
 381  0
                 cmd.createArgument().setValue("-v");
 382   
             }
 383   
         } else {
 384  0
             if (verbose) {
 385  0
                 cmd.createArgument().setValue("-verbose");
 386   
             }
 387  0
             if (old) {
 388  0
                 cmd.createArgument().setValue("-old");
 389   
             }
 390  0
             if (force) {
 391  0
                 cmd.createArgument().setValue("-force");
 392   
             }
 393   
         }
 394   
 
 395  0
         if (stubs) {
 396  0
             if (!old) {
 397  0
                 throw new BuildException("stubs only available in old mode.", getLocation());
 398   
             }
 399  0
             cmd.createArgument().setValue("-stubs");
 400   
         }
 401  0
         if (bootclasspath != null) {
 402  0
             cmd.createArgument().setValue("-bootclasspath");
 403  0
             cmd.createArgument().setPath(bootclasspath);
 404   
         }
 405   
 
 406  0
         logAndAddFilesToCompile(cmd);
 407  0
         return cmd;
 408   
     }
 409   
 
 410   
     /**
 411   
      * Logs the compilation parameters, adds the files to compile and logs the
 412   
      * &qout;niceSourceList&quot;
 413   
      */
 414  0
     protected void logAndAddFilesToCompile(Commandline cmd) {
 415  0
         int n = 0;
 416  0
         log("Compilation " + cmd.describeArguments(),
 417   
             Project.MSG_VERBOSE);
 418   
 
 419  0
         StringBuffer niceClassList = new StringBuffer();
 420  0
         if (cls != null) {
 421  0
             StringTokenizer tok = new StringTokenizer(cls, ",", false);
 422  0
             while (tok.hasMoreTokens()) {
 423  0
                 String aClass = tok.nextToken().trim();
 424  0
                 cmd.createArgument().setValue(aClass);
 425  0
                 niceClassList.append("    " + aClass + lSep);
 426  0
                 n++;
 427   
             }
 428   
         }
 429   
 
 430  0
         Enumeration enum = classes.elements();
 431  0
         while (enum.hasMoreElements()) {
 432  0
             ClassArgument arg = (ClassArgument) enum.nextElement();
 433  0
             String aClass = arg.getName();
 434  0
             cmd.createArgument().setValue(aClass);
 435  0
             niceClassList.append("    " + aClass + lSep);
 436  0
             n++;
 437   
         }
 438   
 
 439  0
         StringBuffer prefix = new StringBuffer("Class");
 440  0
         if (n > 1) {
 441  0
             prefix.append("es");
 442   
         }
 443  0
         prefix.append(" to be compiled:");
 444  0
         prefix.append(lSep);
 445   
 
 446  0
         log(prefix.toString() + niceClassList.toString(), Project.MSG_VERBOSE);
 447   
     }
 448   
 }
 449   
 
 450