KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > taskdefs > optional > Javah


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */

18
19 package org.apache.tools.ant.taskdefs.optional;
20
21 import java.io.File JavaDoc;
22 import java.util.ArrayList JavaDoc;
23 import java.util.Enumeration JavaDoc;
24 import java.util.StringTokenizer JavaDoc;
25 import java.util.Vector JavaDoc;
26 import org.apache.tools.ant.BuildException;
27 import org.apache.tools.ant.Project;
28 import org.apache.tools.ant.Task;
29 import org.apache.tools.ant.taskdefs.optional.javah.JavahAdapter;
30 import org.apache.tools.ant.taskdefs.optional.javah.JavahAdapterFactory;
31 import org.apache.tools.ant.types.Commandline;
32 import org.apache.tools.ant.types.Path;
33 import org.apache.tools.ant.types.Reference;
34 import org.apache.tools.ant.util.facade.FacadeTaskHelper;
35 import org.apache.tools.ant.util.facade.ImplementationSpecificArgument;
36
37 /**
38  * Generates JNI header files using javah.
39  *
40  * This task can take the following arguments:
41  * <ul>
42  * <li>classname - the fully-qualified name of a class</li>
43  * <li>outputFile - Concatenates the resulting header or source files for all
44  * the classes listed into this file</li>
45  * <li>destdir - Sets the directory where javah saves the header files or the
46  * stub files</li>
47  * <li>classpath</li>
48  * <li>bootclasspath</li>
49  * <li>force - Specifies that output files should always be written
50        (JDK1.2 only)</li>
51  * <li>old - Specifies that old JDK1.0-style header files should be generated
52  * (otherwise output file contain JNI-style native method
53  * function prototypes) (JDK1.2 only)</li>
54  * <li>stubs - generate C declarations from the Java object file (used with old)</li>
55  * <li>verbose - causes javah to print a message to stdout concerning the status
56  * of the generated files</li>
57  * <li>extdirs - Override location of installed extensions</li>
58  * </ul>
59  * Of these arguments, either <b>outputFile</b> or <b>destdir</b> is required,
60  * but not both. More than one classname may be specified, using a comma-separated
61  * list or by using <code>&lt;class name="xxx"&gt;</code> elements within the task.
62  * <p>
63  * When this task executes, it will generate C header and source files that
64  * are needed to implement native methods.
65  *
66  */

67
68 public class Javah extends Task {
69
70     private Vector JavaDoc classes = new Vector JavaDoc(2);
71     private String JavaDoc cls;
72     private File JavaDoc destDir;
73     private Path classpath = null;
74     private File JavaDoc outputFile = null;
75     private boolean verbose = false;
76     private boolean force = false;
77     private boolean old = false;
78     private boolean stubs = false;
79     private Path bootclasspath;
80     //private Path extdirs;
81
private static String JavaDoc lSep = System.getProperty("line.separator");
82     private FacadeTaskHelper facade = null;
83
84     /**
85      * No arg constructor.
86      */

87     public Javah() {
88         facade = new FacadeTaskHelper(JavahAdapterFactory.getDefault());
89     }
90
91     /**
92      * the fully-qualified name of the class (or classes, separated by commas).
93      * @param cls the classname (or classnames).
94      */

95     public void setClass(String JavaDoc cls) {
96         this.cls = cls;
97     }
98
99     /**
100      * Adds class to process.
101      * @return a <code>ClassArgument</code> to be configured.
102      */

103     public ClassArgument createClass() {
104         ClassArgument ga = new ClassArgument();
105         classes.addElement(ga);
106         return ga;
107     }
108
109     /**
110      * A class corresponding the the nested "class" element.
111      * It contains a "name" attribute.
112      */

113     public class ClassArgument {
114         private String JavaDoc name;
115
116         /** Constructor for ClassArgument. */
117         public ClassArgument() {
118         }
119
120         /**
121          * Set the name attribute.
122          * @param name the name attribute.
123          */

124         public void setName(String JavaDoc name) {
125             this.name = name;
126         }
127
128         /**
129          * Get the name attribute.
130          * @return the name attribute.
131          */

132         public String JavaDoc getName() {
133             return name;
134         }
135     }
136
137     /**
138      * Names of the classes to process.
139      * @return the array of classes.
140      * @since Ant 1.6.3
141      */

142     public String JavaDoc[] getClasses() {
143         ArrayList JavaDoc al = new ArrayList JavaDoc();
144         if (cls != null) {
145             StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(cls, ",", false);
146             while (tok.hasMoreTokens()) {
147                 al.add(tok.nextToken().trim());
148             }
149         }
150
151         Enumeration JavaDoc e = classes.elements();
152         while (e.hasMoreElements()) {
153             ClassArgument arg = (ClassArgument) e.nextElement();
154             al.add(arg.getName());
155         }
156         return (String JavaDoc[]) al.toArray(new String JavaDoc[al.size()]);
157     }
158
159     /**
160      * Set the destination directory into which the Java source
161      * files should be compiled.
162      * @param destDir the destination directory.
163      */

164     public void setDestdir(File JavaDoc destDir) {
165         this.destDir = destDir;
166     }
167
168     /**
169      * The destination directory, if any.
170      * @return the destination directory.
171      * @since Ant 1.6.3
172      */

173     public File JavaDoc getDestdir() {
174         return destDir;
175     }
176
177     /**
178      * the classpath to use.
179      * @param src the classpath.
180      */

181     public void setClasspath(Path src) {
182         if (classpath == null) {
183             classpath = src;
184         } else {
185             classpath.append(src);
186         }
187     }
188
189     /**
190      * Path to use for classpath.
191      * @return a path to be configured.
192      */

193     public Path createClasspath() {
194         if (classpath == null) {
195             classpath = new Path(getProject());
196         }
197         return classpath.createPath();
198     }
199
200     /**
201      * Adds a reference to a classpath defined elsewhere.
202      * @param r a reference to a classpath.
203      * @todo this needs to be documented in the HTML docs.
204      */

205     public void setClasspathRef(Reference r) {
206         createClasspath().setRefid(r);
207     }
208
209     /**
210      * The classpath to use.
211      * @return the classpath.
212      * @since Ant 1.6.3
213      */

214     public Path getClasspath() {
215         return classpath;
216     }
217
218     /**
219      * location of bootstrap class files.
220      * @param src the bootstrap classpath.
221      */

222     public void setBootclasspath(Path src) {
223         if (bootclasspath == null) {
224             bootclasspath = src;
225         } else {
226             bootclasspath.append(src);
227         }
228     }
229
230     /**
231      * Adds path to bootstrap class files.
232      * @return a path to be configured.
233      */

234     public Path createBootclasspath() {
235         if (bootclasspath == null) {
236             bootclasspath = new Path(getProject());
237         }
238         return bootclasspath.createPath();
239     }
240
241     /**
242      * To the bootstrap path, this adds a reference to a classpath defined elsewhere.
243      * @param r a reference to a classpath
244      * @todo this needs to be documented in the HTML.
245      */

246     public void setBootClasspathRef(Reference r) {
247         createBootclasspath().setRefid(r);
248     }
249
250     /**
251      * The bootclasspath to use.
252      * @return the bootclass path.
253      * @since Ant 1.6.3
254      */

255     public Path getBootclasspath() {
256         return bootclasspath;
257     }
258
259     /**
260      * Concatenates the resulting header or source files for all
261      * the classes listed into this file.
262      * @param outputFile the output file.
263      */

264     public void setOutputFile(File JavaDoc outputFile) {
265         this.outputFile = outputFile;
266     }
267
268     /**
269      * The destination file, if any.
270      * @return the destination file.
271      * @since Ant 1.6.3
272      */

273     public File JavaDoc getOutputfile() {
274         return outputFile;
275     }
276
277     /**
278      * If true, output files should always be written (JDK1.2 only).
279      * @param force the value to use.
280      */

281     public void setForce(boolean force) {
282         this.force = force;
283     }
284
285     /**
286      * Whether output files should always be written.
287      * @return the force attribute.
288      * @since Ant 1.6.3
289      */

290     public boolean getForce() {
291         return force;
292     }
293
294     /**
295      * If true, specifies that old JDK1.0-style header files should be
296      * generated.
297      * (otherwise output file contain JNI-style native method function
298      * prototypes) (JDK1.2 only).
299      * @param old if true use old 1.0 style header files.
300      */

301     public void setOld(boolean old) {
302         this.old = old;
303     }
304
305     /**
306      * Whether old JDK1.0-style header files should be generated.
307      * @return the old attribute.
308      * @since Ant 1.6.3
309      */

310     public boolean getOld() {
311         return old;
312     }
313
314     /**
315      * If true, generate C declarations from the Java object file (used with old).
316      * @param stubs if true, generated C declarations.
317      */

318     public void setStubs(boolean stubs) {
319         this.stubs = stubs;
320     }
321
322     /**
323      * Whether C declarations from the Java object file should be generated.
324      * @return the stubs attribute.
325      * @since Ant 1.6.3
326      */

327     public boolean getStubs() {
328         return stubs;
329     }
330
331     /**
332      * If true, causes Javah to print a message concerning
333      * the status of the generated files.
334      * @param verbose if true, do verbose printing.
335      */

336     public void setVerbose(boolean verbose) {
337         this.verbose = verbose;
338     }
339
340     /**
341      * Whether verbose output should get generated.
342      * @return the verbose attribute.
343      * @since Ant 1.6.3
344      */

345     public boolean getVerbose() {
346         return verbose;
347     }
348
349     /**
350      * Choose the implementation for this particular task.
351      * @param impl the name of the implemenation.
352      * @since Ant 1.6.3
353      */

354     public void setImplementation(String JavaDoc impl) {
355         if ("default".equals(impl)) {
356             facade.setImplementation(JavahAdapterFactory.getDefault());
357         } else {
358             facade.setImplementation(impl);
359         }
360     }
361
362     /**
363      * Adds an implementation specific command-line argument.
364      * @return a ImplementationSpecificArgument to be configured.
365      *
366      * @since Ant 1.6.3
367      */

368     public ImplementationSpecificArgument createArg() {
369         ImplementationSpecificArgument arg =
370             new ImplementationSpecificArgument();
371         facade.addImplementationArgument(arg);
372         return arg;
373     }
374
375     /**
376      * Returns the (implementation specific) settings given as nested
377      * arg elements.
378      * @return the arguments.
379      * @since Ant 1.6.3
380      */

381     public String JavaDoc[] getCurrentArgs() {
382         return facade.getArgs();
383     }
384
385     /**
386      * Execute the task
387      *
388      * @throws BuildException is there is a problem in the task execution.
389      */

390     public void execute() throws BuildException {
391         // first off, make sure that we've got a srcdir
392

393         if ((cls == null) && (classes.size() == 0)) {
394             throw new BuildException("class attribute must be set!",
395                 getLocation());
396         }
397
398         if ((cls != null) && (classes.size() > 0)) {
399             throw new BuildException("set class attribute or class element, "
400                 + "not both.", getLocation());
401         }
402
403         if (destDir != null) {
404             if (!destDir.isDirectory()) {
405                 throw new BuildException("destination directory \"" + destDir
406                     + "\" does not exist or is not a directory", getLocation());
407             }
408             if (outputFile != null) {
409                 throw new BuildException("destdir and outputFile are mutually "
410                     + "exclusive", getLocation());
411             }
412         }
413
414         if (classpath == null) {
415             classpath = (new Path(getProject())).concatSystemClasspath("last");
416         } else {
417             classpath = classpath.concatSystemClasspath("ignore");
418         }
419
420         JavahAdapter ad =
421             JavahAdapterFactory.getAdapter(facade.getImplementation(),
422                                            this);
423         if (!ad.compile(this)) {
424             throw new BuildException("compilation failed");
425         }
426     }
427
428     /**
429      * Logs the compilation parameters, adds the files to compile and logs the
430      * &quot;niceSourceList&quot;
431      * @param cmd the command line.
432      */

433     public void logAndAddFiles(Commandline cmd) {
434         logAndAddFilesToCompile(cmd);
435     }
436
437     /**
438      * Logs the compilation parameters, adds the files to compile and logs the
439      * &quot;niceSourceList&quot;
440      * @param cmd the command line to add parameters to.
441      */

442     protected void logAndAddFilesToCompile(Commandline cmd) {
443         log("Compilation " + cmd.describeArguments(),
444             Project.MSG_VERBOSE);
445
446         StringBuffer JavaDoc niceClassList = new StringBuffer JavaDoc();
447         String JavaDoc[] c = getClasses();
448         for (int i = 0; i < c.length; i++) {
449             cmd.createArgument().setValue(c[i]);
450             niceClassList.append(" ");
451             niceClassList.append(c[i]);
452             niceClassList.append(lSep);
453         }
454
455         StringBuffer JavaDoc prefix = new StringBuffer JavaDoc("Class");
456         if (c.length > 1) {
457             prefix.append("es");
458         }
459         prefix.append(" to be compiled:");
460         prefix.append(lSep);
461
462         log(prefix.toString() + niceClassList.toString(), Project.MSG_VERBOSE);
463     }
464 }
465
466
Popular Tags