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;
020:
021: import java.io.BufferedReader;
022: import java.io.File;
023: import java.io.FileWriter;
024: import java.io.IOException;
025: import java.io.InputStream;
026: import java.io.InputStreamReader;
027: import java.io.PrintWriter;
028:
029: import org.apache.tools.ant.BuildException;
030: import org.apache.tools.ant.MagicNames;
031: import org.apache.tools.ant.Project;
032: import org.apache.tools.ant.Task;
033:
034: /**
035: * Executes a given command if the os platform is appropriate.
036: *
037: * <p><strong>As of Ant 1.2, this class is no longer the
038: * implementation of Ant's <exec> task - it is considered to be
039: * dead code by the Ant developers and is unmaintained. Don't use
040: * it.</strong></p>
041: *
042: * @deprecated since 1.2.
043: * delegate to {@link org.apache.tools.ant.taskdefs.Execute Execute}
044: * instead.
045: */
046: public class Exec extends Task {
047: private String os;
048: private String out;
049: private File dir;
050: private String command;
051: // CheckStyle:VisibilityModifier OFF - bc
052: protected PrintWriter fos = null;
053: // CheckStyle:VisibilityModifier ON
054: private boolean failOnError = false;
055:
056: /**
057: * Constructor for Exec.
058: * Prints a warning message to std error.
059: */
060: public Exec() {
061: System.err.println("As of Ant 1.2 released in October 2000, "
062: + "the Exec class");
063: System.err.println("is considered to be dead code by the Ant "
064: + "developers and is unmaintained.");
065: System.err.println("Don\'t use it!");
066: }
067:
068: /**
069: * Execute the task.
070: * @throws BuildException on error
071: */
072: public void execute() throws BuildException {
073: run(command);
074: }
075:
076: /**
077: * Execute the command.
078: * @param command the command to exec
079: * @return the exit value of the command
080: * @throws BuildException on error
081: */
082: protected int run(String command) throws BuildException {
083:
084: int err = -1; // assume the worst
085:
086: // test if os match
087: String myos = System.getProperty("os.name");
088: log("Myos = " + myos, Project.MSG_VERBOSE);
089: if ((os != null) && (os.indexOf(myos) < 0)) {
090: // this command will be executed only on the specified OS
091: log("Not found in " + os, Project.MSG_VERBOSE);
092: return 0;
093: }
094:
095: // default directory to the project's base directory
096: if (dir == null) {
097: dir = getProject().getBaseDir();
098: }
099:
100: if (myos.toLowerCase().indexOf("windows") >= 0) {
101: if (!dir.equals(getProject().resolveFile("."))) {
102: if (myos.toLowerCase().indexOf("nt") >= 0) {
103: command = "cmd /c cd " + dir + " && " + command;
104: } else {
105: String ant = getProject().getProperty(
106: MagicNames.ANT_HOME);
107: if (ant == null) {
108: throw new BuildException("Property '"
109: + MagicNames.ANT_HOME + "' not "
110: + "found", getLocation());
111: }
112:
113: String antRun = getProject().resolveFile(
114: ant + "/bin/antRun.bat").toString();
115: command = antRun + " " + dir + " " + command;
116: }
117: }
118: } else {
119: String ant = getProject().getProperty(MagicNames.ANT_HOME);
120: if (ant == null) {
121: throw new BuildException("Property '"
122: + MagicNames.ANT_HOME + "' not found",
123: getLocation());
124: }
125: String antRun = getProject().resolveFile(
126: ant + "/bin/antRun").toString();
127:
128: command = antRun + " " + dir + " " + command;
129: }
130:
131: try {
132: // show the command
133: log(command, Project.MSG_VERBOSE);
134:
135: // exec command on system runtime
136: Process proc = Runtime.getRuntime().exec(command);
137:
138: if (out != null) {
139: fos = new PrintWriter(new FileWriter(out));
140: log("Output redirected to " + out, Project.MSG_VERBOSE);
141: }
142:
143: // copy input and error to the output stream
144: StreamPumper inputPumper = new StreamPumper(proc
145: .getInputStream(), Project.MSG_INFO);
146: StreamPumper errorPumper = new StreamPumper(proc
147: .getErrorStream(), Project.MSG_WARN);
148:
149: // starts pumping away the generated output/error
150: inputPumper.start();
151: errorPumper.start();
152:
153: // Wait for everything to finish
154: proc.waitFor();
155: inputPumper.join();
156: errorPumper.join();
157: proc.destroy();
158:
159: // close the output file if required
160: logFlush();
161:
162: // check its exit value
163: err = proc.exitValue();
164: if (err != 0) {
165: if (failOnError) {
166: throw new BuildException("Exec returned: " + err,
167: getLocation());
168: } else {
169: log("Result: " + err, Project.MSG_ERR);
170: }
171: }
172: } catch (IOException ioe) {
173: throw new BuildException("Error exec: " + command, ioe,
174: getLocation());
175: } catch (InterruptedException ex) {
176: //ignore
177: }
178:
179: return err;
180: }
181:
182: /**
183: * Set the directory.
184: * @param d a <code>String</code> value
185: */
186: public void setDir(String d) {
187: this .dir = getProject().resolveFile(d);
188: }
189:
190: /**
191: * Set the Operating System that this exec is to run in.
192: * @param os a <code>String</code> value
193: */
194: public void setOs(String os) {
195: this .os = os;
196: }
197:
198: /**
199: * Set the command to exec.
200: * @param command a <code>String</code> value
201: */
202: public void setCommand(String command) {
203: this .command = command;
204: }
205:
206: /**
207: * Set the output filename.
208: * @param out a <code>String</code> value
209: */
210: public void setOutput(String out) {
211: this .out = out;
212: }
213:
214: /**
215: * Set the failOnError attribute.
216: * Default is false.
217: * @param fail a <code>boolean</code> value
218: */
219: public void setFailonerror(boolean fail) {
220: failOnError = fail;
221: }
222:
223: /**
224: * Log an output message.
225: * @param line the line to putput
226: * @param messageLevel the level of logging - ignored
227: * if output is going to a file
228: */
229: protected void outputLog(String line, int messageLevel) {
230: if (fos == null) {
231: log(line, messageLevel);
232: } else {
233: fos.println(line);
234: }
235: }
236:
237: /**
238: * Close output.
239: */
240: protected void logFlush() {
241: if (fos != null) {
242: fos.close();
243: }
244: }
245:
246: // Inner class for continually pumping the input stream during
247: // Process's runtime.
248: class StreamPumper extends Thread {
249: private BufferedReader din;
250: private int messageLevel;
251: private boolean endOfStream = false;
252: private static final int SLEEP_TIME = 5;
253:
254: public StreamPumper(InputStream is, int messageLevel) {
255: this .din = new BufferedReader(new InputStreamReader(is));
256: this .messageLevel = messageLevel;
257: }
258:
259: public void pumpStream() throws IOException {
260: if (!endOfStream) {
261: String line = din.readLine();
262:
263: if (line != null) {
264: outputLog(line, messageLevel);
265: } else {
266: endOfStream = true;
267: }
268: }
269: }
270:
271: public void run() {
272: try {
273: try {
274: while (!endOfStream) {
275: pumpStream();
276: sleep(SLEEP_TIME);
277: }
278: } catch (InterruptedException ie) {
279: //ignore
280: }
281: din.close();
282: } catch (IOException ioe) {
283: // ignore
284: }
285: }
286: }
287: }
|