1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.simpligility.maven.plugins.androidndk;
18
19 import java.io.File;
20 import java.util.ArrayList;
21 import java.util.HashMap;
22 import java.util.List;
23 import java.util.Map;
24
25 import org.apache.maven.plugin.logging.Log;
26 import org.codehaus.plexus.util.cli.CommandLineException;
27 import org.codehaus.plexus.util.cli.CommandLineUtils;
28 import org.codehaus.plexus.util.cli.Commandline;
29 import org.codehaus.plexus.util.cli.StreamConsumer;
30 import org.codehaus.plexus.util.cli.shell.Shell;
31
32
33
34
35 public interface CommandExecutor
36 {
37
38
39
40
41
42
43 void setLogger( Log logger );
44
45
46
47
48
49
50
51
52
53
54
55
56 void executeCommand( String executable, List< String > commands ) throws ExecutionException;
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 void executeCommand( String executable, List< String > commands, boolean failsOnErrorOutput )
73 throws ExecutionException;
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90 void executeCommand( String executable, List< String > commands, File workingDirectory, boolean failsOnErrorOutput )
91 throws ExecutionException;
92
93
94
95
96
97
98
99 int getResult();
100
101
102
103
104 long getPid();
105
106
107
108
109
110
111 String getStandardOut();
112
113
114
115
116
117
118 String getStandardError();
119
120
121
122
123 void addEnvironment( String name, String value );
124
125 void setErrorListener( ErrorListener errorListener );
126
127 void setCustomShell( Shell s );
128
129 void setCaptureStdOut( boolean captureStdOut );
130 void setCaptureStdErr( boolean captureStdErr );
131
132
133
134
135 public interface ErrorListener
136 {
137 boolean isError( String error );
138 }
139
140
141
142
143 class Factory
144 {
145
146
147
148
149 private Factory()
150 {
151 }
152
153 private static final class DefaultCommandExecutor implements CommandExecutor
154 {
155 private Map< String, String > environment;
156
157
158
159 private Log logger;
160
161
162
163 private StreamConsumer stdOut;
164
165
166
167 private ErrorStreamConsumer stdErr;
168
169
170
171 private int result;
172
173
174 private ErrorListener errorListener;
175 long pid;
176 private Commandline commandline;
177 private Shell customShell;
178
179 private boolean captureStdOut;
180 private boolean captureStdErr;
181
182 @Override
183 public void setLogger( Log logger )
184 {
185 this.logger = logger;
186 }
187
188 @Override
189 public void executeCommand( String executable, List< String > commands ) throws ExecutionException
190 {
191 executeCommand( executable, commands, null, true );
192 }
193
194 @Override
195 public void executeCommand( String executable, List< String > commands, boolean failsOnErrorOutput )
196 throws ExecutionException
197 {
198 executeCommand( executable, commands, null, failsOnErrorOutput );
199 }
200
201 @Override
202 public void executeCommand( String executable, List< String > commands, File workingDirectory,
203 boolean failsOnErrorOutput ) throws ExecutionException
204 {
205 if ( commands == null )
206 {
207 commands = new ArrayList< String >();
208 }
209 stdOut = new StreamConsumerImpl( logger, captureStdOut );
210 stdErr = new ErrorStreamConsumer( logger, errorListener, captureStdErr );
211 commandline = new Commandline();
212 if ( customShell != null )
213 {
214 commandline.setShell( customShell );
215 }
216 commandline.setExecutable( executable );
217
218
219 if ( environment != null )
220 {
221 for ( Map.Entry< String, String > entry : environment.entrySet() )
222 {
223 commandline.addEnvironment( entry.getKey(), entry.getValue() );
224 }
225 }
226
227 commandline.addArguments( commands.toArray( new String[ commands.size() ] ) );
228 if ( workingDirectory != null && workingDirectory.exists() )
229 {
230 commandline.setWorkingDirectory( workingDirectory.getAbsolutePath() );
231 }
232 try
233 {
234 logger.debug( "ANDROID-040-000: Executing command: Commandline = " + commandline );
235 result = CommandLineUtils.executeCommandLine( commandline, stdOut, stdErr );
236 if ( logger != null )
237 {
238 logger.debug( "ANDROID-040-000: Executed command: Commandline = " + commandline + ", Result = "
239 + result );
240 }
241 else
242 {
243 System.out.println( "ANDROID-040-000: Executed command: Commandline = " + commandline
244 + ", Result = " + result );
245 }
246 if ( failsOnErrorOutput && stdErr.hasError() || result != 0 )
247 {
248 throw new ExecutionException( "ANDROID-040-001: Could not execute: Command = "
249 + commandline.toString() + ", Result = " + result );
250 }
251 }
252 catch ( CommandLineException e )
253 {
254 throw new ExecutionException( "ANDROID-040-002: Could not execute: Command = "
255 + commandline.toString() + ", Error message = " + e.getMessage() );
256 }
257 setPid( commandline.getPid() );
258 }
259
260 @Override
261 public int getResult()
262 {
263 return result;
264 }
265
266 @Override
267 public String getStandardOut()
268 {
269 if ( ! captureStdOut )
270 {
271 throw new IllegalStateException( "Unable to provide StdOut since it was not captured" );
272 }
273 return stdOut.toString();
274 }
275
276 @Override
277 public String getStandardError()
278 {
279 if ( ! captureStdErr )
280 {
281 throw new IllegalStateException( "Unable to provide StdOut since it was not captured" );
282 }
283 return stdErr.toString();
284 }
285
286 @Override
287 public void addEnvironment( String name, String value )
288 {
289 if ( environment == null )
290 {
291 environment = new HashMap< String, String >();
292 }
293 environment.put( name, value );
294 }
295
296 @Override
297 public void setErrorListener( ErrorListener errorListener )
298 {
299 this.errorListener = errorListener;
300 }
301
302 public void setPid( long pid )
303 {
304 this.pid = pid;
305 }
306
307 @Override
308 public long getPid()
309 {
310 return pid;
311 }
312
313 @Override
314 public void setCustomShell( Shell shell )
315 {
316 this.customShell = shell;
317 }
318
319 @Override
320 public void setCaptureStdOut( boolean captureStdOut )
321 {
322 this.captureStdOut = captureStdOut;
323 }
324
325 @Override
326 public void setCaptureStdErr( boolean captureStdErr )
327 {
328 this.captureStdErr = captureStdErr;
329 }
330 }
331
332
333
334
335 static class StreamConsumerImpl implements StreamConsumer
336 {
337 private StringBuffer sb = new StringBuffer();
338 private final Log logger;
339 private boolean captureStdOut;
340
341 StreamConsumerImpl( Log logger, boolean captureStdOut )
342 {
343 this.logger = logger;
344 this.captureStdOut = captureStdOut;
345 }
346
347 @Override
348 public void consumeLine( String line )
349 {
350 if ( captureStdOut )
351 {
352 sb.append( line );
353 }
354 if ( logger != null )
355 {
356 logger.debug( line );
357 }
358 }
359
360
361
362
363
364
365 @Override
366 public String toString()
367 {
368 return sb.toString();
369 }
370 }
371
372
373
374
375
376
377 static class ErrorStreamConsumer implements StreamConsumer
378 {
379
380 private boolean error;
381
382 private StringBuffer sbe = new StringBuffer();
383 private final Log logger;
384 private final ErrorListener errorListener;
385 private boolean captureStdErr;
386
387 ErrorStreamConsumer( Log logger, ErrorListener errorListener, boolean captureStdErr )
388 {
389 this.logger = logger;
390 this.errorListener = errorListener;
391 this.captureStdErr = captureStdErr;
392
393 if ( logger == null )
394 {
395 System.out.println( "ANDROID-040-003: Error Log not set: Will not output error logs" );
396 }
397 error = false;
398 }
399
400 @Override
401 public void consumeLine( String line )
402 {
403 if ( captureStdErr )
404 {
405 sbe.append( line );
406 }
407 if ( logger != null )
408 {
409 logger.info( line );
410 }
411 if ( errorListener != null )
412 {
413 error = errorListener.isError( line );
414 }
415 else
416 {
417 error = true;
418 }
419 }
420
421
422
423
424
425
426 public boolean hasError()
427 {
428 return error;
429 }
430
431
432
433
434
435
436 @Override
437 public String toString()
438 {
439 return sbe.toString();
440 }
441 }
442
443
444
445
446
447
448 public static CommandExecutor createDefaultCommmandExecutor()
449 {
450 return new DefaultCommandExecutor();
451
452 }
453 }
454 }