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