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