KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > izforge > izpack > util > FileExecutor


1 /*
2  * IzPack - Copyright 2001-2007 Julien Ponge, All Rights Reserved.
3  *
4  * http://www.izforge.com/izpack/
5  * http://developer.berlios.de/projects/izpack/
6  *
7  * Copyright 2002 Olexij Tkatchenko
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */

21
22 package com.izforge.izpack.util;
23
24 import java.io.BufferedReader JavaDoc;
25 import java.io.BufferedWriter JavaDoc;
26 import java.io.File JavaDoc;
27 import java.io.IOException JavaDoc;
28 import java.io.InputStreamReader JavaDoc;
29 import java.io.Reader JavaDoc;
30 import java.io.StringWriter JavaDoc;
31 import java.io.Writer JavaDoc;
32 import java.util.ArrayList JavaDoc;
33 import java.util.Collection JavaDoc;
34 import java.util.Iterator JavaDoc;
35 import java.util.List JavaDoc;
36
37 import com.izforge.izpack.ExecutableFile;
38
39 /**
40  * Executes a bunch of files. This class is intended to do a system dependent installation
41  * postprocessing. Executable file can be any file installed with current package. After execution
42  * the file can be optionally removed. Before execution on Unix systems execution flag will be set
43  * on processed file.
44  *
45  * @author Olexij Tkatchenko <ot@parcs.de>
46  */

47 public class FileExecutor
48 {
49
50     /**
51      * This is a grabber for stdout and stderr. It will be launched once at command execution end
52      * terminates if the apropriate stream runs out of data.
53      *
54      * @author Olexij Tkatchenko <ot@parcs.de>
55      */

56     private static class MonitorInputStream implements Runnable JavaDoc
57     {
58
59         private BufferedReader JavaDoc reader;
60
61         private BufferedWriter JavaDoc writer;
62
63         private boolean shouldStop = false;
64
65         public MonitorInputStream(Reader JavaDoc in, Writer JavaDoc out)
66         {
67             reader = new BufferedReader JavaDoc(in);
68             writer = new BufferedWriter JavaDoc(out);
69         }
70
71         public void doStop()
72         {
73             shouldStop = true;
74         }
75
76         public void run()
77         {
78             try
79             {
80                 String JavaDoc line;
81                 while ((line = reader.readLine()) != null)
82                 {
83                     writer.write(line);
84                     writer.newLine();
85                     writer.flush();
86                     if (shouldStop) return;
87                 }
88             }
89             catch (IOException JavaDoc ioe)
90             {
91                 ioe.printStackTrace(System.out);
92             }
93         }
94     }
95
96     private boolean stopThread(Thread JavaDoc t, MonitorInputStream m)
97     {
98         m.doStop();
99         long softTimeout = 1000;
100         try
101         {
102             t.join(softTimeout);
103         }
104         catch (InterruptedException JavaDoc e)
105         {}
106
107         if (!t.isAlive()) return true;
108
109         t.interrupt();
110         long hardTimeout = 1000;
111         try
112         {
113             t.join(hardTimeout);
114         }
115         catch (InterruptedException JavaDoc e)
116         {}
117         return !t.isAlive();
118     }
119
120     /**
121      * Constructs a new executor. The executable files specified must have pretranslated paths
122      * (variables expanded and file separator characters converted if necessary).
123      *
124      * @param files the executable files to process
125      */

126     public FileExecutor(Collection JavaDoc files)
127     {
128         this.files = files;
129     }
130
131     /**
132      * Constructs a new executor.
133      */

134     public FileExecutor()
135     {
136         this.files = null;
137     }
138
139     /**
140      * Gets the output of the given (console based) commandline
141      *
142      * @param aCommandLine to execute
143      * @return the result of the command
144      */

145     public static String JavaDoc getExecOutput(String JavaDoc[] aCommandLine)
146     {
147         return getExecOutput(aCommandLine, false);
148
149     }
150
151     /**
152      * Executes the given Command and gets the result of StdOut, or if exec returns !=0: StdErr.
153      *
154      * @param aCommandLine aCommandLine to execute
155      * @param forceToGetStdOut if true returns stdout
156      * @return the result of the command stdout or stderr if exec returns !=0
157      */

158     public static String JavaDoc getExecOutput(String JavaDoc[] aCommandLine, boolean forceToGetStdOut)
159     {
160         FileExecutor fe = new FileExecutor();
161
162         String JavaDoc[] execOut = new String JavaDoc[2];
163
164         int execResult = fe.executeCommand(aCommandLine, execOut);
165
166         if (execResult == 0)
167
168             return execOut[0];
169
170         else if (forceToGetStdOut == true)
171             return execOut[0];
172         else
173             return execOut[1];
174     }
175
176     /**
177      * Executed a system command and waits for completion.
178      *
179      * @param params system command as string array
180      * @param output contains output of the command index 0 = standard output index 1 = standard
181      * error
182      * @return exit status of process
183      */

184     public int executeCommand(String JavaDoc[] params, String JavaDoc[] output)
185     {
186         StringBuffer JavaDoc retval = new StringBuffer JavaDoc();
187         retval.append("executeCommand\n");
188         if (params != null)
189         {
190             for (int i = 0; i < params.length; i++)
191             {
192                 retval.append("\tparams: ").append(params[i]);
193                 retval.append("\n");
194             }
195         }
196         Process JavaDoc process = null;
197         MonitorInputStream outMonitor = null;
198         MonitorInputStream errMonitor = null;
199         Thread JavaDoc t1 = null;
200         Thread JavaDoc t2 = null;
201         int exitStatus = -1;
202
203         Debug.trace(retval);
204
205         try
206         {
207             // execute command
208
process = Runtime.getRuntime().exec(params);
209
210             boolean console = false;// TODO: impl from xml <execute
211
// in_console=true ...>, but works already
212
// if this flag is true
213
if (console)
214             {
215                 Console c = new Console(process);
216                 // save command output
217
output[0] = c.getOutputData();
218                 output[1] = c.getErrorData();
219                 exitStatus = process.exitValue();
220             }
221             else
222             {
223                 StringWriter JavaDoc outWriter = new StringWriter JavaDoc();
224                 StringWriter JavaDoc errWriter = new StringWriter JavaDoc();
225
226                 InputStreamReader JavaDoc or = new InputStreamReader JavaDoc(process.getInputStream());
227                 InputStreamReader JavaDoc er = new InputStreamReader JavaDoc(process.getErrorStream());
228                 outMonitor = new MonitorInputStream(or, outWriter);
229                 errMonitor = new MonitorInputStream(er, errWriter);
230                 t1 = new Thread JavaDoc(outMonitor);
231                 t2 = new Thread JavaDoc(errMonitor);
232                 t1.setDaemon(true);
233                 t2.setDaemon(true);
234                 t1.start();
235                 t2.start();
236
237                 // wait for command to complete
238
exitStatus = process.waitFor();
239                 t1.join();
240                 t2.join();
241
242                 // save command output
243
output[0] = outWriter.toString();
244                 Debug.trace("stdout:");
245                 Debug.trace(output[0]);
246                 output[1] = errWriter.toString();
247                 Debug.trace("stderr:");
248                 Debug.trace(output[1]);
249             }
250             Debug.trace("exit status: " + Integer.toString(exitStatus));
251         }
252         catch (InterruptedException JavaDoc e)
253         {
254             if (Debug.tracing()) e.printStackTrace(System.err);
255             stopThread(t1, outMonitor);
256             stopThread(t2, errMonitor);
257             output[0] = "";
258             output[1] = e.getMessage() + "\n";
259             process.destroy();
260         }
261         catch (IOException JavaDoc e)
262         {
263             if (Debug.tracing()) e.printStackTrace(System.err);
264             output[0] = "";
265             output[1] = e.getMessage() + "\n";
266         }
267         return exitStatus;
268     }
269
270     /**
271      * Executes files specified at construction time.
272      *
273      * @param currentStage the stage of the installation
274      * @param handler The AbstractUIHandler to notify on errors.
275      *
276      * @return 0 on success, else the exit status of the last failed command
277      */

278     public int executeFiles(int currentStage, AbstractUIHandler handler)
279     {
280         int exitStatus = 0;
281         String JavaDoc[] output = new String JavaDoc[2];
282         // String permissions = (System.getProperty("user.name").equals("root"))
283
// ? "a+x" : "u+x";
284
String JavaDoc permissions = "a+x";
285
286         // loop through all executables
287
Iterator JavaDoc efileIterator = files.iterator();
288         while (exitStatus == 0 && efileIterator.hasNext())
289         {
290             ExecutableFile efile = (ExecutableFile) efileIterator.next();
291             boolean deleteAfterwards = !efile.keepFile;
292             File JavaDoc file = new File JavaDoc(efile.path);
293             Debug.trace("handeling executable file " + efile);
294
295             // skip file if not for current OS (it might not have been installed
296
// at all)
297
if (!OsConstraint.oneMatchesCurrentSystem(efile.osList)) continue;
298
299             if (currentStage != ExecutableFile.UNINSTALL && OsVersion.IS_UNIX)
300             {
301                 // fix executable permission for unix systems
302
Debug.trace("making file executable (setting executable flag)");
303                 String JavaDoc[] params = { "/bin/chmod", permissions, file.toString()};
304                 exitStatus = executeCommand(params, output);
305                 if (exitStatus != 0)
306                 {
307                     handler.emitError("file execution error", "Error executing \n" + params[0]
308                             + " " + params[1] + " " + params[2]);
309                     continue;
310                 }
311             }
312
313             // execute command in POSTINSTALL stage
314
if ((exitStatus == 0)
315                     && ((currentStage == ExecutableFile.POSTINSTALL && efile.executionStage == ExecutableFile.POSTINSTALL) || (currentStage == ExecutableFile.UNINSTALL && efile.executionStage == ExecutableFile.UNINSTALL)))
316             {
317                 List JavaDoc paramList = new ArrayList JavaDoc();
318                 if (ExecutableFile.BIN == efile.type)
319                     paramList.add(file.toString());
320
321                 else if (ExecutableFile.JAR == efile.type && null == efile.mainClass)
322                 {
323                     paramList.add(System.getProperty("java.home") + "/bin/java");
324                     paramList.add("-jar");
325                     paramList.add(file.toString());
326                 }
327                 else if (ExecutableFile.JAR == efile.type && null != efile.mainClass)
328                 {
329                     paramList.add(System.getProperty("java.home") + "/bin/java");
330                     paramList.add("-cp");
331                     paramList.add(file.toString());
332                     paramList.add(efile.mainClass);
333                 }
334
335                 if (null != efile.argList && !efile.argList.isEmpty())
336                     paramList.addAll(efile.argList);
337
338                 String JavaDoc[] params = new String JavaDoc[paramList.size()];
339                 for (int i = 0; i < paramList.size(); i++)
340                     params[i] = (String JavaDoc) paramList.get(i);
341
342                 exitStatus = executeCommand(params, output);
343
344                 // bring a dialog depending on return code and failure handling
345
if (exitStatus != 0)
346                 {
347                     deleteAfterwards = false;
348                     String JavaDoc message = output[0] + "\n" + output[1];
349                     if (message.length() == 1)
350                         message = "Failed to execute " + file.toString() + ".";
351
352                     if (efile.onFailure == ExecutableFile.ABORT)
353                     {
354                         // CHECKME: let the user decide or abort anyway?
355
handler.emitError("file execution error", message);
356                     }
357                     else if (efile.onFailure == ExecutableFile.WARN)
358                     {
359                         // CHECKME: let the user decide or abort anyway?
360
handler.emitWarning("file execution error", message);
361                         exitStatus = 0;
362                     }
363                     else
364                     {
365                         if (handler
366                                 .askQuestion(null, "Continue?", AbstractUIHandler.CHOICES_YES_NO) == AbstractUIHandler.ANSWER_YES)
367                             exitStatus = 0;
368                     }
369
370                 }
371
372             }
373
374             // POSTINSTALL executables will be deleted
375
if (efile.executionStage == ExecutableFile.POSTINSTALL && deleteAfterwards)
376             {
377                 if (file.canWrite()) file.delete();
378             }
379
380         }
381         return exitStatus;
382     }
383
384     /** The files to execute. */
385     private Collection JavaDoc files;
386 }
387
Popular Tags