KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > ivata > groupware > admin > script > ExternalScriptExecutor


1 /*
2  * Copyright (c) 2001 - 2005 ivata limited.
3  * All rights reserved.
4  * -----------------------------------------------------------------------------
5  * ivata groupware may be redistributed under the GNU General Public
6  * License as published by the Free Software Foundation;
7  * version 2 of the License.
8  *
9  * These programs are free software; you can redistribute them and/or
10  * modify them under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; version 2 of the License.
12  *
13  * These programs are distributed in the hope that they will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  * See the GNU General Public License in the file LICENSE.txt for more
18  * details.
19  *
20  * If you would like a copy of the GNU General Public License write to
21  *
22  * Free Software Foundation, Inc.
23  * 59 Temple Place - Suite 330
24  * Boston, MA 02111-1307, USA.
25  *
26  *
27  * To arrange commercial support and licensing, contact ivata at
28  * http://www.ivata.com/contact.jsp
29  * -----------------------------------------------------------------------------
30  * $Log: ExternalScriptExecutor.java,v $
31  * Revision 1.2 2005/04/09 17:19:56 colinmacleod
32  * Changed copyright text to GPL v2 explicitly.
33  *
34  * Revision 1.1.1.1 2005/03/10 17:51:39 colinmacleod
35  * Restructured ivata op around Hibernate/PicoContainer.
36  * Renamed ivata groupware.
37  *
38  * Revision 1.4 2004/11/12 18:16:07 colinmacleod
39  * Ordered imports.
40  *
41  * Revision 1.3 2004/11/12 15:57:18 colinmacleod
42  * Removed dependencies on SSLEXT.
43  * Moved Persistence classes to ivata masks.
44  *
45  * Revision 1.2 2004/11/03 16:03:47 colinmacleod
46  * Added checking for null arguments.
47  * Now throws validation exception on errors.
48  *
49  * Revision 1.1 2004/09/30 15:15:57 colinmacleod
50  * Split off addressbook elements into security subproject.
51  *
52  * Revision 1.1 2004/07/13 19:12:33 colinmacleod
53  * New classes as part of conversion to PicoContainer.
54  * -----------------------------------------------------------------------------
55  */

56 package com.ivata.groupware.admin.script;
57
58 import java.io.BufferedReader JavaDoc;
59 import java.io.File JavaDoc;
60 import java.io.IOException JavaDoc;
61 import java.io.InputStream JavaDoc;
62 import java.io.InputStreamReader JavaDoc;
63 import java.util.Arrays JavaDoc;
64 import java.util.Iterator JavaDoc;
65 import java.util.List JavaDoc;
66 import java.util.Vector JavaDoc;
67
68 import org.apache.log4j.Logger;
69
70 import com.ivata.groupware.admin.security.server.SecurityServerException;
71 import com.ivata.mask.util.CollectionHandling;
72 import com.ivata.mask.util.SystemException;
73 import com.ivata.mask.validation.ValidationError;
74 import com.ivata.mask.validation.ValidationErrors;
75 import com.ivata.mask.validation.ValidationException;
76 import com.ivata.mask.web.format.URLFormat;
77
78 /**
79  * Simple class to let you run scripts which exist outside the JVM world.
80  *
81  * @author Colin MacLeod
82  * <a HREF='mailto:colin.macleod@ivata.com'>colin.macleod@ivata.com</a>
83  * @since Apr 6, 2004
84  * @version $Revision: 1.2 $
85  */

86 public class ExternalScriptExecutor implements ScriptExecutor {
87
88     /**
89      * Refer to {@link Logger}.
90      */

91     private static Logger log = Logger.getLogger(ExternalScriptExecutor.class);
92     /**
93      * <p>
94      * All environment variables to be set in the script environment.
95      * </p>
96      */

97     String JavaDoc [] environmentVariables;
98     /**
99      * <p>
100      * Full path to the location where the scripts are stored for this executor.
101      * </p>
102      */

103     private String JavaDoc scriptPath;
104     /**
105      * <p>
106      * This is used to format variables to avoid problems with command line
107      * spaces.
108      * </p>
109      */

110     URLFormat uRLFormat;
111     /**
112      * <p>
113      * Construct a script executor to execute external scripts.
114      * </p>
115      *
116      * @param scriptPath full path to the location where the scripts are stored
117      * for this executor.
118      * @param environmentVariables all environment variables to be set in the
119      * script environemnt, separated by line feeds.
120      * @param uRLFormat used to format variables to avoid problems with command
121      * line spaces.
122      */

123     public ExternalScriptExecutor(URLFormat URLFormat, String JavaDoc scriptPath,
124             String JavaDoc environmentVariables) {
125         this.scriptPath = scriptPath;
126         this.environmentVariables = (String JavaDoc[])
127             CollectionHandling.convertFromLines(environmentVariables).toArray(new String JavaDoc[]{});
128         this.uRLFormat = URLFormat;
129     }
130     /**
131      * <p>Execute a command and handle any error that occurs.</p>
132      *
133      * @param scriptName name of the script to be executed.
134      * @param argv command name and all arguments of to be executed. The first
135      * argument should always be the script name
136      * @throws SecurityServerException if the command returns non-zero, or if
137      * there is
138      * an input/output exception.
139      * @return all lines of the program output as a <code>String</code>.
140      */

141     public String JavaDoc exec(final String JavaDoc scriptName,
142             final String JavaDoc[] arguments) throws SystemException {
143         String JavaDoc [] externalArguments = new String JavaDoc[arguments.length + 1];
144
145         try {
146             externalArguments[0] = scriptPath
147                 + File.separator
148                 + scriptName;
149
150             // put quotes round each of the arguments
151
// TODO: this will probably not work in an Windows environment -
152
// possible solutions are replacing spaces somehow here and
153
// (better) providing perl/other script wrappers to parse arguments
154
for (int index = 0; index < arguments.length; ++index) {
155                 if ((arguments[index] == null)
156                         || (arguments[index].length() == 0)) {
157                     externalArguments[index + 1] = "%00";
158                 } else {
159                     externalArguments[index + 1] = uRLFormat.format(arguments[index]);
160                 }
161             }
162
163             Process JavaDoc process;
164             try {
165                 process = Runtime.getRuntime().exec(externalArguments,
166                         environmentVariables, new File JavaDoc(scriptPath));
167             } catch (IOException JavaDoc e) {
168                 log.error(e);
169                 String JavaDoc argumentsString = CollectionHandling.convertToLines(
170                         Arrays.asList(arguments), ',');
171                 throw new ValidationException(new ValidationError(
172                         "errors.admin.script",
173                         Arrays.asList(new Object JavaDoc[] {
174                                 scriptName,
175                                 argumentsString,
176                                 "IOException: "
177                                     + e.getMessage()
178                         })));
179             }
180
181             if (process.waitFor() != 0) {
182                 String JavaDoc errorText = extractText(process.getErrorStream());
183                 List JavaDoc lines = CollectionHandling.convertFromLines(errorText);
184                 ValidationErrors errors = new ValidationErrors();
185                 Iterator JavaDoc linesIterator = lines.iterator();
186                 while (linesIterator.hasNext()) {
187                     String JavaDoc line = (String JavaDoc) linesIterator.next();
188                     // if it timed out waiting for a password, that is almost
189
// definitely a sudo issue - add a comment to help whoever
190
// installed ivata groupware.
191
if ((lines.size() == 1)
192                             && "Password:".equals(line)) {
193                         line += " (This looks like a user rights issue. Check "
194                             + "visudo is installed properly and is set up for "
195                             + "the user who is running the program. If you "
196                             + "used the install script to install ivata "
197                             + "groupware, change the value of USER_APP_SERVER "
198                             + "at the start of the script and run "
199                             + "setup.pl again.)";
200                     }
201                     // some scripts have been tuned to give out error message
202
// keys when they fail - see if this is one of those
203
if ((line.indexOf("error.") != -1)
204                                 || (line.indexOf("errors.") != -1)) {
205                             List JavaDoc errorArguments = new Vector JavaDoc();
206                         errorArguments.add(scriptName);
207                         errorArguments.addAll(Arrays.asList(arguments));
208                         errors.add(new ValidationError(
209                                 line,
210                                 errorArguments));
211                     } else {
212                         // nothing for it - we'll just have to use a generic
213
// 'script failed' error message
214
String JavaDoc argumentsString = CollectionHandling.convertToLines(
215                                 Arrays.asList(arguments), ',');
216                         errors.add(new ValidationError(
217                                 "errors.admin.script",
218                                 Arrays.asList(new Object JavaDoc[] {
219                                         scriptName,
220                                         argumentsString,
221                                         line
222                                 })));
223                     }
224                 }
225                 throw new ValidationException(errors);
226             }
227
228             return extractText(process.getInputStream());
229         } catch (IOException JavaDoc e) {
230             throw new SystemException("There was an input/output exception:",
231                 e);
232         } catch (InterruptedException JavaDoc e) {
233             throw new SystemException("The script process was interrupted",
234                 e);
235         }
236     }
237
238     /**
239      * <p>Called internally to evaluate the text from the stream
240      * provided.</p>
241      *
242      * @param stream stream containing text to extract.
243      * @throws IOException thrown by <code>BufferedReader</code>.
244      * @return the textual contents of the stream provided.
245      */

246     private String JavaDoc extractText(final InputStream JavaDoc stream) throws IOException JavaDoc {
247         BufferedReader JavaDoc in = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(stream));
248         StringBuffer JavaDoc messageBuffer = new StringBuffer JavaDoc();
249         char[] chbuf = new char[1024];
250         int count;
251
252         while ((count = in.read(chbuf)) != -1) {
253             messageBuffer.append(chbuf, 0, count);
254         }
255
256         return messageBuffer.toString();
257     }
258 }
259
Popular Tags