KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > taskdefs > optional > javacc > JJTree


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.javacc;
20
21 import java.io.File JavaDoc;
22 import java.io.IOException JavaDoc;
23 import java.util.Enumeration JavaDoc;
24 import java.util.Hashtable JavaDoc;
25
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.Execute;
30 import org.apache.tools.ant.taskdefs.LogStreamHandler;
31 import org.apache.tools.ant.types.Commandline;
32 import org.apache.tools.ant.types.CommandlineJava;
33 import org.apache.tools.ant.types.Path;
34 import org.apache.tools.ant.util.JavaEnvUtils;
35
36 /**
37  * Runs the JJTree compiler compiler.
38  *
39  */

40 public class JJTree extends Task {
41
42     // keys to optional attributes
43
private static final String JavaDoc OUTPUT_FILE = "OUTPUT_FILE";
44     private static final String JavaDoc BUILD_NODE_FILES = "BUILD_NODE_FILES";
45     private static final String JavaDoc MULTI = "MULTI";
46     private static final String JavaDoc NODE_DEFAULT_VOID = "NODE_DEFAULT_VOID";
47     private static final String JavaDoc NODE_FACTORY = "NODE_FACTORY";
48     private static final String JavaDoc NODE_SCOPE_HOOK = "NODE_SCOPE_HOOK";
49     private static final String JavaDoc NODE_USES_PARSER = "NODE_USES_PARSER";
50     private static final String JavaDoc STATIC = "STATIC";
51     private static final String JavaDoc VISITOR = "VISITOR";
52
53     private static final String JavaDoc NODE_PACKAGE = "NODE_PACKAGE";
54     private static final String JavaDoc VISITOR_EXCEPTION = "VISITOR_EXCEPTION";
55     private static final String JavaDoc NODE_PREFIX = "NODE_PREFIX";
56
57     private final Hashtable JavaDoc optionalAttrs = new Hashtable JavaDoc();
58
59     private String JavaDoc outputFile = null;
60
61     private static final String JavaDoc DEFAULT_SUFFIX = ".jj";
62
63     // required attributes
64
private File JavaDoc outputDirectory = null;
65     private File JavaDoc targetFile = null;
66     private File JavaDoc javaccHome = null;
67
68     private CommandlineJava cmdl = new CommandlineJava();
69
70
71     /**
72      * Sets the BUILD_NODE_FILES grammar option.
73      * @param buildNodeFiles a <code>boolean</code> value.
74      */

75     public void setBuildnodefiles(boolean buildNodeFiles) {
76         optionalAttrs.put(BUILD_NODE_FILES, buildNodeFiles ? Boolean.TRUE : Boolean.FALSE);
77     }
78
79     /**
80      * Sets the MULTI grammar option.
81      * @param multi a <code>boolean</code> value.
82      */

83     public void setMulti(boolean multi) {
84         optionalAttrs.put(MULTI, multi ? Boolean.TRUE : Boolean.FALSE);
85     }
86
87     /**
88      * Sets the NODE_DEFAULT_VOID grammar option.
89      * @param nodeDefaultVoid a <code>boolean</code> value.
90      */

91     public void setNodedefaultvoid(boolean nodeDefaultVoid) {
92         optionalAttrs.put(NODE_DEFAULT_VOID, nodeDefaultVoid ? Boolean.TRUE : Boolean.FALSE);
93     }
94
95     /**
96      * Sets the NODE_FACTORY grammar option.
97      * @param nodeFactory a <code>boolean</code> value.
98      */

99     public void setNodefactory(boolean nodeFactory) {
100         optionalAttrs.put(NODE_FACTORY, nodeFactory ? Boolean.TRUE : Boolean.FALSE);
101     }
102
103     /**
104      * Sets the NODE_SCOPE_HOOK grammar option.
105      * @param nodeScopeHook a <code>boolean</code> value.
106      */

107     public void setNodescopehook(boolean nodeScopeHook) {
108         optionalAttrs.put(NODE_SCOPE_HOOK, nodeScopeHook ? Boolean.TRUE : Boolean.FALSE);
109     }
110
111     /**
112      * Sets the NODE_USES_PARSER grammar option.
113      * @param nodeUsesParser a <code>boolean</code> value.
114      */

115     public void setNodeusesparser(boolean nodeUsesParser) {
116         optionalAttrs.put(NODE_USES_PARSER, nodeUsesParser ? Boolean.TRUE : Boolean.FALSE);
117     }
118
119     /**
120      * Sets the STATIC grammar option.
121      * @param staticParser a <code>boolean</code> value.
122      */

123     public void setStatic(boolean staticParser) {
124         optionalAttrs.put(STATIC, staticParser ? Boolean.TRUE : Boolean.FALSE);
125     }
126
127     /**
128      * Sets the VISITOR grammar option.
129      * @param visitor a <code>boolean</code> value.
130      */

131     public void setVisitor(boolean visitor) {
132         optionalAttrs.put(VISITOR, visitor ? Boolean.TRUE : Boolean.FALSE);
133     }
134
135     /**
136      * Sets the NODE_PACKAGE grammar option.
137      * @param nodePackage the option to use.
138      */

139     public void setNodepackage(String JavaDoc nodePackage) {
140         optionalAttrs.put(NODE_PACKAGE, nodePackage);
141     }
142
143     /**
144      * Sets the VISITOR_EXCEPTION grammar option.
145      * @param visitorException the option to use.
146      */

147     public void setVisitorException(String JavaDoc visitorException) {
148         optionalAttrs.put(VISITOR_EXCEPTION, visitorException);
149     }
150
151     /**
152      * Sets the NODE_PREFIX grammar option.
153      * @param nodePrefix the option to use.
154      */

155     public void setNodeprefix(String JavaDoc nodePrefix) {
156         optionalAttrs.put(NODE_PREFIX, nodePrefix);
157     }
158
159     /**
160      * The directory to write the generated JavaCC grammar and node files to.
161      * If not set, the files are written to the directory
162      * containing the grammar file.
163      * @param outputDirectory the output directory.
164      */

165     public void setOutputdirectory(File JavaDoc outputDirectory) {
166         this.outputDirectory = outputDirectory;
167     }
168
169     /**
170      * The outputfile to write the generated JavaCC grammar file to.
171      * If not set, the file is written with the same name as
172      * the JJTree grammar file with a suffix .jj.
173      * @param outputFile the output file name.
174      */

175     public void setOutputfile(String JavaDoc outputFile) {
176         this.outputFile = outputFile;
177     }
178
179     /**
180      * The jjtree grammar file to process.
181      * @param targetFile the grammar file.
182      */

183     public void setTarget(File JavaDoc targetFile) {
184         this.targetFile = targetFile;
185     }
186
187     /**
188      * The directory containing the JavaCC distribution.
189      * @param javaccHome the directory containing JavaCC.
190      */

191     public void setJavacchome(File JavaDoc javaccHome) {
192         this.javaccHome = javaccHome;
193     }
194
195     /**
196      * Constructor
197      */

198     public JJTree() {
199         cmdl.setVm(JavaEnvUtils.getJreExecutable("java"));
200     }
201
202     /**
203      * Run the task.
204      * @throws BuildException on error.
205      */

206     public void execute() throws BuildException {
207
208         // load command line with optional attributes
209
Enumeration JavaDoc iter = optionalAttrs.keys();
210         while (iter.hasMoreElements()) {
211             String JavaDoc name = (String JavaDoc) iter.nextElement();
212             Object JavaDoc value = optionalAttrs.get(name);
213             cmdl.createArgument().setValue("-" + name + ":" + value.toString());
214         }
215
216         if (targetFile == null || !targetFile.isFile()) {
217             throw new BuildException("Invalid target: " + targetFile);
218         }
219
220         File JavaDoc javaFile = null;
221
222         // use the directory containing the target as the output directory
223
if (outputDirectory == null) {
224             // convert backslashes to slashes, otherwise jjtree will
225
// put this as comments and this seems to confuse javacc
226
cmdl.createArgument().setValue("-OUTPUT_DIRECTORY:"
227                                            + getDefaultOutputDirectory());
228
229             javaFile = new File JavaDoc(createOutputFileName(targetFile, outputFile,
230                                                      null));
231         } else {
232             if (!outputDirectory.isDirectory()) {
233                 throw new BuildException("'outputdirectory' " + outputDirectory
234                                          + " is not a directory.");
235             }
236
237             // convert backslashes to slashes, otherwise jjtree will
238
// put this as comments and this seems to confuse javacc
239
cmdl.createArgument().setValue("-OUTPUT_DIRECTORY:"
240                                            + outputDirectory.getAbsolutePath()
241                                              .replace('\\', '/'));
242
243             javaFile = new File JavaDoc(createOutputFileName(targetFile, outputFile,
244                                                      outputDirectory
245                                                      .getPath()));
246         }
247
248         if (javaFile.exists()
249             && targetFile.lastModified() < javaFile.lastModified()) {
250             log("Target is already built - skipping (" + targetFile + ")",
251                 Project.MSG_VERBOSE);
252             return;
253         }
254
255         if (outputFile != null) {
256             cmdl.createArgument().setValue("-" + OUTPUT_FILE + ":"
257                                            + outputFile.replace('\\', '/'));
258         }
259
260         cmdl.createArgument().setValue(targetFile.getAbsolutePath());
261
262         final Path classpath = cmdl.createClasspath(getProject());
263         final File JavaDoc javaccJar = JavaCC.getArchiveFile(javaccHome);
264         classpath.createPathElement().setPath(javaccJar.getAbsolutePath());
265         classpath.addJavaRuntime();
266
267         cmdl.setClassname(JavaCC.getMainClass(classpath,
268                                               JavaCC.TASKDEF_TYPE_JJTREE));
269
270         final Commandline.Argument arg = cmdl.createVmArgument();
271         arg.setValue("-mx140M");
272         arg.setValue("-Dinstall.root=" + javaccHome.getAbsolutePath());
273
274         final Execute process =
275             new Execute(new LogStreamHandler(this,
276                                              Project.MSG_INFO,
277                                              Project.MSG_INFO),
278                         null);
279         log(cmdl.describeCommand(), Project.MSG_VERBOSE);
280         process.setCommandline(cmdl.getCommandline());
281
282         try {
283             if (process.execute() != 0) {
284                 throw new BuildException("JJTree failed.");
285             }
286         } catch (IOException JavaDoc e) {
287             throw new BuildException("Failed to launch JJTree", e);
288         }
289     }
290
291     private String JavaDoc createOutputFileName(File JavaDoc destFile, String JavaDoc optionalOutputFile,
292                                         String JavaDoc outputDir) {
293         optionalOutputFile = validateOutputFile(optionalOutputFile,
294                                                 outputDir);
295         String JavaDoc jjtreeFile = destFile.getAbsolutePath().replace('\\', '/');
296
297         if ((optionalOutputFile == null) || optionalOutputFile.equals("")) {
298             int filePos = jjtreeFile.lastIndexOf("/");
299
300             if (filePos >= 0) {
301                 jjtreeFile = jjtreeFile.substring(filePos + 1);
302             }
303
304             int suffixPos = jjtreeFile.lastIndexOf('.');
305
306             if (suffixPos == -1) {
307                 optionalOutputFile = jjtreeFile + DEFAULT_SUFFIX;
308             } else {
309                 String JavaDoc currentSuffix = jjtreeFile.substring(suffixPos);
310
311                 if (currentSuffix.equals(DEFAULT_SUFFIX)) {
312                     optionalOutputFile = jjtreeFile + DEFAULT_SUFFIX;
313                 } else {
314                     optionalOutputFile = jjtreeFile.substring(0, suffixPos)
315                         + DEFAULT_SUFFIX;
316                 }
317             }
318         }
319
320         if ((outputDir == null) || outputDir.equals("")) {
321             outputDir = getDefaultOutputDirectory();
322         }
323
324         return (outputDir + "/" + optionalOutputFile).replace('\\', '/');
325     }
326
327     /**
328      * When running JJTree from an Ant taskdesk the -OUTPUT_DIRECTORY must
329      * always be set. But when -OUTPUT_DIRECTORY is set, -OUTPUT_FILE is
330      * handled as if relative of this -OUTPUT_DIRECTORY. Thus when the
331      * -OUTPUT_FILE is absolute or contains a drive letter we have a problem.
332      *
333      * @param destFile
334      * @param outputDir
335      * @return
336      * @throws BuildException
337      */

338     private String JavaDoc validateOutputFile(String JavaDoc destFile,
339                                       String JavaDoc outputDir)
340         throws BuildException {
341         if (destFile == null) {
342             return null;
343         }
344
345         if ((outputDir == null)
346             && (destFile.startsWith("/") || destFile.startsWith("\\"))) {
347             String JavaDoc relativeOutputFile = makeOutputFileRelative(destFile);
348             setOutputfile(relativeOutputFile);
349
350             return relativeOutputFile;
351         }
352
353         String JavaDoc root = getRoot(new File JavaDoc(destFile)).getAbsolutePath();
354
355         if ((root.length() > 1)
356             && destFile.startsWith(root.substring(0, root.length() - 1))) {
357             throw new BuildException("Drive letter in 'outputfile' not "
358                                      + "supported: " + destFile);
359         }
360
361         return destFile;
362     }
363
364     private String JavaDoc makeOutputFileRelative(String JavaDoc destFile) {
365         StringBuffer JavaDoc relativePath = new StringBuffer JavaDoc();
366         String JavaDoc defaultOutputDirectory = getDefaultOutputDirectory();
367         int nextPos = defaultOutputDirectory.indexOf('/');
368         int startPos = nextPos + 1;
369
370         while (startPos > -1 && startPos < defaultOutputDirectory.length()) {
371             relativePath.append("/..");
372             nextPos = defaultOutputDirectory.indexOf('/', startPos);
373
374             if (nextPos == -1) {
375                 startPos = nextPos;
376             } else {
377                 startPos = nextPos + 1;
378             }
379         }
380
381         relativePath.append(destFile);
382
383         return relativePath.toString();
384     }
385
386     private String JavaDoc getDefaultOutputDirectory() {
387         return getProject().getBaseDir().getAbsolutePath().replace('\\', '/');
388     }
389
390     /**
391      * Determine root directory for a given file.
392      *
393      * @param file
394      * @return file's root directory
395      */

396     private File JavaDoc getRoot(File JavaDoc file) {
397         File JavaDoc root = file.getAbsoluteFile();
398
399         while (root.getParent() != null) {
400             root = root.getParentFile();
401         }
402
403         return root;
404     }
405 }
406
Popular Tags