1. /*
  2. * Copyright 2003-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.javacc;
  18. import java.io.File;
  19. import java.io.IOException;
  20. import java.util.Enumeration;
  21. import java.util.Hashtable;
  22. import org.apache.tools.ant.BuildException;
  23. import org.apache.tools.ant.Project;
  24. import org.apache.tools.ant.Task;
  25. import org.apache.tools.ant.taskdefs.Execute;
  26. import org.apache.tools.ant.taskdefs.LogStreamHandler;
  27. import org.apache.tools.ant.types.Commandline;
  28. import org.apache.tools.ant.types.CommandlineJava;
  29. import org.apache.tools.ant.types.Path;
  30. import org.apache.tools.ant.util.JavaEnvUtils;
  31. /**
  32. * Runs the JJDoc compiler compiler.
  33. *
  34. */
  35. public class JJDoc extends Task {
  36. // keys to optional attributes
  37. private static final String OUTPUT_FILE = "OUTPUT_FILE";
  38. private static final String TEXT = "TEXT";
  39. private static final String ONE_TABLE = "ONE_TABLE";
  40. private final Hashtable optionalAttrs = new Hashtable();
  41. private String outputFile = null;
  42. private boolean plainText = false;
  43. private static final String DEFAULT_SUFFIX_HTML = ".html";
  44. private static final String DEFAULT_SUFFIX_TEXT = ".txt";
  45. // required attributes
  46. private File target = null;
  47. private File javaccHome = null;
  48. private CommandlineJava cmdl = new CommandlineJava();
  49. /**
  50. * Sets the TEXT BNF documentation option.
  51. */
  52. public void setText(boolean plainText) {
  53. optionalAttrs.put(TEXT, new Boolean(plainText));
  54. this.plainText = plainText;
  55. }
  56. /**
  57. * Sets the ONE_TABLE documentation option.
  58. */
  59. public void setOnetable(boolean oneTable) {
  60. optionalAttrs.put(ONE_TABLE, new Boolean(oneTable));
  61. }
  62. /**
  63. * The outputfile to write the generated BNF documentation file to.
  64. * If not set, the file is written with the same name as
  65. * the JavaCC grammar file with a suffix .html or .txt.
  66. */
  67. public void setOutputfile(String outputFile) {
  68. this.outputFile = outputFile;
  69. }
  70. /**
  71. * The javacc grammar file to process.
  72. */
  73. public void setTarget(File target) {
  74. this.target = target;
  75. }
  76. /**
  77. * The directory containing the JavaCC distribution.
  78. */
  79. public void setJavacchome(File javaccHome) {
  80. this.javaccHome = javaccHome;
  81. }
  82. public JJDoc() {
  83. cmdl.setVm(JavaEnvUtils.getJreExecutable("java"));
  84. }
  85. public void execute() throws BuildException {
  86. // load command line with optional attributes
  87. Enumeration iter = optionalAttrs.keys();
  88. while (iter.hasMoreElements()) {
  89. String name = (String) iter.nextElement();
  90. Object value = optionalAttrs.get(name);
  91. cmdl.createArgument()
  92. .setValue("-" + name + ":" + value.toString());
  93. }
  94. if (target == null || !target.isFile()) {
  95. throw new BuildException("Invalid target: " + target);
  96. }
  97. if (outputFile != null) {
  98. cmdl.createArgument() .setValue("-" + OUTPUT_FILE + ":"
  99. + outputFile.replace('\\', '/'));
  100. }
  101. // use the directory containing the target as the output directory
  102. File javaFile = new File(createOutputFileName(target, outputFile,
  103. plainText));
  104. if (javaFile.exists()
  105. && target.lastModified() < javaFile.lastModified()) {
  106. log("Target is already built - skipping (" + target + ")",
  107. Project.MSG_VERBOSE);
  108. return;
  109. }
  110. cmdl.createArgument().setValue(target.getAbsolutePath());
  111. cmdl.setClassname(JavaCC.getMainClass(javaccHome,
  112. JavaCC.TASKDEF_TYPE_JJDOC));
  113. final Path classpath = cmdl.createClasspath(getProject());
  114. final File javaccJar = JavaCC.getArchiveFile(javaccHome);
  115. classpath.createPathElement().setPath(javaccJar.getAbsolutePath());
  116. classpath.addJavaRuntime();
  117. final Commandline.Argument arg = cmdl.createVmArgument();
  118. arg.setValue("-mx140M");
  119. arg.setValue("-Dinstall.root=" + javaccHome.getAbsolutePath());
  120. final Execute process =
  121. new Execute(new LogStreamHandler(this,
  122. Project.MSG_INFO,
  123. Project.MSG_INFO),
  124. null);
  125. log(cmdl.describeCommand(), Project.MSG_VERBOSE);
  126. process.setCommandline(cmdl.getCommandline());
  127. try {
  128. if (process.execute() != 0) {
  129. throw new BuildException("JJDoc failed.");
  130. }
  131. } catch (IOException e) {
  132. throw new BuildException("Failed to launch JJDoc", e);
  133. }
  134. }
  135. private String createOutputFileName(File target, String optionalOutputFile,
  136. boolean plainText) {
  137. String suffix = DEFAULT_SUFFIX_HTML;
  138. String javaccFile = target.getAbsolutePath().replace('\\', '/');
  139. if (plainText) {
  140. suffix = DEFAULT_SUFFIX_TEXT;
  141. }
  142. if ((optionalOutputFile == null) || optionalOutputFile.equals("")) {
  143. int filePos = javaccFile.lastIndexOf("/");
  144. if (filePos >= 0) {
  145. javaccFile = javaccFile.substring(filePos + 1);
  146. }
  147. int suffixPos = javaccFile.lastIndexOf('.');
  148. if (suffixPos == -1) {
  149. optionalOutputFile = javaccFile + suffix;
  150. } else {
  151. String currentSuffix = javaccFile.substring(suffixPos);
  152. if (currentSuffix.equals(suffix)) {
  153. optionalOutputFile = javaccFile + suffix;
  154. } else {
  155. optionalOutputFile = javaccFile.substring(0, suffixPos)
  156. + suffix;
  157. }
  158. }
  159. } else {
  160. optionalOutputFile = optionalOutputFile.replace('\\', '/');
  161. }
  162. return (getProject().getBaseDir() + "/" + optionalOutputFile)
  163. .replace('\\', '/');
  164. }
  165. }