001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: package org.apache.tools.ant.taskdefs.optional.javacc;
020:
021: import java.io.File;
022: import java.io.IOException;
023: import java.util.Enumeration;
024: import java.util.Hashtable;
025:
026: import org.apache.tools.ant.BuildException;
027: import org.apache.tools.ant.Project;
028: import org.apache.tools.ant.Task;
029: import org.apache.tools.ant.taskdefs.Execute;
030: import org.apache.tools.ant.taskdefs.LogStreamHandler;
031: import org.apache.tools.ant.types.Commandline;
032: import org.apache.tools.ant.types.CommandlineJava;
033: import org.apache.tools.ant.types.Path;
034: import org.apache.tools.ant.util.JavaEnvUtils;
035:
036: /**
037: * Runs the JJDoc compiler compiler.
038: *
039: */
040: public class JJDoc extends Task {
041:
042: // keys to optional attributes
043: private static final String OUTPUT_FILE = "OUTPUT_FILE";
044: private static final String TEXT = "TEXT";
045: private static final String ONE_TABLE = "ONE_TABLE";
046:
047: private final Hashtable optionalAttrs = new Hashtable();
048:
049: private String outputFile = null;
050: private boolean plainText = false;
051:
052: private static final String DEFAULT_SUFFIX_HTML = ".html";
053: private static final String DEFAULT_SUFFIX_TEXT = ".txt";
054:
055: // required attributes
056: private File targetFile = null;
057: private File javaccHome = null;
058:
059: private CommandlineJava cmdl = new CommandlineJava();
060:
061: /**
062: * Sets the TEXT BNF documentation option.
063: * @param plainText a <code>boolean</code> value.
064: */
065: public void setText(boolean plainText) {
066: optionalAttrs.put(TEXT, plainText ? Boolean.TRUE
067: : Boolean.FALSE);
068: this .plainText = plainText;
069: }
070:
071: /**
072: * Sets the ONE_TABLE documentation option.
073: * @param oneTable a <code>boolean</code> value.
074: */
075: public void setOnetable(boolean oneTable) {
076: optionalAttrs.put(ONE_TABLE, oneTable ? Boolean.TRUE
077: : Boolean.FALSE);
078: }
079:
080: /**
081: * The outputfile to write the generated BNF documentation file to.
082: * If not set, the file is written with the same name as
083: * the JavaCC grammar file with a suffix .html or .txt.
084: * @param outputFile the name of the output file.
085: */
086: public void setOutputfile(String outputFile) {
087: this .outputFile = outputFile;
088: }
089:
090: /**
091: * The javacc grammar file to process.
092: * @param target the grammar file.
093: */
094: public void setTarget(File target) {
095: this .targetFile = target;
096: }
097:
098: /**
099: * The directory containing the JavaCC distribution.
100: * @param javaccHome the home directory.
101: */
102: public void setJavacchome(File javaccHome) {
103: this .javaccHome = javaccHome;
104: }
105:
106: /**
107: * Constructor
108: */
109: public JJDoc() {
110: cmdl.setVm(JavaEnvUtils.getJreExecutable("java"));
111: }
112:
113: /**
114: * Do the task.
115: * @throws BuildException if there is an error.
116: */
117: public void execute() throws BuildException {
118:
119: // load command line with optional attributes
120: Enumeration iter = optionalAttrs.keys();
121: while (iter.hasMoreElements()) {
122: String name = (String) iter.nextElement();
123: Object value = optionalAttrs.get(name);
124: cmdl.createArgument().setValue(
125: "-" + name + ":" + value.toString());
126: }
127:
128: if (targetFile == null || !targetFile.isFile()) {
129: throw new BuildException("Invalid target: " + targetFile);
130: }
131:
132: if (outputFile != null) {
133: cmdl.createArgument().setValue(
134: "-" + OUTPUT_FILE + ":"
135: + outputFile.replace('\\', '/'));
136: }
137:
138: // use the directory containing the target as the output directory
139: File javaFile = new File(createOutputFileName(targetFile,
140: outputFile, plainText));
141:
142: if (javaFile.exists()
143: && targetFile.lastModified() < javaFile.lastModified()) {
144: log("Target is already built - skipping (" + targetFile
145: + ")", Project.MSG_VERBOSE);
146: return;
147: }
148:
149: cmdl.createArgument().setValue(targetFile.getAbsolutePath());
150:
151: final Path classpath = cmdl.createClasspath(getProject());
152: final File javaccJar = JavaCC.getArchiveFile(javaccHome);
153: classpath.createPathElement().setPath(
154: javaccJar.getAbsolutePath());
155: classpath.addJavaRuntime();
156:
157: cmdl.setClassname(JavaCC.getMainClass(classpath,
158: JavaCC.TASKDEF_TYPE_JJDOC));
159:
160: final Commandline.Argument arg = cmdl.createVmArgument();
161: arg.setValue("-mx140M");
162: arg.setValue("-Dinstall.root=" + javaccHome.getAbsolutePath());
163:
164: final Execute process = new Execute(new LogStreamHandler(this ,
165: Project.MSG_INFO, Project.MSG_INFO), null);
166: log(cmdl.describeCommand(), Project.MSG_VERBOSE);
167: process.setCommandline(cmdl.getCommandline());
168:
169: try {
170: if (process.execute() != 0) {
171: throw new BuildException("JJDoc failed.");
172: }
173: } catch (IOException e) {
174: throw new BuildException("Failed to launch JJDoc", e);
175: }
176: }
177:
178: private String createOutputFileName(File destFile,
179: String optionalOutputFile, boolean plain) {
180: String suffix = DEFAULT_SUFFIX_HTML;
181: String javaccFile = destFile.getAbsolutePath().replace('\\',
182: '/');
183:
184: if (plain) {
185: suffix = DEFAULT_SUFFIX_TEXT;
186: }
187:
188: if ((optionalOutputFile == null)
189: || optionalOutputFile.equals("")) {
190: int filePos = javaccFile.lastIndexOf("/");
191:
192: if (filePos >= 0) {
193: javaccFile = javaccFile.substring(filePos + 1);
194: }
195:
196: int suffixPos = javaccFile.lastIndexOf('.');
197:
198: if (suffixPos == -1) {
199: optionalOutputFile = javaccFile + suffix;
200: } else {
201: String currentSuffix = javaccFile.substring(suffixPos);
202:
203: if (currentSuffix.equals(suffix)) {
204: optionalOutputFile = javaccFile + suffix;
205: } else {
206: optionalOutputFile = javaccFile.substring(0,
207: suffixPos)
208: + suffix;
209: }
210: }
211: } else {
212: optionalOutputFile = optionalOutputFile.replace('\\', '/');
213: }
214:
215: return (getProject().getBaseDir() + "/" + optionalOutputFile)
216: .replace('\\', '/');
217: }
218: }
|