1 package org.codehaus.plexus.util.cli.shell;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import org.codehaus.plexus.util.StringUtils;
20
21 import java.io.File;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.List;
25
26
27
28
29
30
31
32
33
34
35
36
37 public class Shell
38 implements Cloneable
39 {
40 private static final char[] DEFAULT_QUOTING_TRIGGER_CHARS = { ' ' };
41
42 private String shellCommand;
43
44 private List<String> shellArgs = new ArrayList<String>();
45
46 private boolean quotedArgumentsEnabled = true;
47
48 private boolean unconditionallyQuote = false;
49
50 private String executable;
51
52 private String workingDir;
53
54 private boolean quotedExecutableEnabled = true;
55
56 private boolean doubleQuotedArgumentEscaped = false;
57
58 private boolean singleQuotedArgumentEscaped = false;
59
60 private boolean doubleQuotedExecutableEscaped = false;
61
62 private boolean singleQuotedExecutableEscaped = false;
63
64 private char argQuoteDelimiter = '\"';
65
66 private char exeQuoteDelimiter = '\"';
67
68 private String argumentEscapePattern = "\\%s";
69
70
71
72
73
74
75 public void setUnconditionalQuoting( boolean unconditionallyQuote )
76 {
77 this.unconditionallyQuote = unconditionallyQuote;
78 }
79
80
81
82
83
84
85 public void setShellCommand( String shellCommand )
86 {
87 this.shellCommand = shellCommand;
88 }
89
90
91
92
93
94
95 public String getShellCommand()
96 {
97 return shellCommand;
98 }
99
100
101
102
103
104
105 public void setShellArgs( String[] shellArgs )
106 {
107 this.shellArgs.clear();
108 this.shellArgs.addAll( Arrays.asList( shellArgs ) );
109 }
110
111
112
113
114 public String[] getShellArgs()
115 {
116 if ( ( shellArgs == null ) || shellArgs.isEmpty() )
117 {
118 return null;
119 }
120 else
121 {
122 return shellArgs.toArray( new String[0] );
123 }
124 }
125
126
127
128
129
130
131
132
133 public List<String> getCommandLine( String executable, String[] arguments )
134 {
135 return getRawCommandLine( executable, arguments );
136 }
137
138 protected String quoteOneItem( String inputString, boolean isExecutable )
139 {
140 char[] escapeChars = getEscapeChars( isSingleQuotedExecutableEscaped(), isDoubleQuotedExecutableEscaped() );
141 return StringUtils.quoteAndEscape( inputString,
142 isExecutable ? getExecutableQuoteDelimiter() : getArgumentQuoteDelimiter(),
143 escapeChars, getQuotingTriggerChars(), '\\', unconditionallyQuote );
144 }
145
146 protected List<String> getRawCommandLine( String executable, String[] arguments )
147 {
148 List<String> commandLine = new ArrayList<String>();
149 StringBuilder sb = new StringBuilder();
150
151 if ( executable != null )
152 {
153 String preamble = getExecutionPreamble();
154 if ( preamble != null )
155 {
156 sb.append( preamble );
157 }
158
159 if ( isQuotedExecutableEnabled() )
160 {
161 sb.append( quoteOneItem( getOriginalExecutable(), true ) );
162 }
163 else
164 {
165 sb.append( getExecutable() );
166 }
167 }
168 for ( String argument : arguments )
169 {
170 if ( sb.length() > 0 )
171 {
172 sb.append( " " );
173 }
174
175 if ( isQuotedArgumentsEnabled() )
176 {
177 sb.append( quoteOneItem( argument, false ) );
178 }
179 else
180 {
181 sb.append( argument );
182 }
183 }
184
185 commandLine.add( sb.toString() );
186
187 return commandLine;
188 }
189
190 protected char[] getQuotingTriggerChars()
191 {
192 return DEFAULT_QUOTING_TRIGGER_CHARS;
193 }
194
195 protected String getExecutionPreamble()
196 {
197 return null;
198 }
199
200 protected char[] getEscapeChars( boolean includeSingleQuote, boolean includeDoubleQuote )
201 {
202 StringBuilder buf = new StringBuilder( 2 );
203 if ( includeSingleQuote )
204 {
205 buf.append( '\'' );
206 }
207
208 if ( includeDoubleQuote )
209 {
210 buf.append( '\"' );
211 }
212
213 char[] result = new char[buf.length()];
214 buf.getChars( 0, buf.length(), result, 0 );
215
216 return result;
217 }
218
219 protected boolean isDoubleQuotedArgumentEscaped()
220 {
221 return doubleQuotedArgumentEscaped;
222 }
223
224 protected boolean isSingleQuotedArgumentEscaped()
225 {
226 return singleQuotedArgumentEscaped;
227 }
228
229 protected boolean isDoubleQuotedExecutableEscaped()
230 {
231 return doubleQuotedExecutableEscaped;
232 }
233
234 protected boolean isSingleQuotedExecutableEscaped()
235 {
236 return singleQuotedExecutableEscaped;
237 }
238
239 protected void setArgumentQuoteDelimiter( char argQuoteDelimiter )
240 {
241 this.argQuoteDelimiter = argQuoteDelimiter;
242 }
243
244 protected char getArgumentQuoteDelimiter()
245 {
246 return argQuoteDelimiter;
247 }
248
249 protected void setExecutableQuoteDelimiter( char exeQuoteDelimiter )
250 {
251 this.exeQuoteDelimiter = exeQuoteDelimiter;
252 }
253
254 protected char getExecutableQuoteDelimiter()
255 {
256 return exeQuoteDelimiter;
257 }
258
259 protected void setArgumentEscapePattern( String argumentEscapePattern )
260 {
261 this.argumentEscapePattern = argumentEscapePattern;
262 }
263
264 protected String getArgumentEscapePattern()
265 {
266 return argumentEscapePattern;
267 }
268
269
270
271
272
273
274
275
276
277 public List<String> getShellCommandLine( String[] arguments )
278 {
279
280 List<String> commandLine = new ArrayList<String>();
281
282 if ( getShellCommand() != null )
283 {
284 commandLine.add( getShellCommand() );
285 }
286
287 if ( getShellArgs() != null )
288 {
289 commandLine.addAll( getShellArgsList() );
290 }
291
292 commandLine.addAll( getCommandLine( getOriginalExecutable(), arguments ) );
293
294 return commandLine;
295
296 }
297
298 public List<String> getShellArgsList()
299 {
300 return shellArgs;
301 }
302
303 public void addShellArg( String arg )
304 {
305 shellArgs.add( arg );
306 }
307
308 public void setQuotedArgumentsEnabled( boolean quotedArgumentsEnabled )
309 {
310 this.quotedArgumentsEnabled = quotedArgumentsEnabled;
311 }
312
313 public boolean isQuotedArgumentsEnabled()
314 {
315 return quotedArgumentsEnabled;
316 }
317
318 public void setQuotedExecutableEnabled( boolean quotedExecutableEnabled )
319 {
320 this.quotedExecutableEnabled = quotedExecutableEnabled;
321 }
322
323 public boolean isQuotedExecutableEnabled()
324 {
325 return quotedExecutableEnabled;
326 }
327
328
329
330
331
332 public void setExecutable( String executable )
333 {
334 if ( ( executable == null ) || ( executable.length() == 0 ) )
335 {
336 return;
337 }
338 this.executable = executable.replace( '/', File.separatorChar ).replace( '\\', File.separatorChar );
339 }
340
341 public String getExecutable()
342 {
343 return executable;
344 }
345
346
347
348
349 public void setWorkingDirectory( String path )
350 {
351 if ( path != null )
352 {
353 workingDir = path;
354 }
355 }
356
357
358
359
360 public void setWorkingDirectory( File workingDir )
361 {
362 if ( workingDir != null )
363 {
364 this.workingDir = workingDir.getAbsolutePath();
365 }
366 }
367
368 public File getWorkingDirectory()
369 {
370 return workingDir == null ? null : new File( workingDir );
371 }
372
373 public String getWorkingDirectoryAsString()
374 {
375 return workingDir;
376 }
377
378 public void clearArguments()
379 {
380 shellArgs.clear();
381 }
382
383 @Override
384 public Object clone()
385 {
386 Shell shell = new Shell();
387 shell.setExecutable( getExecutable() );
388 shell.setWorkingDirectory( getWorkingDirectory() );
389 shell.setShellArgs( getShellArgs() );
390 return shell;
391 }
392
393 public String getOriginalExecutable()
394 {
395 return executable;
396 }
397
398 public List<String> getOriginalCommandLine( String executable, String[] arguments )
399 {
400 return getRawCommandLine( executable, arguments );
401 }
402
403 protected void setDoubleQuotedArgumentEscaped( boolean doubleQuotedArgumentEscaped )
404 {
405 this.doubleQuotedArgumentEscaped = doubleQuotedArgumentEscaped;
406 }
407
408 protected void setDoubleQuotedExecutableEscaped( boolean doubleQuotedExecutableEscaped )
409 {
410 this.doubleQuotedExecutableEscaped = doubleQuotedExecutableEscaped;
411 }
412
413 protected void setSingleQuotedArgumentEscaped( boolean singleQuotedArgumentEscaped )
414 {
415 this.singleQuotedArgumentEscaped = singleQuotedArgumentEscaped;
416 }
417
418 protected void setSingleQuotedExecutableEscaped( boolean singleQuotedExecutableEscaped )
419 {
420 this.singleQuotedExecutableEscaped = singleQuotedExecutableEscaped;
421 }
422 }