001: package fitnesse.responders;
002:
003: import java.io.BufferedReader;
004: import java.io.File;
005: import java.io.IOException;
006: import java.io.InputStream;
007: import java.io.InputStreamReader;
008: import java.net.URLDecoder;
009:
010: import fitnesse.FitNesseContext;
011: import fitnesse.Responder;
012: import fitnesse.http.Request;
013: import fitnesse.http.Response;
014: import fitnesse.http.SimpleResponse;
015: import fitnesse.util.PropertiesUtil;
016:
017: public class ExecuteProcessResponder implements Responder {
018:
019: public static final String ERROR_MISSING_ARGUMENTS = "Need 1 or more arguments.";
020: public static final String COMMAND_FLAG_WINDOWS = "/C";
021: public static final String COMMAND_NAME_WINDOWS = "cmd.exe";
022: public static final String COMMAND_NAME_WINDOWS_95 = "command.com";
023: public static final String OS_NAME_WINDOWS_95 = "Windows 95";
024: public static final String RESPONDER_KEY = "execArgs";
025: public static final String DEFAULT_ARGS_DELIMITER = ";";
026:
027: private static final String ARGS_DELIMITER_PROPERTY = "ExecuteProcessArgsDelimiter";
028: private static final String WORKING_DIR_PROPERTY = "ExecuteProcessWorkingDir";
029:
030: public String OsName = null;
031:
032: public ExecuteProcessResponder() {
033: this .OsName = getOsName();
034: }
035:
036: public Response makeResponse(FitNesseContext context,
037: Request request) throws Exception {
038: SimpleResponse response = new SimpleResponse();
039: response.setContentType(getContentType(request));
040: response.setContent("Execute Process");
041:
042: String args = request.getInput(RESPONDER_KEY).toString();
043: args = URLDecoder.decode(args, "UTF-8").trim();
044: String result = executeProcess(args);
045: response.setContent(result);
046: return response;
047: }
048:
049: private String getContentType(Request request) {
050: if (request.getResource().endsWith(".hta")) {
051: return "application/hta";
052: }
053: return "application/xml";
054: }
055:
056: private String executeProcess(String args) {
057: String exitValue = "";
058: String errorMessage = "";
059: String output = "";
060:
061: if (args.length() == 0) {
062: errorMessage = ERROR_MISSING_ARGUMENTS;
063: } else {
064:
065: String[] cmd = getCommandArray(args);
066: try {
067: Runtime rt = Runtime.getRuntime();
068: Process proc = rt.exec(cmd);
069:
070: // Error message
071: StreamGobbler errorGobbler = new StreamGobbler(proc
072: .getErrorStream(), "ERROR");
073:
074: // Output
075: StreamGobbler outputGobbler = new StreamGobbler(proc
076: .getInputStream(), "OUTPUT");
077:
078: // Start gobbling
079: errorGobbler.start();
080: outputGobbler.start();
081:
082: // Get process exit value and Gobbler results
083: int val = proc.waitFor();
084: exitValue += val;
085: output = outputGobbler.Result;
086: errorMessage = errorGobbler.Result;
087: } catch (Throwable t) {
088: errorMessage += "Exception: '" + t.toString() + "'";
089: }
090: }
091: return getResultsAsXml(exitValue, output, errorMessage);
092: }
093:
094: public String[] getCommandArray(String args) {
095: String[] cmd = null;
096: String[] argArray = args.split(getArgsDelimiter());
097: if (this .OsName.contains("Windows")) {
098: cmd = new String[2 + argArray.length];
099: argArray = substituteWorkingDir(argArray);
100: if (this .OsName.equals(OS_NAME_WINDOWS_95)) {
101: cmd[0] = COMMAND_NAME_WINDOWS_95;
102: cmd[1] = COMMAND_FLAG_WINDOWS;
103: } else {
104: cmd[0] = COMMAND_NAME_WINDOWS;
105: cmd[1] = COMMAND_FLAG_WINDOWS;
106: }
107: for (int i = 0; i < argArray.length; i++) {
108: cmd[i + 2] = argArray[i];
109: }
110: } else {
111: // Non-windows users are going to have to pass the executor stuff as argument (e.g., "/bin/sh;-c")
112: // We don't yet handle working dir for non-windows -- just pass through...
113: cmd = argArray;
114: }
115: return cmd;
116: }
117:
118: public String[] substituteWorkingDir(String[] argArray) {
119: // If an arg starts with a .\, we substitute the working dir for the .
120: // TODO: Be more sophisticated. ;-)
121: for (int i = 0; i < argArray.length; i++) {
122: if ((argArray[i].indexOf(".\\") == 0)
123: || (argArray[i].indexOf("\".\\") == 0)) {
124: argArray[i] = argArray[i].replace(".\\",
125: getWorkingDir() + "\\");
126: }
127: }
128: return argArray;
129: }
130:
131: private String getWorkingDir() {
132: return PropertiesUtil.getProperty(WORKING_DIR_PROPERTY,
133: getCurrentDir());
134: }
135:
136: private String getCurrentDir() {
137: String path = "";
138: File currentDir = new File(".");
139: try {
140: path = currentDir.getCanonicalPath();
141: } catch (IOException e) {
142: // Drop the exception -- we'll just return empty string for now
143: }
144: return path;
145: }
146:
147: public String getResultsAsXml(String exitValue, String output,
148: String errorMessage) {
149: StringBuffer asXml = new StringBuffer();
150: asXml.append("<?xml version=\"1.0\"?> ");
151: asXml.append("<process> ");
152: asXml.append("<exit-val>" + exitValue + "</exit-val> ");
153: asXml.append("<output>" + output + "</output> ");
154: asXml.append("<error>" + errorMessage + "</error> ");
155: asXml.append("</process>");
156: return asXml.toString();
157: }
158:
159: private String getArgsDelimiter() {
160: return PropertiesUtil.getProperty(ARGS_DELIMITER_PROPERTY,
161: DEFAULT_ARGS_DELIMITER);
162: }
163:
164: private String getOsName() {
165: return System.getProperty("os.name");
166: }
167: }
168:
169: class StreamGobbler extends Thread {
170: InputStream is;
171: String type;
172:
173: StreamGobbler(InputStream is, String type) {
174: this .is = is;
175: this .type = type;
176: }
177:
178: public String Result = "";
179:
180: public void run() {
181: try {
182: InputStreamReader isr = new InputStreamReader(is);
183: BufferedReader br = new BufferedReader(isr);
184: String line = "";
185: while ((line = br.readLine()) != null) {
186: Result += line + "\n";
187: }
188: } catch (IOException ioe) {
189: Result += "Exception: " + ioe.getStackTrace().toString()
190: + "\n";
191: }
192: }
193: }
|