1 package org.apache.maven.it.util.cli;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81 import org.apache.maven.it.util.cli.shell.CommandShell;
82 import org.apache.maven.it.util.cli.shell.CmdShell;
83 import org.apache.maven.it.util.cli.shell.Shell;
84
85 import java.io.File;
86 import java.io.IOException;
87 import java.util.ArrayList;
88 import java.util.Arrays;
89 import java.util.Iterator;
90 import java.util.List;
91 import java.util.Properties;
92 import java.util.StringTokenizer;
93 import java.util.Vector;
94 import java.util.Hashtable;
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124 public class Commandline
125 implements Cloneable
126 {
127 protected static final String OS_NAME = "os.name";
128
129 protected static final String WINDOWS = "Windows";
130
131 protected String executable = null;
132
133 protected Vector arguments = new Vector();
134
135 protected Hashtable envVars = new Hashtable();
136
137 private File workingDir = null;
138
139 private long pid = -1;
140
141 private Shell shell;
142
143
144
145
146
147
148
149 public Commandline( String toProcess )
150 {
151 super();
152 setDefaultShell();
153 String[] tmp = new String[0];
154 try
155 {
156 tmp = translateCommandline( toProcess );
157 }
158 catch ( Exception e )
159 {
160 System.err.println( "Error translating Commandline." );
161 }
162 if ( tmp != null && tmp.length > 0 )
163 {
164 setExecutable( tmp[0] );
165 for ( int i = 1; i < tmp.length; i++ )
166 {
167 createArgument().setValue( tmp[i] );
168 }
169 }
170 }
171
172
173
174
175
176 public Commandline()
177 {
178 super();
179 setDefaultShell();
180 }
181
182 public long getPid()
183 {
184 if ( pid == -1 )
185 {
186 pid = Long.parseLong( String.valueOf( System.currentTimeMillis() ) );
187 }
188
189 return pid;
190 }
191
192 public void setPid( long pid )
193 {
194 this.pid = pid;
195 }
196
197
198
199
200 public static class Argument
201 {
202
203 private String[] parts;
204
205
206
207
208
209
210 public void setValue( String value )
211 {
212 if ( value != null )
213 {
214 parts = new String[]{value};
215 }
216 }
217
218
219
220
221
222
223 public void setLine( String line )
224 {
225 if ( line == null )
226 {
227 return;
228 }
229 try
230 {
231 parts = translateCommandline( line );
232 }
233 catch ( Exception e )
234 {
235 System.err.println( "Error translating Commandline." );
236 }
237 }
238
239
240
241
242
243
244
245 public void setFile( File value )
246 {
247 parts = new String[]{value.getAbsolutePath()};
248 }
249
250
251
252
253 public String[] getParts()
254 {
255 return parts;
256 }
257 }
258
259
260
261
262
263
264
265 public class Marker
266 {
267
268 private int position;
269
270 private int realPos = -1;
271
272 Marker( int position )
273 {
274 this.position = position;
275 }
276
277
278
279
280
281
282
283 public int getPosition()
284 {
285 if ( realPos == -1 )
286 {
287 realPos = ( executable == null ? 0 : 1 );
288 for ( int i = 0; i < position; i++ )
289 {
290 Argument arg = (Argument) arguments.elementAt( i );
291 realPos += arg.getParts().length;
292 }
293 }
294 return realPos;
295 }
296 }
297
298
299
300
301
302
303 private void setDefaultShell()
304 {
305 String os = System.getProperty( OS_NAME );
306
307
308 if ( os.indexOf( WINDOWS ) > -1 )
309 {
310 if ( os.indexOf( "95" ) > -1 || os.indexOf( "98" ) > -1 || os.indexOf( "Me" ) > -1 )
311 {
312 setShell( new CommandShell() );
313 }
314 else
315 {
316 setShell( new CmdShell() );
317 }
318 }
319 }
320
321
322
323
324
325
326
327
328
329
330
331 public Argument createArgument()
332 {
333 return this.createArgument( false );
334 }
335
336
337
338
339
340
341
342
343
344
345 public Argument createArgument( boolean insertAtStart )
346 {
347 Argument argument = new Argument();
348 if ( insertAtStart )
349 {
350 arguments.insertElementAt( argument, 0 );
351 }
352 else
353 {
354 arguments.addElement( argument );
355 }
356 return argument;
357 }
358
359
360
361
362 public void setExecutable( String executable )
363 {
364 if ( executable == null || executable.length() == 0 )
365 {
366 return;
367 }
368 this.executable = executable.replace( '/', File.separatorChar ).replace( '\\', File.separatorChar );
369 }
370
371 public String getExecutable()
372 {
373 return executable;
374 }
375
376 public void addArguments( String[] line )
377 {
378 for ( int i = 0; i < line.length; i++ )
379 {
380 createArgument().setValue( line[i] );
381 }
382 }
383
384
385
386
387 public void addEnvironment( String name,
388 String value )
389 {
390 envVars.put( name, name + "=" + value );
391 }
392
393
394
395
396 public void addSystemEnvironment()
397 throws Exception
398 {
399 Properties envVars = CommandLineUtils.getSystemEnvVars();
400
401 for ( Iterator i = envVars.keySet().iterator(); i.hasNext(); )
402 {
403 String key = (String) i.next();
404
405 if ( !this.envVars.containsKey( key ) )
406 {
407 this.envVars.put( key, key + "=" + envVars.getProperty( key ) );
408 }
409 }
410 }
411
412
413
414
415 public String[] getEnvironmentVariables()
416 throws CommandLineException
417 {
418 try
419 {
420 addSystemEnvironment();
421 }
422 catch ( Exception e )
423 {
424 throw new CommandLineException( "Error setting up environmental variables", e );
425 }
426
427 return (String[]) envVars.values().toArray( new String[envVars.size()] );
428 }
429
430
431
432
433 public String[] getCommandline()
434 {
435 final String[] args = getArguments();
436 if ( executable == null )
437 {
438 return args;
439 }
440 final String[] result = new String[args.length + 1];
441 result[0] = executable;
442 System.arraycopy( args, 0, result, 1, args.length );
443 return result;
444 }
445
446
447
448
449 public String[] getShellCommandline()
450 {
451
452 if ( getShell() == null )
453 {
454 if ( executable != null )
455 {
456 List commandLine = new ArrayList();
457 commandLine.add( executable );
458 commandLine.addAll( Arrays.asList( getArguments() ) );
459 return (String[]) commandLine.toArray( new String[0] );
460 }
461 else
462 {
463 return getArguments();
464 }
465
466 }
467 else
468 {
469 return (String[]) getShell().getShellCommandLine( executable, getArguments() ).toArray( new String[0] );
470 }
471 }
472
473
474
475
476
477 public String[] getArguments()
478 {
479 Vector result = new Vector( arguments.size() * 2 );
480 for ( int i = 0; i < arguments.size(); i++ )
481 {
482 Argument arg = (Argument) arguments.elementAt( i );
483 String[] s = arg.getParts();
484 if ( s != null )
485 {
486 for ( int j = 0; j < s.length; j++ )
487 {
488 result.addElement( s[j] );
489 }
490 }
491 }
492
493 String[] res = new String[result.size()];
494 result.copyInto( res );
495 return res;
496 }
497
498 public String toString()
499 {
500 return toString( getCommandline() );
501 }
502
503
504
505
506
507
508
509
510
511
512 public static String quoteArgument( String argument )
513 throws CommandLineException
514 {
515 if ( argument.indexOf( '\"' ) > -1 )
516 {
517 if ( argument.indexOf( '\'' ) > -1 )
518 {
519 throw new CommandLineException( "Can't handle single and double quotes in same argument" );
520 }
521 else
522 {
523 return '\'' + argument + '\'';
524 }
525 }
526 else if ( containsAny( argument, "'<>&|*? " ) )
527 {
528 return '\"' + argument + '\"';
529 }
530 else
531 {
532 return argument;
533 }
534 }
535
536 private static boolean containsAny( String argument, String chars )
537 {
538 for ( int i = chars.length() - 1; i >= 0; i-- )
539 {
540 if ( argument.indexOf( chars.charAt( i ) ) >= 0 )
541 {
542 return true;
543 }
544 }
545 return false;
546 }
547
548 public static String toString( String[] line )
549 {
550
551 if ( line == null || line.length == 0 )
552 {
553 return "";
554 }
555
556
557 final StringBuffer result = new StringBuffer();
558 for ( int i = 0; i < line.length; i++ )
559 {
560 if ( i > 0 )
561 {
562 result.append( ' ' );
563 }
564 try
565 {
566 result.append( quoteArgument( line[i] ) );
567 }
568 catch ( Exception e )
569 {
570 System.err.println( "Error quoting argument." );
571 }
572 }
573 return result.toString();
574 }
575
576 public static String[] translateCommandline( String toProcess )
577 throws Exception
578 {
579 if ( toProcess == null || toProcess.length() == 0 )
580 {
581 return new String[0];
582 }
583
584
585
586 final int normal = 0;
587 final int inQuote = 1;
588 final int inDoubleQuote = 2;
589 int state = normal;
590 StringTokenizer tok = new StringTokenizer( toProcess, "\"\' ", true );
591 Vector v = new Vector();
592 StringBuffer current = new StringBuffer();
593
594 while ( tok.hasMoreTokens() )
595 {
596 String nextTok = tok.nextToken();
597 switch ( state )
598 {
599 case inQuote:
600 if ( "\'".equals( nextTok ) )
601 {
602 state = normal;
603 }
604 else
605 {
606 current.append( nextTok );
607 }
608 break;
609 case inDoubleQuote:
610 if ( "\"".equals( nextTok ) )
611 {
612 state = normal;
613 }
614 else
615 {
616 current.append( nextTok );
617 }
618 break;
619 default:
620 if ( "\'".equals( nextTok ) )
621 {
622 state = inQuote;
623 }
624 else if ( "\"".equals( nextTok ) )
625 {
626 state = inDoubleQuote;
627 }
628 else if ( " ".equals( nextTok ) )
629 {
630 if ( current.length() != 0 )
631 {
632 v.addElement( current.toString() );
633 current.setLength( 0 );
634 }
635 }
636 else
637 {
638 current.append( nextTok );
639 }
640 break;
641 }
642 }
643
644 if ( current.length() != 0 )
645 {
646 v.addElement( current.toString() );
647 }
648
649 if ( state == inQuote || state == inDoubleQuote )
650 {
651 throw new CommandLineException( "unbalanced quotes in " + toProcess );
652 }
653
654 String[] args = new String[v.size()];
655 v.copyInto( args );
656 return args;
657 }
658
659 public int size()
660 {
661 return getCommandline().length;
662 }
663
664 public Object clone()
665 {
666 Commandline c = new Commandline();
667 c.setExecutable( executable );
668 c.addArguments( getArguments() );
669 return c;
670 }
671
672
673
674
675 public void clear()
676 {
677 executable = null;
678 arguments.removeAllElements();
679 }
680
681
682
683
684 public void clearArgs()
685 {
686 arguments.removeAllElements();
687 }
688
689
690
691
692
693
694
695
696 public Marker createMarker()
697 {
698 return new Marker( arguments.size() );
699 }
700
701
702
703
704 public void setWorkingDirectory( String path )
705 {
706 if ( path != null )
707 {
708 workingDir = new File( path );
709 }
710 }
711
712 public File getWorkingDirectory()
713 {
714 return workingDir;
715 }
716
717
718
719
720 public Process execute()
721 throws CommandLineException
722 {
723 Process process;
724
725
726
727 String[] environment = getEnvironmentVariables();
728
729 try
730 {
731 if ( workingDir == null )
732 {
733 process = Runtime.getRuntime().exec( getShellCommandline(), environment );
734 }
735 else
736 {
737 if ( !workingDir.exists() )
738 {
739 throw new CommandLineException(
740 "Working directory \"" + workingDir.getPath() + "\" does not exist!" );
741 }
742 else if ( !workingDir.isDirectory() )
743 {
744 throw new CommandLineException(
745 "Path \"" + workingDir.getPath() + "\" does not specify a directory." );
746 }
747
748 process = Runtime.getRuntime().exec( getShellCommandline(), environment, workingDir );
749 }
750 }
751 catch ( IOException ex )
752 {
753 throw new CommandLineException( "Error while executing process.", ex );
754 }
755
756 return process;
757 }
758
759 public Properties getSystemEnvVars()
760 throws Exception
761 {
762 return CommandLineUtils.getSystemEnvVars();
763 }
764
765
766
767
768
769
770
771 public void setShell( Shell shell )
772 {
773 this.shell = shell;
774 }
775
776
777
778
779
780
781 public Shell getShell()
782 {
783 return shell;
784 }
785 }