KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > taskdefs > Rmic


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;
20
21 import java.io.File JavaDoc;
22 import java.io.IOException JavaDoc;
23 import java.rmi.Remote JavaDoc;
24 import java.util.Vector JavaDoc;
25 import org.apache.tools.ant.BuildException;
26 import org.apache.tools.ant.DirectoryScanner;
27 import org.apache.tools.ant.Project;
28 import org.apache.tools.ant.taskdefs.rmic.RmicAdapter;
29 import org.apache.tools.ant.taskdefs.rmic.RmicAdapterFactory;
30 import org.apache.tools.ant.types.FilterSetCollection;
31 import org.apache.tools.ant.types.Path;
32 import org.apache.tools.ant.types.Reference;
33 import org.apache.tools.ant.util.FileNameMapper;
34 import org.apache.tools.ant.util.FileUtils;
35 import org.apache.tools.ant.util.SourceFileScanner;
36 import org.apache.tools.ant.util.facade.FacadeTaskHelper;
37
38 /**
39  * Runs the rmic compiler against classes.</p>
40  * <p>Rmic can be run on a single class (as specified with the classname
41  * attribute) or a number of classes at once (all classes below base that
42  * are neither _Stub nor _Skel classes). If you want to rmic a single
43  * class and this class is a class nested into another class, you have to
44  * specify the classname in the form <code>Outer$$Inner</code> instead of
45  * <code>Outer.Inner</code>.</p>
46  * <p>It is possible to refine the set of files that are being rmiced. This can
47  * be done with the <i>includes</i>, <i>includesfile</i>, <i>excludes</i>,
48  * <i>excludesfile</i> and <i>defaultexcludes</i>
49  * attributes. With the <i>includes</i> or <i>includesfile</i> attribute you
50  * specify the files you want to have included by using patterns. The
51  * <i>exclude</i> or <i>excludesfile</i> attribute is used to specify
52  * the files you want to have excluded. This is also done with patterns. And
53  * finally with the <i>defaultexcludes</i> attribute, you can specify whether
54  * you want to use default exclusions or not. See the section on
55  * directory based tasks</a>, on how the
56  * inclusion/exclusion of files works, and how to write patterns.</p>
57  * <p>This task forms an implicit FileSet and
58  * supports all attributes of <code>&lt;fileset&gt;</code>
59  * (<code>dir</code> becomes <code>base</code>) as well as the nested
60  * <code>&lt;include&gt;</code>, <code>&lt;exclude&gt;</code> and
61  * <code>&lt;patternset&gt;</code> elements.</p>
62  * <p>It is possible to use different compilers. This can be selected
63  * with the &quot;build.rmic&quot; property or the <code>compiler</code>
64  * attribute. <a name="compilervalues">There are three choices</a>:</p>
65  * <ul>
66  * <li>sun (the standard compiler of the JDK)</li>
67  * <li>kaffe (the standard compiler of
68  * {@link <a HREF="http://www.kaffe.org">Kaffe</a>})</li>
69  * <li>weblogic</li>
70  * </ul>
71  *
72  * <p> The <a HREF="http://dione.zcu.cz/~toman40/miniRMI/">miniRMI</a>
73  * project contains a compiler implementation for this task as well,
74  * please consult miniRMI's documentation to learn how to use it.</p>
75  *
76  * @since Ant 1.1
77  *
78  * @ant.task category="java"
79  */

80
81 public class Rmic extends MatchingTask {
82
83     /** rmic failed message */
84     public static final String JavaDoc ERROR_RMIC_FAILED
85         = "Rmic failed; see the compiler error output for details.";
86
87     private File JavaDoc baseDir;
88     private String JavaDoc classname;
89     private File JavaDoc sourceBase;
90     private String JavaDoc stubVersion;
91     private Path compileClasspath;
92     private Path extDirs;
93     private boolean verify = false;
94     private boolean filtering = false;
95
96     private boolean iiop = false;
97     private String JavaDoc iiopOpts;
98     private boolean idl = false;
99     private String JavaDoc idlOpts;
100     private boolean debug = false;
101     private boolean includeAntRuntime = true;
102     private boolean includeJavaRuntime = false;
103
104     private Vector JavaDoc compileList = new Vector JavaDoc();
105
106     private ClassLoader JavaDoc loader = null;
107
108     private FacadeTaskHelper facade;
109     /** unable to verify message */
110     public static final String JavaDoc ERROR_UNABLE_TO_VERIFY_CLASS = "Unable to verify class ";
111     /** could not be found message */
112     public static final String JavaDoc ERROR_NOT_FOUND = ". It could not be found.";
113     /** not defined message */
114     public static final String JavaDoc ERROR_NOT_DEFINED = ". It is not defined.";
115     /** loaded error message */
116     public static final String JavaDoc ERROR_LOADING_CAUSED_EXCEPTION = ". Loading caused Exception: ";
117     /** base not exists message */
118     public static final String JavaDoc ERROR_NO_BASE_EXISTS = "base does not exist: ";
119     /** base not a directory message */
120     public static final String JavaDoc ERROR_NOT_A_DIR = "base is not a directory:";
121     /** base attribute not set message */
122     public static final String JavaDoc ERROR_BASE_NOT_SET = "base attribute must be set!";
123
124     private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
125
126     /**
127      * Constructor for Rmic.
128      */

129     public Rmic() {
130         facade = new FacadeTaskHelper(RmicAdapterFactory.DEFAULT_COMPILER);
131     }
132
133     /**
134      * Sets the location to store the compiled files; required
135      * @param base the location to store the compiled files
136      */

137     public void setBase(File JavaDoc base) {
138         this.baseDir = base;
139     }
140
141     /**
142      * Gets the base directory to output generated class.
143      * @return the location of the compiled files
144      */

145
146     public File JavaDoc getBase() {
147         return this.baseDir;
148     }
149
150     /**
151      * Sets the class to run <code>rmic</code> against;
152      * optional
153      * @param classname the name of the class for rmic to create code for
154      */

155     public void setClassname(String JavaDoc classname) {
156         this.classname = classname;
157     }
158
159     /**
160      * Gets the class name to compile.
161      * @return the name of the class to compile
162      */

163     public String JavaDoc getClassname() {
164         return classname;
165     }
166
167     /**
168      * optional directory to save generated source files to.
169      * @param sourceBase the directory to save source files to.
170      */

171     public void setSourceBase(File JavaDoc sourceBase) {
172         this.sourceBase = sourceBase;
173     }
174
175     /**
176      * Gets the source dirs to find the source java files.
177      * @return sourceBase the directory containing the source files.
178      */

179     public File JavaDoc getSourceBase() {
180         return sourceBase;
181     }
182
183     /**
184      * Specify the JDK version for the generated stub code.
185      * Specify &quot;1.1&quot; to pass the &quot;-v1.1&quot; option to rmic.</td>
186      * @param stubVersion the JDK version
187      */

188     public void setStubVersion(String JavaDoc stubVersion) {
189         this.stubVersion = stubVersion;
190     }
191
192     /**
193      * Gets the JDK version for the generated stub code.
194      * @return stubVersion
195      */

196     public String JavaDoc getStubVersion() {
197         return stubVersion;
198     }
199
200     /**
201      * Sets token filtering [optional], default=false
202      * @param filter turn on token filtering
203      */

204     public void setFiltering(boolean filter) {
205         this.filtering = filter;
206     }
207
208     /**
209      * Gets whether token filtering is set
210      * @return filtering
211      */

212     public boolean getFiltering() {
213         return filtering;
214     }
215
216     /**
217      * Generate debug info (passes -g to rmic);
218      * optional, defaults to false
219      * @param debug turn on debug info
220      */

221     public void setDebug(boolean debug) {
222         this.debug = debug;
223     }
224
225     /**
226      * Gets the debug flag.
227      * @return debug
228      */

229     public boolean getDebug() {
230         return debug;
231     }
232
233     /**
234      * Set the classpath to be used for this compilation.
235      * @param classpath the classpath used for this compilation
236      */

237     public void setClasspath(Path classpath) {
238         if (compileClasspath == null) {
239             compileClasspath = classpath;
240         } else {
241             compileClasspath.append(classpath);
242         }
243     }
244
245     /**
246      * Creates a nested classpath element.
247      * @return classpath
248      */

249     public Path createClasspath() {
250         if (compileClasspath == null) {
251             compileClasspath = new Path(getProject());
252         }
253         return compileClasspath.createPath();
254     }
255
256     /**
257      * Adds to the classpath a reference to
258      * a &lt;path&gt; defined elsewhere.
259      * @param pathRef the reference to add to the classpath
260      */

261     public void setClasspathRef(Reference pathRef) {
262         createClasspath().setRefid(pathRef);
263     }
264
265     /**
266      * Gets the classpath.
267      * @return the classpath
268      */

269     public Path getClasspath() {
270         return compileClasspath;
271     }
272
273     /**
274      * Flag to enable verification so that the classes
275      * found by the directory match are
276      * checked to see if they implement java.rmi.Remote.
277      * optional; This defaults to false if not set.
278      * @param verify turn on verification for classes
279      */

280
281     public void setVerify(boolean verify) {
282         this.verify = verify;
283     }
284
285     /**
286      * Get verify flag.
287      * @return verify
288      */

289     public boolean getVerify() {
290         return verify;
291     }
292
293     /**
294      * Indicates that IIOP compatible stubs should
295      * be generated; optional, defaults to false
296      * if not set.
297      * @param iiop generate IIOP compatible stubs
298      */

299     public void setIiop(boolean iiop) {
300         this.iiop = iiop;
301     }
302
303     /**
304      * Gets iiop flags.
305      * @return iiop
306      */

307     public boolean getIiop() {
308         return iiop;
309     }
310
311     /**
312      * Set additional arguments for iiop
313      * @param iiopOpts additional arguments for iiop
314      */

315     public void setIiopopts(String JavaDoc iiopOpts) {
316         this.iiopOpts = iiopOpts;
317     }
318
319     /**
320      * Gets additional arguments for iiop.
321      * @return iiopOpts
322      */

323     public String JavaDoc getIiopopts() {
324         return iiopOpts;
325     }
326
327     /**
328      * Indicates that IDL output should be
329      * generated. This defaults to false
330      * if not set.
331      * @param idl generate IDL output
332      */

333     public void setIdl(boolean idl) {
334         this.idl = idl;
335     }
336
337     /**
338      * Gets IDL flags.
339      * @return the idl flag
340      */

341     public boolean getIdl() {
342         return idl;
343     }
344
345     /**
346      * pass additional arguments for IDL compile
347      * @param idlOpts additional IDL arguments
348      */

349     public void setIdlopts(String JavaDoc idlOpts) {
350         this.idlOpts = idlOpts;
351     }
352
353     /**
354      * Gets additional arguments for idl compile.
355      * @return the idl options
356      */

357     public String JavaDoc getIdlopts() {
358         return idlOpts;
359     }
360
361     /**
362      * Gets file list to compile.
363      * @return the list of files to compile.
364      */

365     public Vector JavaDoc getFileList() {
366         return compileList;
367     }
368
369     /**
370      * Sets whether or not to include ant's own classpath in this task's
371      * classpath.
372      * Optional; default is <code>true</code>.
373      * @param include if true include ant's classpath
374      */

375     public void setIncludeantruntime(boolean include) {
376         includeAntRuntime = include;
377     }
378
379     /**
380      * Gets whether or not the ant classpath is to be included in the
381      * task's classpath.
382      * @return true if ant's classpath is to be included
383      */

384     public boolean getIncludeantruntime() {
385         return includeAntRuntime;
386     }
387
388     /**
389      * task's classpath.
390      * Enables or disables including the default run-time
391      * libraries from the executing VM; optional,
392      * defaults to false
393      * @param include if true include default run-time libraries
394      */

395     public void setIncludejavaruntime(boolean include) {
396         includeJavaRuntime = include;
397     }
398
399     /**
400      * Gets whether or not the java runtime should be included in this
401      * task's classpath.
402      * @return true if default run-time libraries are included
403      */

404     public boolean getIncludejavaruntime() {
405         return includeJavaRuntime;
406     }
407
408     /**
409      * Sets the extension directories that will be used during the
410      * compilation; optional.
411      * @param extDirs the extension directories to be used
412      */

413     public void setExtdirs(Path extDirs) {
414         if (this.extDirs == null) {
415             this.extDirs = extDirs;
416         } else {
417             this.extDirs.append(extDirs);
418         }
419     }
420
421     /**
422      * Maybe creates a nested extdirs element.
423      * @return path object to be configured with the extension directories
424      */

425     public Path createExtdirs() {
426         if (extDirs == null) {
427             extDirs = new Path(getProject());
428         }
429         return extDirs.createPath();
430     }
431
432     /**
433      * Gets the extension directories that will be used during the
434      * compilation.
435      * @return the extension directories to be used
436      */

437     public Path getExtdirs() {
438         return extDirs;
439     }
440
441     /**
442      * @return the compile list.
443      */

444     public Vector JavaDoc getCompileList() {
445         return compileList;
446     }
447
448     /**
449      * Sets the compiler implementation to use; optional,
450      * defaults to the value of the <code>build.rmic</code> property,
451      * or failing that, default compiler for the current VM
452      * @param compiler the compiler implemention to use
453      * @since Ant 1.5
454      */

455     public void setCompiler(String JavaDoc compiler) {
456         if (compiler.length() > 0) {
457             facade.setImplementation(compiler);
458         }
459     }
460
461     /**
462      * get the name of the current compiler
463      * @return the name of the compiler
464      * @since Ant 1.5
465      */

466     public String JavaDoc getCompiler() {
467         facade.setMagicValue(getProject().getProperty("build.rmic"));
468         return facade.getImplementation();
469     }
470
471     /**
472      * Adds an implementation specific command line argument.
473      * @return an object to be configured with a command line argument
474      * @since Ant 1.5
475      */

476     public ImplementationSpecificArgument createCompilerArg() {
477         ImplementationSpecificArgument arg =
478             new ImplementationSpecificArgument();
479         facade.addImplementationArgument(arg);
480         return arg;
481     }
482
483     /**
484      * Get the additional implementation specific command line arguments.
485      * @return array of command line arguments, guaranteed to be non-null.
486      * @since Ant 1.5
487      */

488     public String JavaDoc[] getCurrentCompilerArgs() {
489         getCompiler();
490         return facade.getArgs();
491     }
492
493     /**
494      * execute by creating an instance of an implementation
495      * class and getting to do the work
496      * @throws org.apache.tools.ant.BuildException
497      * if there's a problem with baseDir or RMIC
498      */

499     public void execute() throws BuildException {
500         if (baseDir == null) {
501             throw new BuildException(ERROR_BASE_NOT_SET, getLocation());
502         }
503         if (!baseDir.exists()) {
504             throw new BuildException(ERROR_NO_BASE_EXISTS + baseDir, getLocation());
505         }
506         if (!baseDir.isDirectory()) {
507             throw new BuildException(ERROR_NOT_A_DIR + baseDir, getLocation());
508         }
509         if (verify) {
510             log("Verify has been turned on.", Project.MSG_VERBOSE);
511         }
512
513         RmicAdapter adapter = RmicAdapterFactory.getRmic(getCompiler(), this);
514
515         // now we need to populate the compiler adapter
516
adapter.setRmic(this);
517
518         Path classpath = adapter.getClasspath();
519         loader = getProject().createClassLoader(classpath);
520
521         try {
522             // scan base dirs to build up compile lists only if a
523
// specific classname is not given
524
if (classname == null) {
525                 DirectoryScanner ds = this.getDirectoryScanner(baseDir);
526                 String JavaDoc[] files = ds.getIncludedFiles();
527                 scanDir(baseDir, files, adapter.getMapper());
528             } else {
529                 // otherwise perform a timestamp comparison - at least
530
scanDir(baseDir,
531                         new String JavaDoc[] {classname.replace('.',
532                                                         File.separatorChar)
533                                           + ".class"},
534                         adapter.getMapper());
535             }
536
537             int fileCount = compileList.size();
538             if (fileCount > 0) {
539                 log("RMI Compiling " + fileCount
540                     + " class" + (fileCount > 1 ? "es" : "") + " to " + baseDir,
541                     Project.MSG_INFO);
542
543                 // finally, lets execute the compiler!!
544
if (!adapter.execute()) {
545                     throw new BuildException(ERROR_RMIC_FAILED, getLocation());
546                 }
547             }
548
549             /*
550              * Move the generated source file to the base directory. If
551              * base directory and sourcebase are the same, the generated
552              * sources are already in place.
553              */

554             if (null != sourceBase && !baseDir.equals(sourceBase)
555                 && fileCount > 0) {
556                 if (idl) {
557                     log("Cannot determine sourcefiles in idl mode, ",
558                         Project.MSG_WARN);
559                     log("sourcebase attribute will be ignored.",
560                         Project.MSG_WARN);
561                 } else {
562                     for (int j = 0; j < fileCount; j++) {
563                         moveGeneratedFile(baseDir, sourceBase,
564                                           (String JavaDoc) compileList.elementAt(j),
565                                           adapter);
566                     }
567                 }
568             }
569         } finally {
570             compileList.removeAllElements();
571         }
572     }
573
574     /**
575      * Move the generated source file(s) to the base directory
576      *
577      * @throws org.apache.tools.ant.BuildException When error
578      * copying/removing files.
579      */

580     private void moveGeneratedFile (File JavaDoc baseDir, File JavaDoc sourceBaseFile,
581                                     String JavaDoc classname,
582                                     RmicAdapter adapter)
583         throws BuildException {
584
585         String JavaDoc classFileName =
586             classname.replace('.', File.separatorChar) + ".class";
587         String JavaDoc[] generatedFiles =
588             adapter.getMapper().mapFileName(classFileName);
589
590         for (int i = 0; i < generatedFiles.length; i++) {
591             final String JavaDoc generatedFile = generatedFiles[i];
592             if (!generatedFile.endsWith(".class")) {
593                 // don't know how to handle that - a IDL file doesn't
594
// have a corresponding Java source for example.
595
continue;
596             }
597
598             final int pos = generatedFile.length() - ".class".length();
599             String JavaDoc sourceFileName =
600                 generatedFile.substring(0, pos) + ".java";
601
602             File JavaDoc oldFile = new File JavaDoc(baseDir, sourceFileName);
603             if (!oldFile.exists()) {
604                 // no source file generated, nothing to move
605
continue;
606             }
607
608             File JavaDoc newFile = new File JavaDoc(sourceBaseFile, sourceFileName);
609             try {
610                 if (filtering) {
611                     FILE_UTILS.copyFile(oldFile, newFile,
612                         new FilterSetCollection(getProject()
613                                                 .getGlobalFilterSet()));
614                 } else {
615                     FILE_UTILS.copyFile(oldFile, newFile);
616                 }
617                 oldFile.delete();
618             } catch (IOException JavaDoc ioe) {
619                 String JavaDoc msg = "Failed to copy " + oldFile + " to "
620                     + newFile + " due to " + ioe.getMessage();
621                 throw new BuildException(msg, ioe, getLocation());
622             }
623         }
624     }
625
626     /**
627      * Scans the directory looking for class files to be compiled.
628      * The result is returned in the class variable compileList.
629      * @param baseDir the base direction
630      * @param files the list of files to scan
631      * @param mapper the mapper of files to target files
632      */

633     protected void scanDir(File JavaDoc baseDir, String JavaDoc[] files,
634                            FileNameMapper mapper) {
635
636         String JavaDoc[] newFiles = files;
637         if (idl) {
638             log("will leave uptodate test to rmic implementation in idl mode.",
639                 Project.MSG_VERBOSE);
640         } else if (iiop
641                    && iiopOpts != null && iiopOpts.indexOf("-always") > -1) {
642             log("no uptodate test as -always option has been specified",
643                 Project.MSG_VERBOSE);
644         } else {
645             SourceFileScanner sfs = new SourceFileScanner(this);
646             newFiles = sfs.restrict(files, baseDir, baseDir, mapper);
647         }
648
649         for (int i = 0; i < newFiles.length; i++) {
650             String JavaDoc name = newFiles[i].replace(File.separatorChar, '.');
651             name = name.substring(0, name.lastIndexOf(".class"));
652             compileList.addElement(name);
653         }
654     }
655
656     /**
657      * Load named class and test whether it can be rmic'ed
658      * @param classname the name of the class to be tested
659      * @return true if the class can be rmic'ed
660      */

661     public boolean isValidRmiRemote(String JavaDoc classname) {
662         try {
663             Class JavaDoc testClass = loader.loadClass(classname);
664             // One cannot RMIC an interface for "classic" RMI (JRMP)
665
if (testClass.isInterface() && !iiop && !idl) {
666                 return false;
667             }
668             return isValidRmiRemote(testClass);
669         } catch (ClassNotFoundException JavaDoc e) {
670             log(ERROR_UNABLE_TO_VERIFY_CLASS + classname
671                 + ERROR_NOT_FOUND, Project.MSG_WARN);
672         } catch (NoClassDefFoundError JavaDoc e) {
673             log(ERROR_UNABLE_TO_VERIFY_CLASS + classname
674                 + ERROR_NOT_DEFINED, Project.MSG_WARN);
675         } catch (Throwable JavaDoc t) {
676             log(ERROR_UNABLE_TO_VERIFY_CLASS + classname
677                 + ERROR_LOADING_CAUSED_EXCEPTION
678                 + t.getMessage(), Project.MSG_WARN);
679         }
680         // we only get here if an exception has been thrown
681
return false;
682     }
683
684     /**
685      * Returns the topmost interface that extends Remote for a given
686      * class - if one exists.
687      * @param testClass the class to be tested
688      * @return the topmost interface that extends Remote, or null if there
689      * is none.
690      */

691     public Class JavaDoc getRemoteInterface(Class JavaDoc testClass) {
692         if (Remote JavaDoc.class.isAssignableFrom(testClass)) {
693             Class JavaDoc [] interfaces = testClass.getInterfaces();
694             if (interfaces != null) {
695                 for (int i = 0; i < interfaces.length; i++) {
696                     if (Remote JavaDoc.class.isAssignableFrom(interfaces[i])) {
697                         return interfaces[i];
698                     }
699                 }
700             }
701         }
702         return null;
703     }
704
705     /**
706      * Check to see if the class or (super)interfaces implement
707      * java.rmi.Remote.
708      */

709     private boolean isValidRmiRemote (Class JavaDoc testClass) {
710         return getRemoteInterface(testClass) != null;
711     }
712
713     /**
714      * Classloader for the user-specified classpath.
715      * @return the classloader
716      */

717     public ClassLoader JavaDoc getLoader() {
718         return loader;
719     }
720
721     /**
722      * Adds an "compiler" attribute to Commandline$Attribute used to
723      * filter command line attributes based on the current
724      * implementation.
725      */

726     public class ImplementationSpecificArgument extends
727         org.apache.tools.ant.util.facade.ImplementationSpecificArgument {
728
729         /**
730          * Only pass the specified argument if the
731          * chosen compiler implementation matches the
732          * value of this attribute. Legal values are
733          * the same as those in the above list of
734          * valid compilers.)
735          * @param impl the compiler to be used.
736          */

737         public void setCompiler(String JavaDoc impl) {
738             super.setImplementation(impl);
739         }
740     }
741
742 }
743
744
Popular Tags