1 | /*
|
---|
2 | * Copyright 2000,2002-2004 The Apache Software Foundation
|
---|
3 | *
|
---|
4 | * Licensed under the Apache License, Version 2.0 (the "License");
|
---|
5 | * you may not use this file except in compliance with the License.
|
---|
6 | * You may obtain a copy of the License at
|
---|
7 | *
|
---|
8 | * http://www.apache.org/licenses/LICENSE-2.0
|
---|
9 | *
|
---|
10 | * Unless required by applicable law or agreed to in writing, software
|
---|
11 | * distributed under the License is distributed on an "AS IS" BASIS,
|
---|
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
---|
13 | * See the License for the specific language governing permissions and
|
---|
14 | * limitations under the License.
|
---|
15 | *
|
---|
16 | */
|
---|
17 | package org.apache.tools.ant.taskdefs.optional.jsp;
|
---|
18 |
|
---|
19 | //apache/ant imports
|
---|
20 | import java.io.File;
|
---|
21 | import java.util.Date;
|
---|
22 | import java.util.StringTokenizer;
|
---|
23 | import java.util.Vector;
|
---|
24 | import org.apache.tools.ant.BuildException;
|
---|
25 | import org.apache.tools.ant.DirectoryScanner;
|
---|
26 | import org.apache.tools.ant.Project;
|
---|
27 | import org.apache.tools.ant.taskdefs.Java;
|
---|
28 | import org.apache.tools.ant.taskdefs.MatchingTask;
|
---|
29 | import org.apache.tools.ant.types.Path;
|
---|
30 |
|
---|
31 | /**
|
---|
32 | * Precompiles JSP's using WebLogic's JSP compiler (weblogic.jspc).
|
---|
33 | *
|
---|
34 | *
|
---|
35 | * Tested only on Weblogic 4.5.1 - NT4.0 and Solaris 5.7
|
---|
36 | *
|
---|
37 | * required attributes
|
---|
38 | * src : root of source tree for JSP, ie, the document root for your weblogic server
|
---|
39 | * dest : root of destination directory, what you have set as
|
---|
40 | * WorkingDir in the weblogic properties
|
---|
41 | * package : start package name under which your JSP's would be compiled
|
---|
42 | *
|
---|
43 | * other attributes
|
---|
44 | * classpath
|
---|
45 | *
|
---|
46 | * A classpath should be set which contains the weblogic classes as well as all
|
---|
47 | * application classes referenced by the JSP. The system classpath is also
|
---|
48 | * appended when the jspc is called, so you may choose to put everything in
|
---|
49 | * the classpath while calling Ant. However, since presumably the JSP's will
|
---|
50 | * reference classes being build by Ant, it would be better to explicitly add
|
---|
51 | * the classpath in the task
|
---|
52 | *
|
---|
53 | * The task checks timestamps on the JSP's and the generated classes, and compiles
|
---|
54 | * only those files that have changed.
|
---|
55 | *
|
---|
56 | * It follows the weblogic naming convention of putting classes in
|
---|
57 | * <b> _dirName/_fileName.class for dirname/fileName.jsp </b>
|
---|
58 | *
|
---|
59 | * Limitation: It compiles the files thru the Classic compiler only.
|
---|
60 | * Limitation: Since it is my experience that weblogic jspc throws out of
|
---|
61 | * memory error on being given too many files at one go, it is
|
---|
62 | * called multiple times with one jsp file each.
|
---|
63 | *
|
---|
64 | * <pre>
|
---|
65 | * example
|
---|
66 | * <target name="jspcompile" depends="compile">
|
---|
67 | * <wljspc src="c:\\weblogic\\myserver\\public_html"
|
---|
68 | * dest="c:\\weblogic\\myserver\\serverclasses" package="myapp.jsp">
|
---|
69 | * <classpath>
|
---|
70 | * <pathelement location="${weblogic.classpath}" />
|
---|
71 | * <pathelement path="${compile.dest}" />
|
---|
72 | * </classpath>
|
---|
73 | *
|
---|
74 | * </wljspc>
|
---|
75 | * </target>
|
---|
76 | * </pre>
|
---|
77 | *
|
---|
78 | */
|
---|
79 |
|
---|
80 | public class WLJspc extends MatchingTask {
|
---|
81 | //TODO Test on other versions of weblogic
|
---|
82 | //TODO add more attributes to the task, to take care of all jspc options
|
---|
83 | //TODO Test on Unix
|
---|
84 |
|
---|
85 | /** root of compiled files tree */
|
---|
86 | private File destinationDirectory;
|
---|
87 |
|
---|
88 | /** root of source files tree */
|
---|
89 | private File sourceDirectory;
|
---|
90 |
|
---|
91 | /** package under which resultant classes will reside */
|
---|
92 | private String destinationPackage;
|
---|
93 |
|
---|
94 | /** classpath used to compile the jsp files. */
|
---|
95 | private Path compileClasspath;
|
---|
96 |
|
---|
97 | //private String compilerPath; //fully qualified name for the compiler executable
|
---|
98 |
|
---|
99 | private String pathToPackage = "";
|
---|
100 | private Vector filesToDo = new Vector();
|
---|
101 |
|
---|
102 | public void execute() throws BuildException {
|
---|
103 | if (!destinationDirectory.isDirectory()) {
|
---|
104 | throw new BuildException("destination directory "
|
---|
105 | + destinationDirectory.getPath() + " is not valid");
|
---|
106 | }
|
---|
107 |
|
---|
108 | if (!sourceDirectory.isDirectory()) {
|
---|
109 | throw new BuildException("src directory "
|
---|
110 | + sourceDirectory.getPath() + " is not valid");
|
---|
111 | }
|
---|
112 |
|
---|
113 | if (destinationPackage == null) {
|
---|
114 | throw new BuildException("package attribute must be present.",
|
---|
115 | getLocation());
|
---|
116 | }
|
---|
117 |
|
---|
118 |
|
---|
119 | pathToPackage
|
---|
120 | = this.destinationPackage.replace('.', File.separatorChar);
|
---|
121 | // get all the files in the sourceDirectory
|
---|
122 | DirectoryScanner ds = super.getDirectoryScanner(sourceDirectory);
|
---|
123 |
|
---|
124 | //use the systemclasspath as well, to include the ant jar
|
---|
125 | if (compileClasspath == null) {
|
---|
126 | compileClasspath = new Path(getProject());
|
---|
127 | }
|
---|
128 |
|
---|
129 | compileClasspath = compileClasspath.concatSystemClasspath();
|
---|
130 | String[] files = ds.getIncludedFiles();
|
---|
131 |
|
---|
132 | //Weblogic.jspc calls System.exit() ... have to fork
|
---|
133 | // Therefore, takes loads of time
|
---|
134 | // Can pass directories at a time (*.jsp) but easily runs out of
|
---|
135 | // memory on hefty dirs (even on a Sun)
|
---|
136 | Java helperTask = (Java) getProject().createTask("java");
|
---|
137 | helperTask.setFork(true);
|
---|
138 | helperTask.setClassname("weblogic.jspc");
|
---|
139 | helperTask.setTaskName(getTaskName());
|
---|
140 | String[] args = new String[12];
|
---|
141 |
|
---|
142 | File jspFile = null;
|
---|
143 | String parents = "";
|
---|
144 | int j = 0;
|
---|
145 | //XXX this array stuff is a remnant of prev trials.. gotta remove.
|
---|
146 | args[j++] = "-d";
|
---|
147 | args[j++] = destinationDirectory.getAbsolutePath().trim();
|
---|
148 | args[j++] = "-docroot";
|
---|
149 | args[j++] = sourceDirectory.getAbsolutePath().trim();
|
---|
150 | args[j++] = "-keepgenerated"; //TODO: Parameterise ??
|
---|
151 | //Call compiler as class... dont want to fork again
|
---|
152 | //Use classic compiler -- can be parameterised?
|
---|
153 | args[j++] = "-compilerclass";
|
---|
154 | args[j++] = "sun.tools.javac.Main";
|
---|
155 | //Weblogic jspc does not seem to work unless u explicitly set this...
|
---|
156 | // Does not take the classpath from the env....
|
---|
157 | // Am i missing something about the Java task??
|
---|
158 | args[j++] = "-classpath";
|
---|
159 | args[j++] = compileClasspath.toString();
|
---|
160 |
|
---|
161 | this.scanDir(files);
|
---|
162 | log("Compiling " + filesToDo.size() + " JSP files");
|
---|
163 |
|
---|
164 | for (int i = 0; i < filesToDo.size(); i++) {
|
---|
165 | //XXX
|
---|
166 | // All this to get package according to weblogic standards
|
---|
167 | // Can be written better... this is too hacky!
|
---|
168 | // Careful.. similar code in scanDir , but slightly different!!
|
---|
169 | String filename = (String) filesToDo.elementAt(i);
|
---|
170 | jspFile = new File(filename);
|
---|
171 | args[j] = "-package";
|
---|
172 | parents = jspFile.getParent();
|
---|
173 | if ((parents != null) && (!("").equals(parents))) {
|
---|
174 | parents = this.replaceString(parents, File.separator, "_.");
|
---|
175 | args[j + 1] = destinationPackage + "." + "_" + parents;
|
---|
176 | } else {
|
---|
177 | args[j + 1] = destinationPackage;
|
---|
178 | }
|
---|
179 |
|
---|
180 |
|
---|
181 | args[j + 2] = sourceDirectory + File.separator + filename;
|
---|
182 | helperTask.clearArgs();
|
---|
183 |
|
---|
184 | for (int x = 0; x < j + 3; x++) {
|
---|
185 | helperTask.createArg().setValue(args[x]);
|
---|
186 | }
|
---|
187 |
|
---|
188 | helperTask.setClasspath(compileClasspath);
|
---|
189 | if (helperTask.executeJava() != 0) {
|
---|
190 | log(filename + " failed to compile", Project.MSG_WARN);
|
---|
191 | }
|
---|
192 | }
|
---|
193 | }
|
---|
194 |
|
---|
195 |
|
---|
196 |
|
---|
197 | /**
|
---|
198 | * Set the classpath to be used for this compilation.
|
---|
199 | *
|
---|
200 | */
|
---|
201 | public void setClasspath(Path classpath) {
|
---|
202 | if (compileClasspath == null) {
|
---|
203 | compileClasspath = classpath;
|
---|
204 | } else {
|
---|
205 | compileClasspath.append(classpath);
|
---|
206 | }
|
---|
207 | }
|
---|
208 |
|
---|
209 | /**
|
---|
210 | * Maybe creates a nested classpath element.
|
---|
211 | */
|
---|
212 | public Path createClasspath() {
|
---|
213 | if (compileClasspath == null) {
|
---|
214 | compileClasspath = new Path(getProject());
|
---|
215 | }
|
---|
216 | return compileClasspath;
|
---|
217 | }
|
---|
218 |
|
---|
219 | /**
|
---|
220 | * Set the directory containing the source jsp's
|
---|
221 | *
|
---|
222 | *
|
---|
223 | * @param dirName the directory containg the source jsp's
|
---|
224 | */
|
---|
225 | public void setSrc(File dirName) {
|
---|
226 |
|
---|
227 | sourceDirectory = dirName;
|
---|
228 | }
|
---|
229 |
|
---|
230 | /**
|
---|
231 | * Set the directory containing the source jsp's
|
---|
232 | *
|
---|
233 | *
|
---|
234 | * @param dirName the directory containg the source jsp's
|
---|
235 | */
|
---|
236 | public void setDest(File dirName) {
|
---|
237 |
|
---|
238 | destinationDirectory = dirName;
|
---|
239 | }
|
---|
240 |
|
---|
241 | /**
|
---|
242 | * Set the package under which the compiled classes go
|
---|
243 | *
|
---|
244 | * @param packageName the package name for the clases
|
---|
245 | */
|
---|
246 | public void setPackage(String packageName) {
|
---|
247 |
|
---|
248 | destinationPackage = packageName;
|
---|
249 | }
|
---|
250 |
|
---|
251 |
|
---|
252 |
|
---|
253 | protected void scanDir(String files[]) {
|
---|
254 |
|
---|
255 | long now = (new Date()).getTime();
|
---|
256 | File jspFile = null;
|
---|
257 | String parents = null;
|
---|
258 | String pack = "";
|
---|
259 | for (int i = 0; i < files.length; i++) {
|
---|
260 | File srcFile = new File(this.sourceDirectory, files[i]);
|
---|
261 | //XXX
|
---|
262 | // All this to convert source to destination directory according
|
---|
263 | // to weblogic standards Can be written better... this is too hacky!
|
---|
264 | jspFile = new File(files[i]);
|
---|
265 | parents = jspFile.getParent();
|
---|
266 |
|
---|
267 | if ((parents != null) && (!("").equals(parents))) {
|
---|
268 | parents = this.replaceString(parents, File.separator, "_/");
|
---|
269 | pack = pathToPackage + File.separator + "_" + parents;
|
---|
270 | } else {
|
---|
271 | pack = pathToPackage;
|
---|
272 | }
|
---|
273 |
|
---|
274 | String filePath = pack + File.separator + "_";
|
---|
275 | int startingIndex = files[i].lastIndexOf(File.separator) != -1
|
---|
276 | ? files[i].lastIndexOf(File.separator) + 1 : 0;
|
---|
277 | int endingIndex = files[i].indexOf(".jsp");
|
---|
278 | if (endingIndex == -1) {
|
---|
279 | log("Skipping " + files[i] + ". Not a JSP",
|
---|
280 | Project.MSG_VERBOSE);
|
---|
281 | continue;
|
---|
282 | }
|
---|
283 |
|
---|
284 | filePath += files[i].substring(startingIndex, endingIndex);
|
---|
285 | filePath += ".class";
|
---|
286 | File classFile = new File(this.destinationDirectory, filePath);
|
---|
287 |
|
---|
288 | if (srcFile.lastModified() > now) {
|
---|
289 | log("Warning: file modified in the future: "
|
---|
290 | + files[i], Project.MSG_WARN);
|
---|
291 | }
|
---|
292 | if (srcFile.lastModified() > classFile.lastModified()) {
|
---|
293 | filesToDo.addElement(files[i]);
|
---|
294 | log("Recompiling File " + files[i], Project.MSG_VERBOSE);
|
---|
295 | }
|
---|
296 | }
|
---|
297 | }
|
---|
298 |
|
---|
299 |
|
---|
300 | protected String replaceString(String inpString, String escapeChars,
|
---|
301 | String replaceChars) {
|
---|
302 | String localString = "";
|
---|
303 | int numTokens = 0;
|
---|
304 | StringTokenizer st = new StringTokenizer(inpString, escapeChars, true);
|
---|
305 | numTokens = st.countTokens();
|
---|
306 | for (int i = 0; i < numTokens; i++) {
|
---|
307 | String test = st.nextToken();
|
---|
308 | test = (test.equals(escapeChars) ? replaceChars : test);
|
---|
309 | localString += test;
|
---|
310 | }
|
---|
311 | return localString;
|
---|
312 | }
|
---|
313 | }
|
---|