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 }