1 | /*
|
---|
2 | * Copyright 2001-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 |
|
---|
18 | package org.apache.tools.ant.taskdefs.optional.metamata;
|
---|
19 |
|
---|
20 | import java.io.File;
|
---|
21 | import java.io.FileWriter;
|
---|
22 | import java.io.IOException;
|
---|
23 | import java.io.PrintWriter;
|
---|
24 | import java.util.Vector;
|
---|
25 | import org.apache.tools.ant.BuildException;
|
---|
26 | import org.apache.tools.ant.Project;
|
---|
27 | import org.apache.tools.ant.taskdefs.Execute;
|
---|
28 | import org.apache.tools.ant.taskdefs.ExecuteStreamHandler;
|
---|
29 | import org.apache.tools.ant.taskdefs.LogStreamHandler;
|
---|
30 | import org.apache.tools.ant.types.Commandline;
|
---|
31 | import org.apache.tools.ant.types.Path;
|
---|
32 | import org.apache.tools.ant.util.JavaEnvUtils;
|
---|
33 |
|
---|
34 | /**
|
---|
35 | * Simple Metamata MParse task.
|
---|
36 | * Based on the original written by
|
---|
37 | * <a href="mailto:[email protected]">Thomas Haas</a>.
|
---|
38 | *
|
---|
39 | * This version was written for Metamata 2.0 available at
|
---|
40 | * <a href="http://www.metamata.com">http://www.metamata.com</a>
|
---|
41 | *
|
---|
42 | * @todo make a subclass of AbstractMetaMataTask
|
---|
43 | */
|
---|
44 | public class MParse extends AbstractMetamataTask {
|
---|
45 |
|
---|
46 | private File target = null;
|
---|
47 | private boolean verbose = false;
|
---|
48 | private boolean debugparser = false;
|
---|
49 | private boolean debugscanner = false;
|
---|
50 | private boolean cleanup = false;
|
---|
51 |
|
---|
52 | /** The .jj file to process; required. */
|
---|
53 | public void setTarget(File target) {
|
---|
54 | this.target = target;
|
---|
55 | }
|
---|
56 |
|
---|
57 | /** set verbose mode */
|
---|
58 | public void setVerbose(boolean flag) {
|
---|
59 | verbose = flag;
|
---|
60 | }
|
---|
61 |
|
---|
62 | /** set scanner debug mode; optional, default false */
|
---|
63 | public void setDebugscanner(boolean flag) {
|
---|
64 | debugscanner = flag;
|
---|
65 | }
|
---|
66 |
|
---|
67 | /** set parser debug mode; optional, default false */
|
---|
68 | public void setDebugparser(boolean flag) {
|
---|
69 | debugparser = flag;
|
---|
70 | }
|
---|
71 |
|
---|
72 | /** Remove the intermediate Sun JavaCC file
|
---|
73 | * ; optional, default false.
|
---|
74 | */
|
---|
75 | public void setCleanup(boolean value) {
|
---|
76 | cleanup = value;
|
---|
77 | }
|
---|
78 |
|
---|
79 | public MParse() {
|
---|
80 | cmdl.setVm(JavaEnvUtils.getJreExecutable("java"));
|
---|
81 | cmdl.setClassname("com.metamata.jj.MParse");
|
---|
82 | }
|
---|
83 |
|
---|
84 |
|
---|
85 | /** execute the command line */
|
---|
86 | public void execute() throws BuildException {
|
---|
87 | try {
|
---|
88 | setUp();
|
---|
89 | ExecuteStreamHandler handler = createStreamHandler();
|
---|
90 | _execute(handler);
|
---|
91 | } finally {
|
---|
92 | cleanUp();
|
---|
93 | }
|
---|
94 | }
|
---|
95 |
|
---|
96 | /** return the default stream handler for this task */
|
---|
97 | protected ExecuteStreamHandler createStreamHandler() {
|
---|
98 | return new LogStreamHandler(this, Project.MSG_INFO, Project.MSG_INFO);
|
---|
99 | }
|
---|
100 |
|
---|
101 | /**
|
---|
102 | * check the options and build the command line
|
---|
103 | */
|
---|
104 | protected void setUp() throws BuildException {
|
---|
105 | checkOptions();
|
---|
106 |
|
---|
107 | // set the classpath as the jar files
|
---|
108 | File[] jars = getMetamataLibs();
|
---|
109 | final Path classPath = cmdl.createClasspath(getProject());
|
---|
110 | for (int i = 0; i < jars.length; i++) {
|
---|
111 | classPath.createPathElement().setLocation(jars[i]);
|
---|
112 | }
|
---|
113 |
|
---|
114 | // set the metamata.home property
|
---|
115 | final Commandline.Argument vmArgs = cmdl.createVmArgument();
|
---|
116 | vmArgs.setValue("-Dmetamata.home=" + metamataHome.getAbsolutePath());
|
---|
117 |
|
---|
118 |
|
---|
119 | // write all the options to a temp file and use it ro run the process
|
---|
120 | Vector opts = getOptions();
|
---|
121 | String[] options = new String[ opts.size() ];
|
---|
122 | opts.copyInto(options);
|
---|
123 |
|
---|
124 | optionsFile = createTmpFile();
|
---|
125 | generateOptionsFile(optionsFile, options);
|
---|
126 | Commandline.Argument args = cmdl.createArgument();
|
---|
127 | args.setLine("-arguments " + optionsFile.getAbsolutePath());
|
---|
128 | }
|
---|
129 |
|
---|
130 |
|
---|
131 | /** execute the process with a specific handler */
|
---|
132 | protected void _execute(ExecuteStreamHandler handler) throws BuildException {
|
---|
133 | // target has been checked as a .jj, see if there is a matching
|
---|
134 | // java file and if it is needed to run to process the grammar
|
---|
135 | String pathname = target.getAbsolutePath();
|
---|
136 | int pos = pathname.length() - ".jj".length();
|
---|
137 | pathname = pathname.substring(0, pos) + ".java";
|
---|
138 | File javaFile = new File(pathname);
|
---|
139 | if (javaFile.exists() && target.lastModified() < javaFile.lastModified()) {
|
---|
140 | getProject().log("Target is already build - skipping (" + target + ")");
|
---|
141 | return;
|
---|
142 | }
|
---|
143 |
|
---|
144 | final Execute process = new Execute(handler);
|
---|
145 | log(cmdl.describeCommand(), Project.MSG_VERBOSE);
|
---|
146 | process.setCommandline(cmdl.getCommandline());
|
---|
147 | try {
|
---|
148 | if (process.execute() != 0) {
|
---|
149 | throw new BuildException("Metamata task failed.");
|
---|
150 | }
|
---|
151 | } catch (IOException e) {
|
---|
152 | throw new BuildException("Failed to launch Metamata task: ", e);
|
---|
153 | }
|
---|
154 | }
|
---|
155 |
|
---|
156 | /** clean up all the mess that we did with temporary objects */
|
---|
157 | protected void cleanUp() {
|
---|
158 | if (optionsFile != null) {
|
---|
159 | optionsFile.delete();
|
---|
160 | optionsFile = null;
|
---|
161 | }
|
---|
162 | if (cleanup) {
|
---|
163 | String name = target.getName();
|
---|
164 | int pos = name.length() - ".jj".length();
|
---|
165 | name = "__jj" + name.substring(0, pos) + ".sunjj";
|
---|
166 | final File sunjj = new File(target.getParent(), name);
|
---|
167 | if (sunjj.exists()) {
|
---|
168 | getProject().log("Removing stale file: " + sunjj.getName());
|
---|
169 | sunjj.delete();
|
---|
170 | }
|
---|
171 | }
|
---|
172 | }
|
---|
173 |
|
---|
174 | /**
|
---|
175 | * return an array of files containing the path to the needed
|
---|
176 | * libraries to run metamata. The file are not checked for
|
---|
177 | * existence. You should do this yourself if needed or simply let the
|
---|
178 | * forked process do it for you.
|
---|
179 | * @return array of jars/zips needed to run metamata.
|
---|
180 | */
|
---|
181 | protected File[] getMetamataLibs() {
|
---|
182 | Vector files = new Vector();
|
---|
183 | files.addElement(new File(metamataHome, "lib/metamata.jar"));
|
---|
184 | files.addElement(new File(metamataHome, "bin/lib/JavaCC.zip"));
|
---|
185 |
|
---|
186 | File[] array = new File[ files.size() ];
|
---|
187 | files.copyInto(array);
|
---|
188 | return array;
|
---|
189 | }
|
---|
190 |
|
---|
191 |
|
---|
192 | /**
|
---|
193 | * validate options set and resolve files and paths
|
---|
194 | * @throws BuildException thrown if an option has an incorrect state.
|
---|
195 | */
|
---|
196 | protected void checkOptions() throws BuildException {
|
---|
197 | // check that the home is ok.
|
---|
198 | if (metamataHome == null || !metamataHome.exists()) {
|
---|
199 | throw new BuildException("'metamatahome' must point to Metamata home directory.");
|
---|
200 | }
|
---|
201 | metamataHome = getProject().resolveFile(metamataHome.getPath());
|
---|
202 |
|
---|
203 | // check that the needed jar exists.
|
---|
204 | File[] jars = getMetamataLibs();
|
---|
205 | for (int i = 0; i < jars.length; i++) {
|
---|
206 | if (!jars[i].exists()) {
|
---|
207 | throw new BuildException(jars[i]
|
---|
208 | + " does not exist. Check your metamata installation.");
|
---|
209 | }
|
---|
210 | }
|
---|
211 |
|
---|
212 | // check that the target is ok and resolve it.
|
---|
213 | if (target == null || !target.isFile()
|
---|
214 | || !target.getName().endsWith(".jj")) {
|
---|
215 | throw new BuildException("Invalid target: " + target);
|
---|
216 | }
|
---|
217 | target = getProject().resolveFile(target.getPath());
|
---|
218 | }
|
---|
219 |
|
---|
220 | /**
|
---|
221 | * return all options of the command line as string elements
|
---|
222 | * @return an array of options corresponding to the setted options.
|
---|
223 | */
|
---|
224 | protected Vector getOptions() {
|
---|
225 | Vector options = new Vector();
|
---|
226 | if (verbose) {
|
---|
227 | options.addElement("-verbose");
|
---|
228 | }
|
---|
229 | if (debugscanner) {
|
---|
230 | options.addElement("-ds");
|
---|
231 | }
|
---|
232 | if (debugparser) {
|
---|
233 | options.addElement("-dp");
|
---|
234 | }
|
---|
235 | if (classPath != null) {
|
---|
236 | options.addElement("-classpath");
|
---|
237 | options.addElement(classPath.toString());
|
---|
238 | }
|
---|
239 | if (sourcePath != null) {
|
---|
240 | options.addElement("-sourcepath");
|
---|
241 | options.addElement(sourcePath.toString());
|
---|
242 | }
|
---|
243 | options.addElement(target.getAbsolutePath());
|
---|
244 | return options;
|
---|
245 | }
|
---|
246 |
|
---|
247 | /**
|
---|
248 | * write all options to a file with one option / line
|
---|
249 | * @param tofile the file to write the options to.
|
---|
250 | * @param options the array of options element to write to the file.
|
---|
251 | * @throws BuildException thrown if there is a problem while writing
|
---|
252 | * to the file.
|
---|
253 | */
|
---|
254 | protected void generateOptionsFile(File tofile, String[] options) throws BuildException {
|
---|
255 | FileWriter fw = null;
|
---|
256 | try {
|
---|
257 | fw = new FileWriter(tofile);
|
---|
258 | PrintWriter pw = new PrintWriter(fw);
|
---|
259 | for (int i = 0; i < options.length; i++) {
|
---|
260 | pw.println(options[i]);
|
---|
261 | }
|
---|
262 | pw.flush();
|
---|
263 | } catch (IOException e) {
|
---|
264 | throw new BuildException("Error while writing options file " + tofile, e);
|
---|
265 | } finally {
|
---|
266 | if (fw != null) {
|
---|
267 | try {
|
---|
268 | fw.close();
|
---|
269 | } catch (IOException ignored) {
|
---|
270 | // ignore
|
---|
271 | }
|
---|
272 | }
|
---|
273 | }
|
---|
274 | }
|
---|
275 | }
|
---|