KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > taskdefs > optional > jsp > JspC


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.jsp;
20
21 import java.io.File JavaDoc;
22 import java.util.Date JavaDoc;
23 import java.util.Enumeration 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.MatchingTask;
29 import org.apache.tools.ant.taskdefs.optional.jsp.compilers.JspCompilerAdapter;
30 import org.apache.tools.ant.taskdefs.optional.jsp.compilers.JspCompilerAdapterFactory;
31 import org.apache.tools.ant.types.Path;
32 import org.apache.tools.ant.types.Reference;
33
34 /**
35  * Runs a JSP compiler.
36  *
37  * <p> This task takes the given jsp files and compiles them into java
38  * files. It is then up to the user to compile the java files into classes.
39  *
40  * <p> The task requires the srcdir and destdir attributes to be
41  * set. This Task is a MatchingTask, so the files to be compiled can be
42  * specified using includes/excludes attributes or nested include/exclude
43  * elements. Optional attributes are verbose (set the verbosity level passed
44  * to jasper), package (name of the destination package for generated java
45  * classes and classpath (the classpath to use when running the jsp
46  * compiler).
47  * <p> This task supports the nested elements classpath (A Path) and
48  * classpathref (A Reference) which can be used in preference to the
49  * attribute classpath, if the jsp compiler is not already in the ant
50  * classpath.
51  *
52  * <p><h4>Usage</h4>
53  * <pre>
54  * &lt;jspc srcdir="${basedir}/src/war"
55  * destdir="${basedir}/gensrc"
56  * package="com.i3sp.jsp"
57  * verbose="9"&gt;
58  * &lt;include name="**\/*.jsp" /&gt;
59  * &lt;/jspc&gt;
60  * </pre>
61  *
62  * <p> Large Amount of cutting and pasting from the Javac task...
63  * @since 1.5
64  */

65 public class JspC extends MatchingTask {
66     private Path classpath;
67     private Path compilerClasspath;
68     private Path src;
69     private File JavaDoc destDir;
70     private String JavaDoc packageName;
71     /** name of the compiler to use */
72     private String JavaDoc compilerName = "jasper";
73
74     /**
75      * -ieplugin &lt;clsid&gt; Java Plugin classid for Internet Explorer
76      */

77     private String JavaDoc iepluginid;
78     private boolean mapped;
79     private int verbose = 0;
80     // CheckStyle:VisibilityModifier OFF - bc
81
protected Vector JavaDoc compileList = new Vector JavaDoc();
82     Vector JavaDoc javaFiles = new Vector JavaDoc();
83
84     /**
85      * flag to control action on execution trouble
86      */

87     protected boolean failOnError = true;
88
89     /**
90      * -uriroot &lt;dir&gt; The root directory that uri files should be resolved
91      * against,
92      */

93     private File JavaDoc uriroot;
94
95     /**
96      * -webinc &lt;file&gt; Creates partial servlet mappings for the -webapp option
97      */

98     private File JavaDoc webinc;
99
100     /**
101      * -webxml &lt;file&gt; Creates a complete web.xml when using the -webapp option.
102      */

103
104     private File JavaDoc webxml;
105
106     /**
107      * web apps
108      */

109     protected WebAppParameter webApp;
110
111
112
113     private static final String JavaDoc FAIL_MSG
114         = "Compile failed, messages should have been provided.";
115
116     // CheckStyle:VisibilityModifier ON
117

118     /**
119      * Set the path for source JSP files.
120      * @param srcDir the source path.
121      */

122     public void setSrcDir(Path srcDir) {
123         if (src == null) {
124             src = srcDir;
125         } else {
126             src.append(srcDir);
127         }
128     }
129
130     /**
131      * Get the source dir.
132      * @return the source path.
133      */

134     public Path getSrcDir() {
135         return src;
136     }
137
138     /**
139      * Set the destination directory into which the JSP source
140      * files should be compiled.
141      * @param destDir the destination directory.
142      */

143     public void setDestdir(File JavaDoc destDir) {
144         this.destDir = destDir;
145     }
146
147     /**
148      * Get the destination directory.
149      * @return the directory.
150      */

151     public File JavaDoc getDestdir() {
152         return destDir;
153     }
154
155     /**
156      * Set the name of the package the compiled jsp files should be in.
157      * @param pkg the name of the package.
158      */

159     public void setPackage(String JavaDoc pkg) {
160         this.packageName = pkg;
161     }
162
163     /**
164      * Get the name of the package.
165      * @return the package.
166      */

167     public String JavaDoc getPackage() {
168         return packageName;
169     }
170
171     /**
172      * Set the verbose level of the compiler
173      * @param i the verbose level to use.
174      */

175     public void setVerbose(int i) {
176         verbose = i;
177     }
178
179     /**
180      * Get the verbose level.
181      * @return the level.
182      */

183     public int getVerbose() {
184         return verbose;
185     }
186
187     /**
188      * Whether or not the build should halt if compilation fails.
189      * Defaults to <code>true</code>.
190      * @param fail a <code>boolean</code> value.
191      */

192     public void setFailonerror(boolean fail) {
193         failOnError = fail;
194     }
195     /**
196      * Gets the failonerror flag.
197      * @return the flag.
198      */

199     public boolean getFailonerror() {
200         return failOnError;
201     }
202
203     /**
204      * Get the IE CLASSID value.
205      * @return the value.
206      */

207     public String JavaDoc getIeplugin() {
208         return iepluginid;
209     }
210     /**
211      * Java Plugin CLASSID for Internet Explorer
212      * @param iepluginid the id to use.
213      */

214     public void setIeplugin(String JavaDoc iepluginid) {
215         this.iepluginid = iepluginid;
216     }
217
218     /**
219      * If true, generate separate write() calls for each HTML line
220      * in the JSP.
221      * @return mapping status
222      */

223     public boolean isMapped() {
224         return mapped;
225     }
226
227     /**
228      * If true, generate separate write() calls for each HTML line
229      * in the JSP.
230      * @param mapped a <code>boolean</code> value.
231      */

232     public void setMapped(boolean mapped) {
233         this.mapped = mapped;
234     }
235
236     /**
237      * The URI context of relative URI references in the JSP pages.
238      * If it does not exist then it is derived from the location
239      * of the file relative to the declared or derived value of uriroot.
240      *
241      * @param uribase The new Uribase value
242      */

243     public void setUribase(File JavaDoc uribase) {
244         log("Uribase is currently an unused parameter", Project.MSG_WARN);
245     }
246
247     /**
248      * Get the uri base value.
249      * @return the value.
250      */

251     public File JavaDoc getUribase() {
252         return uriroot;
253     }
254
255     /**
256      * The root directory that uri files should be resolved
257      * against. (Default is the directory jspc is invoked from)
258      *
259      * @param uriroot The new Uribase value
260      */

261     public void setUriroot(File JavaDoc uriroot) {
262         this.uriroot = uriroot;
263     }
264
265     /**
266      * Get the uri root value.
267      * @return the value.
268      */

269     public File JavaDoc getUriroot() {
270         return uriroot;
271     }
272
273
274     /**
275      * Set the classpath to be used for this compilation.
276      * @param cp the path to be used.
277      */

278     public void setClasspath(Path cp) {
279         if (classpath == null) {
280             classpath = cp;
281         } else {
282             classpath.append(cp);
283         }
284     }
285
286     /**
287      * Adds a path to the classpath.
288      * @return a path to be configured.
289      */

290     public Path createClasspath() {
291         if (classpath == null) {
292             classpath = new Path(getProject());
293         }
294         return classpath.createPath();
295     }
296
297     /**
298      * Adds a reference to a classpath defined elsewhere
299      * @param r a reference to a classpath.
300      */

301     public void setClasspathRef(Reference r) {
302         createClasspath().setRefid(r);
303     }
304
305     /**
306      * Get the classpath.
307      * @return the classpath.
308      */

309     public Path getClasspath() {
310         return classpath;
311     }
312
313     /**
314      * Set the classpath to be used to find this compiler adapter
315      * @param cp the compiler classpath.
316      */

317     public void setCompilerclasspath(Path cp) {
318         if (compilerClasspath == null) {
319             compilerClasspath = cp;
320         } else {
321             compilerClasspath.append(cp);
322         }
323     }
324
325     /**
326      * get the classpath used to find the compiler adapter
327      * @return the compiler classpath.
328      */

329     public Path getCompilerclasspath() {
330         return compilerClasspath;
331     }
332
333     /**
334      * Support nested compiler classpath, used to locate compiler adapter
335      * @return a path to be configured.
336      */

337     public Path createCompilerclasspath() {
338         if (compilerClasspath == null) {
339             compilerClasspath = new Path(getProject());
340         }
341         return compilerClasspath.createPath();
342     }
343
344     /**
345      * Filename for web.xml.
346      *
347      * @param webxml The new Webxml value
348      */

349     public void setWebxml(File JavaDoc webxml) {
350         this.webxml = webxml;
351     }
352
353     /**
354      * Filename for web.xml.
355      * @return The filename for web.xml.
356      */

357     public File JavaDoc getWebxml() {
358         return this.webxml;
359     }
360
361     /**
362      * output filename for the fraction of web.xml that lists
363      * servlets.
364      * @param webinc The new Webinc value
365      */

366     public void setWebinc(File JavaDoc webinc) {
367         this.webinc = webinc;
368     }
369
370     /**
371      * Get the webinc attribute.
372      * @return the webinc attribute.
373      */

374     public File JavaDoc getWebinc() {
375         return this.webinc;
376     }
377
378     /**
379      * Adds a single webapp.
380      *
381      * @param webappParam add a web app parameter
382      * @throws BuildException if more than one webapp is specified.
383      */

384     public void addWebApp(WebAppParameter webappParam)
385         throws BuildException {
386         //demand create vector of filesets
387
if (webApp == null) {
388             webApp = webappParam;
389         } else {
390             throw new BuildException("Only one webapp can be specified");
391         }
392     }
393
394     /**
395      * Get the web app.
396      * @return the web app attribute.
397      */

398     public WebAppParameter getWebApp() {
399         return webApp;
400     }
401
402     /**
403      * Class name of a JSP compiler adapter.
404      * @param compiler the compiler class name.
405      */

406     public void setCompiler(String JavaDoc compiler) {
407         this.compilerName = compiler;
408     }
409
410     /**
411     * get the list of files to compile
412     * @return the list of files.
413     */

414     public Vector JavaDoc getCompileList() {
415         return compileList;
416     }
417
418     /**
419      * execute by building up a list of files that
420      * have changed and hand them off to a jsp compiler
421      * @throws BuildException on error.
422      */

423     public void execute()
424         throws BuildException {
425
426         // make sure that we've got a destdir
427
if (destDir == null) {
428             throw new BuildException("destdir attribute must be set!",
429                                      getLocation());
430         }
431
432         if (!destDir.isDirectory()) {
433             throw new BuildException("destination directory \"" + destDir
434                     + "\" does not exist or is not a directory", getLocation());
435         }
436
437         File JavaDoc dest = getActualDestDir();
438
439         //bind to a compiler
440
JspCompilerAdapter compiler =
441             JspCompilerAdapterFactory.getCompiler(compilerName, this,
442                 getProject().createClassLoader(compilerClasspath));
443
444         //if we are a webapp, hand off to the compiler, which had better handle it
445
if (webApp != null) {
446             doCompilation(compiler);
447             return;
448         }
449
450         // make sure that we've got a srcdir
451
if (src == null) {
452             throw new BuildException("srcdir attribute must be set!",
453                                      getLocation());
454         }
455         String JavaDoc [] list = src.list();
456         if (list.length == 0) {
457             throw new BuildException("srcdir attribute must be set!",
458                     getLocation());
459         }
460
461
462         // if the compiler does its own dependency stuff, we just call it right now
463
if (compiler.implementsOwnDependencyChecking()) {
464             doCompilation(compiler);
465             return;
466         }
467
468         //the remainder of this method is only for compilers that need their dependency work done
469
JspMangler mangler = compiler.createMangler();
470
471         // scan source directories and dest directory to build up both copy
472
// lists and compile lists
473
resetFileLists();
474         int filecount = 0;
475         for (int i = 0; i < list.length; i++) {
476             File JavaDoc srcDir = getProject().resolveFile(list[i]);
477             if (!srcDir.exists()) {
478                 throw new BuildException("srcdir \"" + srcDir.getPath()
479                     + "\" does not exist!", getLocation());
480             }
481             DirectoryScanner ds = this.getDirectoryScanner(srcDir);
482             String JavaDoc[] files = ds.getIncludedFiles();
483             filecount = files.length;
484             scanDir(srcDir, dest, mangler, files);
485         }
486
487         // compile the source files
488

489         log("compiling " + compileList.size() + " files", Project.MSG_VERBOSE);
490
491         if (compileList.size() > 0) {
492
493             log("Compiling " + compileList.size() + " source file"
494                 + (compileList.size() == 1 ? "" : "s")
495                 + " to "
496                 + dest);
497             doCompilation(compiler);
498
499         } else {
500             if (filecount == 0) {
501                 log("there were no files to compile", Project.MSG_INFO);
502             } else {
503                 log("all files are up to date", Project.MSG_VERBOSE);
504             }
505         }
506     }
507
508     /**
509      * calculate where the files will end up:
510      * this is destDir or it id destDir + the package name
511      */

512     private File JavaDoc getActualDestDir() {
513         File JavaDoc dest = null;
514         if (packageName == null) {
515             dest = destDir;
516         } else {
517             String JavaDoc path = destDir.getPath() + File.separatorChar
518                 + packageName.replace('.', File.separatorChar);
519             dest = new File JavaDoc(path);
520         }
521         return dest;
522     }
523
524     /**
525      * do the compile
526      */

527     private void doCompilation(JspCompilerAdapter compiler)
528             throws BuildException {
529         // now we need to populate the compiler adapter
530
compiler.setJspc(this);
531
532         // finally, lets execute the compiler!!
533
if (!compiler.execute()) {
534             if (failOnError) {
535                 throw new BuildException(FAIL_MSG, getLocation());
536             } else {
537                 log(FAIL_MSG, Project.MSG_ERR);
538             }
539         }
540     }
541
542     /**
543      * Clear the list of files to be compiled and copied..
544      */

545     protected void resetFileLists() {
546         compileList.removeAllElements();
547     }
548
549     /**
550      * Scans the directory looking for source files to be compiled.
551      * The results are returned in the class variable compileList
552      * @param srcDir the source directory.
553      * @param dest the destination directory.
554      * @param mangler the jsp filename mangler.
555      * @param files the file names to mangle.
556      */

557     protected void scanDir(
558         File JavaDoc srcDir, File JavaDoc dest, JspMangler mangler, String JavaDoc[] files) {
559
560         long now = (new Date JavaDoc()).getTime();
561
562         for (int i = 0; i < files.length; i++) {
563             String JavaDoc filename = files[i];
564             File JavaDoc srcFile = new File JavaDoc(srcDir, filename);
565             File JavaDoc javaFile = mapToJavaFile(mangler, srcFile, srcDir, dest);
566             if (javaFile == null) {
567                 continue;
568             }
569
570             if (srcFile.lastModified() > now) {
571                 log("Warning: file modified in the future: " + filename,
572                         Project.MSG_WARN);
573             }
574             boolean shouldCompile = false;
575             shouldCompile = isCompileNeeded(srcFile, javaFile);
576             if (shouldCompile) {
577                compileList.addElement(srcFile.getAbsolutePath());
578                javaFiles.addElement(javaFile);
579             }
580         }
581     }
582
583     /**
584      * Test whether or not compilation is needed. A return value of
585      * <code>true<code> means yes, <code>false</code> means
586      * our tests do not indicate this, but as the TLDs are
587      * not used for dependency checking this is not guaranteed.
588      * The current tests are
589      * <ol>
590      * <li>no dest file
591      * <li>dest file out of date w.r.t source
592      * <li>dest file zero bytes long
593      * </ol>
594      * @param srcFile JSP source file
595      * @param javaFile JSP dest file
596      * @return true if a compile is definately needed.
597      *
598      */

599     private boolean isCompileNeeded(File JavaDoc srcFile, File JavaDoc javaFile) {
600         boolean shouldCompile = false;
601         if (!javaFile.exists()) {
602             shouldCompile = true;
603             log("Compiling " + srcFile.getPath()
604                 + " because java file " + javaFile.getPath()
605                 + " does not exist", Project.MSG_VERBOSE);
606             } else {
607                 if (srcFile.lastModified() > javaFile.lastModified()) {
608                     shouldCompile = true;
609                     log("Compiling " + srcFile.getPath()
610                         + " because it is out of date with respect to "
611                         + javaFile.getPath(),
612                         Project.MSG_VERBOSE);
613                 } else {
614                     if (javaFile.length() == 0) {
615                         shouldCompile = true;
616                         log("Compiling " + srcFile.getPath()
617                             + " because java file " + javaFile.getPath()
618                             + " is empty", Project.MSG_VERBOSE);
619                     }
620                 }
621         }
622         return shouldCompile;
623     }
624
625
626     /**
627      * get a filename from our jsp file.
628      * @param mangler the jsp filename managler.
629      * @param srcFile the source file.
630      * @param srcDir the source directory.
631      * @param dest the destination directory.
632      * @return the filename.
633      * @todo support packages and subdirs
634      */

635     protected File JavaDoc mapToJavaFile(JspMangler mangler, File JavaDoc srcFile, File JavaDoc srcDir, File JavaDoc dest) {
636         if (!srcFile.getName().endsWith(".jsp")) {
637             return null;
638         }
639         String JavaDoc javaFileName = mangler.mapJspToJavaName(srcFile);
640 // String srcFileDir=srcFile.getParent();
641
return new File JavaDoc(dest, javaFileName);
642     }
643
644     /**
645      * delete any java output files that are empty
646      * this is to get around a little defect in jasper: when it
647      * fails, it leaves incomplete files around.
648      */

649     public void deleteEmptyJavaFiles() {
650         if (javaFiles != null) {
651             Enumeration JavaDoc e = javaFiles.elements();
652             while (e.hasMoreElements()) {
653                 File JavaDoc file = (File JavaDoc) e.nextElement();
654                 if (file.exists() && file.length() == 0) {
655                     log("deleting empty output file " + file);
656                     file.delete();
657                 }
658             }
659         }
660     }
661
662     /**
663      * static inner class used as a parameter element
664      */

665     public static class WebAppParameter {
666
667         /**
668          * the sole option
669          */

670         private File JavaDoc directory;
671
672         /**
673          * query current directory
674          * @return the directory.
675          */

676         public File JavaDoc getDirectory() {
677             return directory;
678         }
679
680         /**
681          * set directory; alternate syntax
682          * @param directory the base dir.
683          */

684         public void setBaseDir(File JavaDoc directory) {
685             this.directory = directory;
686         }
687     //end inner class
688
}
689
690
691 //end class
692
}
693
Popular Tags