source: other-projects/trunk/gs3-release-maker/apache-ant-1.6.5/src/main/org/apache/tools/ant/taskdefs/optional/javacc/JJTree.java@ 14627

Last change on this file since 14627 was 14627, checked in by oranfry, 17 years ago

initial import of the gs3-release-maker

File size: 13.2 KB
Line 
1/*
2 * Copyright 2000-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
18package org.apache.tools.ant.taskdefs.optional.javacc;
19
20import java.io.File;
21import java.io.IOException;
22import java.util.Enumeration;
23import java.util.Hashtable;
24import org.apache.tools.ant.BuildException;
25import org.apache.tools.ant.Project;
26import org.apache.tools.ant.Task;
27import org.apache.tools.ant.taskdefs.Execute;
28import org.apache.tools.ant.taskdefs.LogStreamHandler;
29import org.apache.tools.ant.types.Commandline;
30import org.apache.tools.ant.types.CommandlineJava;
31import org.apache.tools.ant.types.Path;
32import org.apache.tools.ant.util.JavaEnvUtils;
33
34/**
35 * Runs the JJTree compiler compiler.
36 *
37 */
38public class JJTree extends Task {
39
40 // keys to optional attributes
41 private static final String OUTPUT_FILE = "OUTPUT_FILE";
42 private static final String BUILD_NODE_FILES = "BUILD_NODE_FILES";
43 private static final String MULTI = "MULTI";
44 private static final String NODE_DEFAULT_VOID = "NODE_DEFAULT_VOID";
45 private static final String NODE_FACTORY = "NODE_FACTORY";
46 private static final String NODE_SCOPE_HOOK = "NODE_SCOPE_HOOK";
47 private static final String NODE_USES_PARSER = "NODE_USES_PARSER";
48 private static final String STATIC = "STATIC";
49 private static final String VISITOR = "VISITOR";
50
51 private static final String NODE_PACKAGE = "NODE_PACKAGE";
52 private static final String VISITOR_EXCEPTION = "VISITOR_EXCEPTION";
53 private static final String NODE_PREFIX = "NODE_PREFIX";
54
55 private final Hashtable optionalAttrs = new Hashtable();
56
57 private String outputFile = null;
58
59 private static final String DEFAULT_SUFFIX = ".jj";
60
61 // required attributes
62 private File outputDirectory = null;
63 private File target = null;
64 private File javaccHome = null;
65
66 private CommandlineJava cmdl = new CommandlineJava();
67
68
69 /**
70 * Sets the BUILD_NODE_FILES grammar option.
71 */
72 public void setBuildnodefiles(boolean buildNodeFiles) {
73 optionalAttrs.put(BUILD_NODE_FILES, new Boolean(buildNodeFiles));
74 }
75
76 /**
77 * Sets the MULTI grammar option.
78 */
79 public void setMulti(boolean multi) {
80 optionalAttrs.put(MULTI, new Boolean(multi));
81 }
82
83 /**
84 * Sets the NODE_DEFAULT_VOID grammar option.
85 */
86 public void setNodedefaultvoid(boolean nodeDefaultVoid) {
87 optionalAttrs.put(NODE_DEFAULT_VOID, new Boolean(nodeDefaultVoid));
88 }
89
90 /**
91 * Sets the NODE_FACTORY grammar option.
92 */
93 public void setNodefactory(boolean nodeFactory) {
94 optionalAttrs.put(NODE_FACTORY, new Boolean(nodeFactory));
95 }
96
97 /**
98 * Sets the NODE_SCOPE_HOOK grammar option.
99 */
100 public void setNodescopehook(boolean nodeScopeHook) {
101 optionalAttrs.put(NODE_SCOPE_HOOK, new Boolean(nodeScopeHook));
102 }
103
104 /**
105 * Sets the NODE_USES_PARSER grammar option.
106 */
107 public void setNodeusesparser(boolean nodeUsesParser) {
108 optionalAttrs.put(NODE_USES_PARSER, new Boolean(nodeUsesParser));
109 }
110
111 /**
112 * Sets the STATIC grammar option.
113 */
114 public void setStatic(boolean staticParser) {
115 optionalAttrs.put(STATIC, new Boolean(staticParser));
116 }
117
118 /**
119 * Sets the VISITOR grammar option.
120 */
121 public void setVisitor(boolean visitor) {
122 optionalAttrs.put(VISITOR, new Boolean(visitor));
123 }
124
125 /**
126 * Sets the NODE_PACKAGE grammar option.
127 */
128 public void setNodepackage(String nodePackage) {
129 optionalAttrs.put(NODE_PACKAGE, new String(nodePackage));
130 }
131
132 /**
133 * Sets the VISITOR_EXCEPTION grammar option.
134 */
135 public void setVisitorException(String visitorException) {
136 optionalAttrs.put(VISITOR_EXCEPTION, new String(visitorException));
137 }
138
139 /**
140 * Sets the NODE_PREFIX grammar option.
141 */
142 public void setNodeprefix(String nodePrefix) {
143 optionalAttrs.put(NODE_PREFIX, new String(nodePrefix));
144 }
145
146 /**
147 * The directory to write the generated JavaCC grammar and node files to.
148 * If not set, the files are written to the directory
149 * containing the grammar file.
150 */
151 public void setOutputdirectory(File outputDirectory) {
152 this.outputDirectory = outputDirectory;
153 }
154
155 /**
156 * The outputfile to write the generated JavaCC grammar file to.
157 * If not set, the file is written with the same name as
158 * the JJTree grammar file with a suffix .jj.
159 */
160 public void setOutputfile(String outputFile) {
161 this.outputFile = outputFile;
162 }
163
164 /**
165 * The jjtree grammar file to process.
166 */
167 public void setTarget(File target) {
168 this.target = target;
169 }
170
171 /**
172 * The directory containing the JavaCC distribution.
173 */
174 public void setJavacchome(File javaccHome) {
175 this.javaccHome = javaccHome;
176 }
177
178 public JJTree() {
179 cmdl.setVm(JavaEnvUtils.getJreExecutable("java"));
180 }
181
182 public void execute() throws BuildException {
183
184 // load command line with optional attributes
185 Enumeration iter = optionalAttrs.keys();
186 while (iter.hasMoreElements()) {
187 String name = (String) iter.nextElement();
188 Object value = optionalAttrs.get(name);
189 cmdl.createArgument().setValue("-" + name + ":" + value.toString());
190 }
191
192 if (target == null || !target.isFile()) {
193 throw new BuildException("Invalid target: " + target);
194 }
195
196 File javaFile = null;
197
198 // use the directory containing the target as the output directory
199 if (outputDirectory == null) {
200 // convert backslashes to slashes, otherwise jjtree will
201 // put this as comments and this seems to confuse javacc
202 cmdl.createArgument().setValue("-OUTPUT_DIRECTORY:"
203 + getDefaultOutputDirectory());
204
205 javaFile = new File(createOutputFileName(target, outputFile,
206 null));
207 } else {
208 if (!outputDirectory.isDirectory()) {
209 throw new BuildException("'outputdirectory' " + outputDirectory
210 + " is not a directory.");
211 }
212
213 // convert backslashes to slashes, otherwise jjtree will
214 // put this as comments and this seems to confuse javacc
215 cmdl.createArgument().setValue("-OUTPUT_DIRECTORY:"
216 + outputDirectory.getAbsolutePath()
217 .replace('\\', '/'));
218
219 javaFile = new File(createOutputFileName(target, outputFile,
220 outputDirectory
221 .getPath()));
222 }
223
224 if (javaFile.exists()
225 && target.lastModified() < javaFile.lastModified()) {
226 log("Target is already built - skipping (" + target + ")",
227 Project.MSG_VERBOSE);
228 return;
229 }
230
231 if (outputFile != null) {
232 cmdl.createArgument().setValue("-" + OUTPUT_FILE + ":"
233 + outputFile.replace('\\', '/'));
234 }
235
236 cmdl.createArgument().setValue(target.getAbsolutePath());
237
238 cmdl.setClassname(JavaCC.getMainClass(javaccHome,
239 JavaCC.TASKDEF_TYPE_JJTREE));
240
241 final Path classpath = cmdl.createClasspath(getProject());
242 final File javaccJar = JavaCC.getArchiveFile(javaccHome);
243 classpath.createPathElement().setPath(javaccJar.getAbsolutePath());
244 classpath.addJavaRuntime();
245
246 final Commandline.Argument arg = cmdl.createVmArgument();
247 arg.setValue("-mx140M");
248 arg.setValue("-Dinstall.root=" + javaccHome.getAbsolutePath());
249
250 final Execute process =
251 new Execute(new LogStreamHandler(this,
252 Project.MSG_INFO,
253 Project.MSG_INFO),
254 null);
255 log(cmdl.describeCommand(), Project.MSG_VERBOSE);
256 process.setCommandline(cmdl.getCommandline());
257
258 try {
259 if (process.execute() != 0) {
260 throw new BuildException("JJTree failed.");
261 }
262 } catch (IOException e) {
263 throw new BuildException("Failed to launch JJTree", e);
264 }
265 }
266
267 private String createOutputFileName(File target, String optionalOutputFile,
268 String outputDirectory) {
269 optionalOutputFile = validateOutputFile(optionalOutputFile,
270 outputDirectory);
271 String jjtreeFile = target.getAbsolutePath().replace('\\', '/');
272
273 if ((optionalOutputFile == null) || optionalOutputFile.equals("")) {
274 int filePos = jjtreeFile.lastIndexOf("/");
275
276 if (filePos >= 0) {
277 jjtreeFile = jjtreeFile.substring(filePos + 1);
278 }
279
280 int suffixPos = jjtreeFile.lastIndexOf('.');
281
282 if (suffixPos == -1) {
283 optionalOutputFile = jjtreeFile + DEFAULT_SUFFIX;
284 } else {
285 String currentSuffix = jjtreeFile.substring(suffixPos);
286
287 if (currentSuffix.equals(DEFAULT_SUFFIX)) {
288 optionalOutputFile = jjtreeFile + DEFAULT_SUFFIX;
289 } else {
290 optionalOutputFile = jjtreeFile.substring(0, suffixPos)
291 + DEFAULT_SUFFIX;
292 }
293 }
294 }
295
296 if ((outputDirectory == null) || outputDirectory.equals("")) {
297 outputDirectory = getDefaultOutputDirectory();
298 }
299
300 return (outputDirectory + "/" + optionalOutputFile).replace('\\', '/');
301 }
302
303 /*
304 * Not used anymore
305 private boolean isAbsolute(String fileName) {
306 return (fileName.startsWith("/") || (new File(fileName).isAbsolute()));
307 }
308*/
309 /**
310 * When running JJTree from an Ant taskdesk the -OUTPUT_DIRECTORY must
311 * always be set. But when -OUTPUT_DIRECTORY is set, -OUTPUT_FILE is
312 * handled as if relative of this -OUTPUT_DIRECTORY. Thus when the
313 * -OUTPUT_FILE is absolute or contains a drive letter we have a problem.
314 *
315 * @param outputFile
316 * @param outputDirectory
317 * @return
318 * @throws BuildException
319 */
320 private String validateOutputFile(String outputFile,
321 String outputDirectory)
322 throws BuildException {
323 if (outputFile == null) {
324 return null;
325 }
326
327 if ((outputDirectory == null)
328 && (outputFile.startsWith("/") || outputFile.startsWith("\\"))) {
329 String relativeOutputFile = makeOutputFileRelative(outputFile);
330 setOutputfile(relativeOutputFile);
331
332 return relativeOutputFile;
333 }
334
335 String root = getRoot(new File(outputFile)).getAbsolutePath();
336
337 if ((root.length() > 1)
338 && outputFile.startsWith(root.substring(0, root.length() - 1))) {
339 throw new BuildException("Drive letter in 'outputfile' not "
340 + "supported: " + outputFile);
341 }
342
343 return outputFile;
344 }
345
346 private String makeOutputFileRelative(String outputFile) {
347 StringBuffer relativePath = new StringBuffer();
348 String defaultOutputDirectory = getDefaultOutputDirectory();
349 int nextPos = defaultOutputDirectory.indexOf('/');
350 int startPos = nextPos + 1;
351
352 while (startPos > -1 && startPos < defaultOutputDirectory.length()) {
353 relativePath.append("/..");
354 nextPos = defaultOutputDirectory.indexOf('/', startPos);
355
356 if (nextPos == -1) {
357 startPos = nextPos;
358 } else {
359 startPos = nextPos + 1;
360 }
361 }
362
363 relativePath.append(outputFile);
364
365 return relativePath.toString();
366 }
367
368 private String getDefaultOutputDirectory() {
369 return getProject().getBaseDir().getAbsolutePath().replace('\\', '/');
370 }
371
372 /**
373 * Determine root directory for a given file.
374 *
375 * @param file
376 * @return file's root directory
377 */
378 private File getRoot(File file) {
379 File root = file.getAbsoluteFile();
380
381 while (root.getParent() != null) {
382 root = root.getParentFile();
383 }
384
385 return root;
386 }
387}
Note: See TracBrowser for help on using the repository browser.