KickJava   Java API By Example, From Geeks To Geeks.

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


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.InputStream JavaDoc;
23 import java.util.Enumeration JavaDoc;
24 import java.util.Hashtable JavaDoc;
25
26 import org.apache.tools.ant.AntClassLoader;
27 import org.apache.tools.ant.BuildException;
28 import org.apache.tools.ant.Project;
29 import org.apache.tools.ant.Task;
30 import org.apache.tools.ant.taskdefs.Execute;
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  * JavaCC compiler compiler task.
38  *
39  */

40 public class JavaCC extends Task {
41
42     // keys to optional attributes
43
private static final String JavaDoc LOOKAHEAD = "LOOKAHEAD";
44     private static final String JavaDoc CHOICE_AMBIGUITY_CHECK = "CHOICE_AMBIGUITY_CHECK";
45     private static final String JavaDoc OTHER_AMBIGUITY_CHECK = "OTHER_AMBIGUITY_CHECK";
46
47     private static final String JavaDoc STATIC = "STATIC";
48     private static final String JavaDoc DEBUG_PARSER = "DEBUG_PARSER";
49     private static final String JavaDoc DEBUG_LOOKAHEAD = "DEBUG_LOOKAHEAD";
50     private static final String JavaDoc DEBUG_TOKEN_MANAGER = "DEBUG_TOKEN_MANAGER";
51     private static final String JavaDoc OPTIMIZE_TOKEN_MANAGER = "OPTIMIZE_TOKEN_MANAGER";
52     private static final String JavaDoc ERROR_REPORTING = "ERROR_REPORTING";
53     private static final String JavaDoc JAVA_UNICODE_ESCAPE = "JAVA_UNICODE_ESCAPE";
54     private static final String JavaDoc UNICODE_INPUT = "UNICODE_INPUT";
55     private static final String JavaDoc IGNORE_CASE = "IGNORE_CASE";
56     private static final String JavaDoc COMMON_TOKEN_ACTION = "COMMON_TOKEN_ACTION";
57     private static final String JavaDoc USER_TOKEN_MANAGER = "USER_TOKEN_MANAGER";
58     private static final String JavaDoc USER_CHAR_STREAM = "USER_CHAR_STREAM";
59     private static final String JavaDoc BUILD_PARSER = "BUILD_PARSER";
60     private static final String JavaDoc BUILD_TOKEN_MANAGER = "BUILD_TOKEN_MANAGER";
61     private static final String JavaDoc SANITY_CHECK = "SANITY_CHECK";
62     private static final String JavaDoc FORCE_LA_CHECK = "FORCE_LA_CHECK";
63     private static final String JavaDoc CACHE_TOKENS = "CACHE_TOKENS";
64     private static final String JavaDoc KEEP_LINE_COLUMN = "KEEP_LINE_COLUMN";
65     private static final String JavaDoc JDK_VERSION = "JDK_VERSION";
66
67     private final Hashtable JavaDoc optionalAttrs = new Hashtable JavaDoc();
68
69     // required attributes
70
private File JavaDoc outputDirectory = null;
71     private File JavaDoc targetFile = null;
72     private File JavaDoc javaccHome = null;
73
74     private CommandlineJava cmdl = new CommandlineJava();
75
76     protected static final int TASKDEF_TYPE_JAVACC = 1;
77     protected static final int TASKDEF_TYPE_JJTREE = 2;
78     protected static final int TASKDEF_TYPE_JJDOC = 3;
79
80     protected static final String JavaDoc[] ARCHIVE_LOCATIONS =
81         new String JavaDoc[] {
82             "JavaCC.zip",
83             "bin/lib/JavaCC.zip",
84             "bin/lib/javacc.jar",
85             "javacc.jar", // used by jpackage for JavaCC 3.x
86
};
87
88     protected static final int[] ARCHIVE_LOCATIONS_VS_MAJOR_VERSION =
89         new int[] {
90             1,
91             2,
92             3,
93             3,
94         };
95
96     protected static final String JavaDoc COM_PACKAGE = "COM.sun.labs.";
97     protected static final String JavaDoc COM_JAVACC_CLASS = "javacc.Main";
98     protected static final String JavaDoc COM_JJTREE_CLASS = "jjtree.Main";
99     protected static final String JavaDoc COM_JJDOC_CLASS = "jjdoc.JJDocMain";
100
101     protected static final String JavaDoc ORG_PACKAGE_3_0 = "org.netbeans.javacc.";
102     protected static final String JavaDoc ORG_PACKAGE_3_1 = "org.javacc.";
103     protected static final String JavaDoc ORG_JAVACC_CLASS = "parser.Main";
104     protected static final String JavaDoc ORG_JJTREE_CLASS = COM_JJTREE_CLASS;
105     protected static final String JavaDoc ORG_JJDOC_CLASS = COM_JJDOC_CLASS;
106
107     /**
108      * Sets the LOOKAHEAD grammar option.
109      * @param lookahead an <code>int</code> value.
110      */

111     public void setLookahead(int lookahead) {
112         optionalAttrs.put(LOOKAHEAD, new Integer JavaDoc(lookahead));
113     }
114
115     /**
116      * Sets the CHOICE_AMBIGUITY_CHECK grammar option.
117      * @param choiceAmbiguityCheck an <code>int</code> value.
118      */

119     public void setChoiceambiguitycheck(int choiceAmbiguityCheck) {
120         optionalAttrs.put(CHOICE_AMBIGUITY_CHECK, new Integer JavaDoc(choiceAmbiguityCheck));
121     }
122
123     /**
124      * Sets the OTHER_AMBIGUITY_CHECK grammar option.
125      * @param otherAmbiguityCheck an <code>int</code> value.
126      */

127     public void setOtherambiguityCheck(int otherAmbiguityCheck) {
128         optionalAttrs.put(OTHER_AMBIGUITY_CHECK, new Integer JavaDoc(otherAmbiguityCheck));
129     }
130
131     /**
132      * Sets the STATIC grammar option.
133      * @param staticParser a <code>boolean</code> value.
134      */

135     public void setStatic(boolean staticParser) {
136         optionalAttrs.put(STATIC, staticParser ? Boolean.TRUE : Boolean.FALSE);
137     }
138
139     /**
140      * Sets the DEBUG_PARSER grammar option.
141      * @param debugParser a <code>boolean</code> value.
142      */

143     public void setDebugparser(boolean debugParser) {
144         optionalAttrs.put(DEBUG_PARSER, debugParser ? Boolean.TRUE : Boolean.FALSE);
145     }
146
147     /**
148      * Sets the DEBUG_LOOKAHEAD grammar option.
149      * @param debugLookahead a <code>boolean</code> value.
150      */

151     public void setDebuglookahead(boolean debugLookahead) {
152         optionalAttrs.put(DEBUG_LOOKAHEAD, debugLookahead ? Boolean.TRUE : Boolean.FALSE);
153     }
154
155     /**
156      * Sets the DEBUG_TOKEN_MANAGER grammar option.
157      * @param debugTokenManager a <code>boolean</code> value.
158      */

159     public void setDebugtokenmanager(boolean debugTokenManager) {
160         optionalAttrs.put(DEBUG_TOKEN_MANAGER, debugTokenManager ? Boolean.TRUE : Boolean.FALSE);
161     }
162
163     /**
164      * Sets the OPTIMIZE_TOKEN_MANAGER grammar option.
165      * @param optimizeTokenManager a <code>boolean</code> value.
166      */

167     public void setOptimizetokenmanager(boolean optimizeTokenManager) {
168         optionalAttrs.put(OPTIMIZE_TOKEN_MANAGER,
169                           optimizeTokenManager ? Boolean.TRUE : Boolean.FALSE);
170     }
171
172     /**
173      * Sets the ERROR_REPORTING grammar option.
174      * @param errorReporting a <code>boolean</code> value.
175      */

176     public void setErrorreporting(boolean errorReporting) {
177         optionalAttrs.put(ERROR_REPORTING, errorReporting ? Boolean.TRUE : Boolean.FALSE);
178     }
179
180     /**
181      * Sets the JAVA_UNICODE_ESCAPE grammar option.
182      * @param javaUnicodeEscape a <code>boolean</code> value.
183      */

184     public void setJavaunicodeescape(boolean javaUnicodeEscape) {
185         optionalAttrs.put(JAVA_UNICODE_ESCAPE, javaUnicodeEscape ? Boolean.TRUE : Boolean.FALSE);
186     }
187
188     /**
189      * Sets the UNICODE_INPUT grammar option.
190      * @param unicodeInput a <code>boolean</code> value.
191      */

192     public void setUnicodeinput(boolean unicodeInput) {
193         optionalAttrs.put(UNICODE_INPUT, unicodeInput ? Boolean.TRUE : Boolean.FALSE);
194     }
195
196     /**
197      * Sets the IGNORE_CASE grammar option.
198      * @param ignoreCase a <code>boolean</code> value.
199      */

200     public void setIgnorecase(boolean ignoreCase) {
201         optionalAttrs.put(IGNORE_CASE, ignoreCase ? Boolean.TRUE : Boolean.FALSE);
202     }
203
204     /**
205      * Sets the COMMON_TOKEN_ACTION grammar option.
206      * @param commonTokenAction a <code>boolean</code> value.
207      */

208     public void setCommontokenaction(boolean commonTokenAction) {
209         optionalAttrs.put(COMMON_TOKEN_ACTION, commonTokenAction ? Boolean.TRUE : Boolean.FALSE);
210     }
211
212     /**
213      * Sets the USER_TOKEN_MANAGER grammar option.
214      * @param userTokenManager a <code>boolean</code> value.
215      */

216     public void setUsertokenmanager(boolean userTokenManager) {
217         optionalAttrs.put(USER_TOKEN_MANAGER, userTokenManager ? Boolean.TRUE : Boolean.FALSE);
218     }
219
220     /**
221      * Sets the USER_CHAR_STREAM grammar option.
222      * @param userCharStream a <code>boolean</code> value.
223      */

224     public void setUsercharstream(boolean userCharStream) {
225         optionalAttrs.put(USER_CHAR_STREAM, userCharStream ? Boolean.TRUE : Boolean.FALSE);
226     }
227
228     /**
229      * Sets the BUILD_PARSER grammar option.
230      * @param buildParser a <code>boolean</code> value.
231      */

232     public void setBuildparser(boolean buildParser) {
233         optionalAttrs.put(BUILD_PARSER, buildParser ? Boolean.TRUE : Boolean.FALSE);
234     }
235
236     /**
237      * Sets the BUILD_TOKEN_MANAGER grammar option.
238      * @param buildTokenManager a <code>boolean</code> value.
239      */

240     public void setBuildtokenmanager(boolean buildTokenManager) {
241         optionalAttrs.put(BUILD_TOKEN_MANAGER, buildTokenManager ? Boolean.TRUE : Boolean.FALSE);
242     }
243
244     /**
245      * Sets the SANITY_CHECK grammar option.
246      * @param sanityCheck a <code>boolean</code> value.
247      */

248     public void setSanitycheck(boolean sanityCheck) {
249         optionalAttrs.put(SANITY_CHECK, sanityCheck ? Boolean.TRUE : Boolean.FALSE);
250     }
251
252     /**
253      * Sets the FORCE_LA_CHECK grammar option.
254      * @param forceLACheck a <code>boolean</code> value.
255      */

256     public void setForcelacheck(boolean forceLACheck) {
257         optionalAttrs.put(FORCE_LA_CHECK, forceLACheck ? Boolean.TRUE : Boolean.FALSE);
258     }
259
260     /**
261      * Sets the CACHE_TOKENS grammar option.
262      * @param cacheTokens a <code>boolean</code> value.
263      */

264     public void setCachetokens(boolean cacheTokens) {
265         optionalAttrs.put(CACHE_TOKENS, cacheTokens ? Boolean.TRUE : Boolean.FALSE);
266     }
267
268     /**
269      * Sets the KEEP_LINE_COLUMN grammar option.
270      * @param keepLineColumn a <code>boolean</code> value.
271      */

272     public void setKeeplinecolumn(boolean keepLineColumn) {
273         optionalAttrs.put(KEEP_LINE_COLUMN, keepLineColumn ? Boolean.TRUE : Boolean.FALSE);
274     }
275
276     /**
277      * Sets the JDK_VERSION option.
278      * @param jdkVersion the version to use.
279      * @since Ant1.7
280      */

281     public void setJDKversion(String JavaDoc jdkVersion) {
282         optionalAttrs.put(JDK_VERSION, jdkVersion);
283     }
284
285     /**
286      * The directory to write the generated files to.
287      * If not set, the files are written to the directory
288      * containing the grammar file.
289      * @param outputDirectory the output directory.
290      */

291     public void setOutputdirectory(File JavaDoc outputDirectory) {
292         this.outputDirectory = outputDirectory;
293     }
294
295     /**
296      * The grammar file to process.
297      * @param targetFile the grammar file.
298      */

299     public void setTarget(File JavaDoc targetFile) {
300         this.targetFile = targetFile;
301     }
302
303     /**
304      * The directory containing the JavaCC distribution.
305      * @param javaccHome the directory.
306      */

307     public void setJavacchome(File JavaDoc javaccHome) {
308         this.javaccHome = javaccHome;
309     }
310
311     /**
312      * Constructor
313      */

314     public JavaCC() {
315         cmdl.setVm(JavaEnvUtils.getJreExecutable("java"));
316     }
317
318     /**
319      * Run the task.
320      * @throws BuildException on error.
321      */

322     public void execute() throws BuildException {
323
324         // load command line with optional attributes
325
Enumeration JavaDoc iter = optionalAttrs.keys();
326         while (iter.hasMoreElements()) {
327             String JavaDoc name = (String JavaDoc) iter.nextElement();
328             Object JavaDoc value = optionalAttrs.get(name);
329             cmdl.createArgument().setValue("-" + name + ":" + value.toString());
330         }
331
332         // check the target is a file
333
if (targetFile == null || !targetFile.isFile()) {
334             throw new BuildException("Invalid target: " + targetFile);
335         }
336
337         // use the directory containing the target as the output directory
338
if (outputDirectory == null) {
339             outputDirectory = new File JavaDoc(targetFile.getParent());
340         } else if (!outputDirectory.isDirectory()) {
341             throw new BuildException("Outputdir not a directory.");
342         }
343         cmdl.createArgument().setValue("-OUTPUT_DIRECTORY:"
344                                        + outputDirectory.getAbsolutePath());
345
346         // determine if the generated java file is up-to-date
347
final File JavaDoc javaFile = getOutputJavaFile(outputDirectory, targetFile);
348         if (javaFile.exists() && targetFile.lastModified() < javaFile.lastModified()) {
349             log("Target is already built - skipping (" + targetFile + ")", Project.MSG_VERBOSE);
350             return;
351         }
352         cmdl.createArgument().setValue(targetFile.getAbsolutePath());
353
354         final Path classpath = cmdl.createClasspath(getProject());
355         final File JavaDoc javaccJar = JavaCC.getArchiveFile(javaccHome);
356         classpath.createPathElement().setPath(javaccJar.getAbsolutePath());
357         classpath.addJavaRuntime();
358
359         cmdl.setClassname(JavaCC.getMainClass(classpath,
360                                               JavaCC.TASKDEF_TYPE_JAVACC));
361
362         final Commandline.Argument arg = cmdl.createVmArgument();
363         arg.setValue("-mx140M");
364         arg.setValue("-Dinstall.root=" + javaccHome.getAbsolutePath());
365
366         Execute.runCommand(this, cmdl.getCommandline());
367     }
368
369     /**
370      * Helper method to retrieve the path used to store the JavaCC.zip
371      * or javacc.jar which is different from versions.
372      *
373      * @param home the javacc home path directory.
374      * @throws BuildException thrown if the home directory is invalid
375      * or if the archive could not be found despite attempts to do so.
376      * @return the file object pointing to the JavaCC archive.
377      */

378     protected static File JavaDoc getArchiveFile(File JavaDoc home) throws BuildException {
379         return new File JavaDoc(home,
380                         ARCHIVE_LOCATIONS[getArchiveLocationIndex(home)]);
381     }
382
383     /**
384      * Helper method to retrieve main class which is different from versions.
385      * @param home the javacc home path directory.
386      * @param type the taskdef.
387      * @throws BuildException thrown if the home directory is invalid
388      * or if the archive could not be found despite attempts to do so.
389      * @return the main class for the taskdef.
390      */

391     protected static String JavaDoc getMainClass(File JavaDoc home, int type)
392         throws BuildException {
393
394         Path p = new Path(null);
395         p.createPathElement().setLocation(getArchiveFile(home));
396         p.addJavaRuntime();
397         return getMainClass(p, type);
398     }
399
400     /**
401      * Helper method to retrieve main class which is different from versions.
402      * @param path classpath to search in.
403      * @param type the taskdef.
404      * @throws BuildException thrown if the home directory is invalid
405      * or if the archive could not be found despite attempts to do so.
406      * @return the main class for the taskdef.
407      * @since Ant 1.7
408      */

409     protected static String JavaDoc getMainClass(Path path, int type)
410         throws BuildException {
411         String JavaDoc packagePrefix = null;
412         String JavaDoc mainClass = null;
413
414         AntClassLoader l = new AntClassLoader();
415         l.setClassPath(path.concatSystemClasspath("ignore"));
416         String JavaDoc javaccClass = COM_PACKAGE + COM_JAVACC_CLASS;
417         InputStream JavaDoc is = l.getResourceAsStream(javaccClass.replace('.', '/')
418                                                + ".class");
419         if (is != null) {
420             packagePrefix = COM_PACKAGE;
421             switch (type) {
422             case TASKDEF_TYPE_JAVACC:
423                 mainClass = COM_JAVACC_CLASS;
424
425                 break;
426
427             case TASKDEF_TYPE_JJTREE:
428                 mainClass = COM_JJTREE_CLASS;
429
430                 break;
431
432             case TASKDEF_TYPE_JJDOC:
433                 mainClass = COM_JJDOC_CLASS;
434
435                 break;
436             default:
437                 // Fall Through
438
}
439         } else {
440             javaccClass = ORG_PACKAGE_3_1 + ORG_JAVACC_CLASS;
441             is = l.getResourceAsStream(javaccClass.replace('.', '/')
442                                        + ".class");
443             if (is != null) {
444                 packagePrefix = ORG_PACKAGE_3_1;
445             } else {
446                 javaccClass = ORG_PACKAGE_3_0 + ORG_JAVACC_CLASS;
447                 is = l.getResourceAsStream(javaccClass.replace('.', '/')
448                                            + ".class");
449                 if (is != null) {
450                     packagePrefix = ORG_PACKAGE_3_0;
451                 }
452             }
453
454             if (is != null) {
455                 switch (type) {
456                 case TASKDEF_TYPE_JAVACC:
457                     mainClass = ORG_JAVACC_CLASS;
458
459                 break;
460
461                 case TASKDEF_TYPE_JJTREE:
462                     mainClass = ORG_JJTREE_CLASS;
463
464                     break;
465
466                 case TASKDEF_TYPE_JJDOC:
467                     mainClass = ORG_JJDOC_CLASS;
468
469                     break;
470                 default:
471                     // Fall Through
472
}
473             }
474         }
475
476         if (packagePrefix == null) {
477             throw new BuildException("failed to load JavaCC");
478         }
479         if (mainClass == null) {
480             throw new BuildException("unknown task type " + type);
481         }
482         return packagePrefix + mainClass;
483     }
484
485     /**
486      * Helper method to determine the archive location index.
487      *
488      * @param home the javacc home path directory.
489      * @throws BuildException thrown if the home directory is invalid
490      * or if the archive could not be found despite attempts to do so.
491      * @return the archive location index
492      */

493     private static int getArchiveLocationIndex(File JavaDoc home)
494         throws BuildException {
495
496         if (home == null || !home.isDirectory()) {
497             throw new BuildException("JavaCC home must be a valid directory.");
498         }
499
500         for (int i = 0; i < ARCHIVE_LOCATIONS.length; i++) {
501             File JavaDoc f = new File JavaDoc(home, ARCHIVE_LOCATIONS[i]);
502
503             if (f.exists()) {
504                 return i;
505             }
506         }
507
508         throw new BuildException("Could not find a path to JavaCC.zip "
509                                  + "or javacc.jar from '" + home + "'.");
510     }
511
512     /**
513      * Helper method to determine the major version number of JavaCC.
514      *
515      * @param home the javacc home path directory.
516      * @throws BuildException thrown if the home directory is invalid
517      * or if the archive could not be found despite attempts to do so.
518      * @return a the major version number
519      */

520     protected static int getMajorVersionNumber(File JavaDoc home)
521         throws BuildException {
522
523         return
524             ARCHIVE_LOCATIONS_VS_MAJOR_VERSION[getArchiveLocationIndex(home)];
525     }
526
527     /**
528      * Determines the output Java file to be generated by the given grammar
529      * file.
530      *
531      */

532     private File JavaDoc getOutputJavaFile(File JavaDoc outputdir, File JavaDoc srcfile) {
533         String JavaDoc path = srcfile.getPath();
534
535         // Extract file's base-name
536
int startBasename = path.lastIndexOf(File.separator);
537         if (startBasename != -1) {
538             path = path.substring(startBasename + 1);
539         }
540
541         // Replace the file's extension with '.java'
542
int startExtn = path.lastIndexOf('.');
543         if (startExtn != -1) {
544             path = path.substring(0, startExtn) + ".java";
545         } else {
546             path += ".java";
547         }
548
549         // Change the directory
550
if (outputdir != null) {
551             path = outputdir + File.separator + path;
552         }
553
554         return new File JavaDoc(path);
555     }
556 }
557
Popular Tags