File D:\maven-qcr-plugin-testsunitaires\qcr4java\jenkins-master\target\site\qc\core\src\main\java\hudson\util\QuotedStringTokenizer.java.html

1 /**
2 * (C) Copyright 2004-2005 Mort Bay Consulting Pty. Ltd.
3 *
4 * Parts of this code was taken from the Jetty project, which can be
5 * found at http://www.mortbay.org/jetty
6 *
7 * Licensed to the Apache Software Foundation (ASF) under one or more
8 * contributor license agreements. See the NOTICE file distributed with
9 * this work for additional information regarding copyright ownership.
10 * The ASF licenses this file to You under the Apache License, Version 2.0
11 * (the "License"); you may not use this file except in compliance with
12 * the License. You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 */
22
23 // ========================================================================
24 // Copyright 2004-2005 Mort Bay Consulting Pty. Ltd.
25 // ------------------------------------------------------------------------
26 // Licensed under the Apache License, Version 2.0 (the "License");
27 // you may not use this file except in compliance with the License.
28 // You may obtain a copy of the License at
29 // http://www.apache.org/licenses/LICENSE-2.0
30 // Unless required by applicable law or agreed to in writing, software
31 // distributed under the License is distributed on an "AS IS" BASIS,
32 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
33 // See the License for the specific language governing permissions and
34 // limitations under the License.
35 // ========================================================================
36 package hudson.util;
37
38 import java.util.NoSuchElementException;
39 import java.util.StringTokenizer;
40 import java.util.List;
41 import java.util.ArrayList;
42
43 /* ------------------------------------------------------------ */
44 /** StringTokenizer with Quoting support.
45 *
46 * This class is a copy of the java.util.StringTokenizer API and
47 * the behaviour is the same, except that single and doulbe quoted
48 * string values are recognized.
49 * Delimiters within quotes are not considered delimiters.
50 * Quotes can be escaped with '\'.
51 *
52 * @see java.util.StringTokenizer
53 * @author Greg Wilkins (gregw)
54 */
55 public class QuotedStringTokenizer
56 extends StringTokenizer
57 {
58 private final static String __delim=" \t\n\r";
59 private String _string;
60 private String _delim = __delim;
61 private boolean _returnQuotes=false;
62 private boolean _returnDelimiters=false;
63 private StringBuilder _token;
64 private boolean _hasToken=false;
65 private int _i=0;
66 private int _lastStart=0;
67 private boolean _double=true;
68 private boolean _single=true;
69
70 public static String[] tokenize(String str) {
71 return new QuotedStringTokenizer(str).toArray();
72 }
73
74 public static String[] tokenize(String str, String delimiters) {
75 return new QuotedStringTokenizer(str,delimiters).toArray();
76 }
77
78 /* ------------------------------------------------------------ */
79 /**
80 *
81 * @param str
82 * String to tokenize.
83 * @param delim
84 * List of delimiter characters as string. Can be null, to default to ' \t\n\r'
85 * @param returnDelimiters
86 * If true, {@link #nextToken()} will include the delimiters, not just tokenized
87 * tokens.
88 * @param returnQuotes
89 * If true, {@link #nextToken()} will include the quotation characters when they are present.
90 */
91 public QuotedStringTokenizer(String str,
92 String delim,
93 boolean returnDelimiters,
94 boolean returnQuotes)
95 {
96 super("");
97 _string=str;
98 if (delim!=null)
99 _delim=delim;
100 _returnDelimiters=returnDelimiters;
101 _returnQuotes=returnQuotes;
102
103 if (_delim.indexOf('\'')>=0 ||
104 _delim.indexOf('"')>=0)
105 throw new Error("Can't use quotes as delimiters: "+_delim);
106
107 _token=new StringBuilder(_string.length()>1024?512:_string.length()/2);
108 }
109
110 /* ------------------------------------------------------------ */
111 public QuotedStringTokenizer(String str,
112 String delim,
113 boolean returnDelimiters)
114 {
115 this(str,delim,returnDelimiters,false);
116 }
117
118 /* ------------------------------------------------------------ */
119 public QuotedStringTokenizer(String str,
120 String delim)
121 {
122 this(str,delim,false,false);
123 }
124
125 /* ------------------------------------------------------------ */
126 public QuotedStringTokenizer(String str)
127 {
128 this(str,null,false,false);
129 }
130
131 public String[] toArray() {
132 List<String> r = new ArrayList<String>();
133 while(hasMoreTokens())
134 r.add(nextToken());
135 return r.toArray(new String[r.size()]);
136 }
137
138
139 /* ------------------------------------------------------------ */
140 @Override
141 public boolean hasMoreTokens()
142 {
143 // Already found a token
144 if (_hasToken)
145 return true;
146
147 _lastStart=_i;
148
149 int state=0;
150 boolean escape=false;
151 while (_i<_string.length())
152 {
153 char c=_string.charAt(_i++);
154
155 switch (state)
156 {
157 case 0: // Start
158 if(_delim.indexOf(c)>=0)
159 {
160 if (_returnDelimiters)
161 {
162 _token.append(c);
163 return _hasToken=true;
164 }
165 }
166 else if (c=='\'' && _single)
167 {
168 if (_returnQuotes)
169 _token.append(c);
170 state=2;
171 }
172 else if (c=='\"' && _double)
173 {
174 if (_returnQuotes)
175 _token.append(c);
176 state=3;
177 }
178 else
179 {
180 _token.append(c);
181 _hasToken=true;
182 state=1;
183 }
184 continue;
185
186 case 1: // Token
187 _hasToken=true;
188 if (escape)
189 {
190 escape=false;
191 if(ESCAPABLE_CHARS.indexOf(c)<0)
192 _token.append('\\');
193 _token.append(c);
194 }
195 else if(_delim.indexOf(c)>=0)
196 {
197 if (_returnDelimiters)
198 _i--;
199 return _hasToken;
200 }
201 else if (c=='\'' && _single)
202 {
203 if (_returnQuotes)
204 _token.append(c);
205 state=2;
206 }
207 else if (c=='\"' && _double)
208 {
209 if (_returnQuotes)
210 _token.append(c);
211 state=3;
212 }
213 else if (c=='\\')
214 {
215 escape=true;
216 }
217 else
218 _token.append(c);
219 continue;
220
221
222 case 2: // Single Quote
223 _hasToken=true;
224 if (escape)
225 {
226 escape=false;
227 if(ESCAPABLE_CHARS.indexOf(c)<0)
228 _token.append('\\');
229 _token.append(c);
230 }
231 else if (c=='\'')
232 {
233 if (_returnQuotes)
234 _token.append(c);
235 state=1;
236 }
237 else if (c=='\\')
238 {
239 if (_returnQuotes)
240 _token.append(c);
241 escape=true;
242 }
243 else
244 _token.append(c);
245 continue;
246
247
248 case 3: // Double Quote
249 _hasToken=true;
250 if (escape)
251 {
252 escape=false;
253 if(ESCAPABLE_CHARS.indexOf(c)<0)
254 _token.append('\\');
255 _token.append(c);
256 }
257 else if (c=='\"')
258 {
259 if (_returnQuotes)
260 _token.append(c);
261 state=1;
262 }
263 else if (c=='\\')
264 {
265 if (_returnQuotes)
266 _token.append(c);
267 escape=true;
268 }
269 else
270 _token.append(c);
271 continue;
272 }
273 }
274
275 return _hasToken;
276 }
277
278 /* ------------------------------------------------------------ */
279 @Override
280 public String nextToken()
281 throws NoSuchElementException
282 {
283 if (!hasMoreTokens() || _token==null)
284 throw new NoSuchElementException();
285 String t=_token.toString();
286 _token.setLength(0);
287 _hasToken=false;
288 return t;
289 }
290
291 /* ------------------------------------------------------------ */
292 @Override
293 public String nextToken(String delim)
294 throws NoSuchElementException
295 {
296 _delim=delim;
297 _i=_lastStart;
298 _token.setLength(0);
299 _hasToken=false;
300 return nextToken();
301 }
302
303 /* ------------------------------------------------------------ */
304 @Override
305 public boolean hasMoreElements()
306 {
307 return hasMoreTokens();
308 }
309
310 /* ------------------------------------------------------------ */
311 @Override
312 public Object nextElement()
313 throws NoSuchElementException
314 {
315 return nextToken();
316 }
317
318 /* ------------------------------------------------------------ */
319 /** Not implemented.
320 */
321 @Override
322 public int countTokens()
323 {
324 return -1;
325 }
326
327
328 /* ------------------------------------------------------------ */
329 /** Quote a string.
330 * The string is quoted only if quoting is required due to
331 * embeded delimiters, quote characters or the
332 * empty string.
333 * @param s The string to quote.
334 * @return quoted string
335 */
336 public static String quote(String s, String delim)
337 {
338 if (s==null)
339 return null;
340 if (s.length()==0)
341 return "\"\"";
342
343
344 for (int i=0;i<s.length();i++)
345 {
346 char c = s.charAt(i);
347 if (c=='\\' || c=='"' || c=='\'' || Character.isWhitespace(c) || delim.indexOf(c)>=0)
348 {
349 StringBuffer b=new StringBuffer(s.length()+8);
350 quote(b,s);
351 return b.toString();
352 }
353 }
354
355 return s;
356 }
357
358 /* ------------------------------------------------------------ */
359 /** Quote a string.
360 * The string is quoted only if quoting is required due to
361 * embeded delimiters, quote characters or the
362 * empty string.
363 * @param s The string to quote.
364 * @return quoted string
365 */
366 public static String quote(String s)
367 {
368 if (s==null)
369 return null;
370 if (s.length()==0)
371 return "\"\"";
372
373 StringBuffer b=new StringBuffer(s.length()+8);
374 quote(b,s);
375 return b.toString();
376
377 }
378
379
380 /* ------------------------------------------------------------ */
381 /** Quote a string into a StringBuffer.
382 * The characters ", \, \n, \r, \t, \f and \b are escaped
383 * @param buf The StringBuffer
384 * @param s The String to quote.
385 */
386 public static void quote(StringBuffer buf, String s)
387 {
388 synchronized(buf)
389 {
390 buf.append('"');
391 for (int i=0;i<s.length();i++)
392 {
393 char c = s.charAt(i);
394 switch(c)
395 {
396 case '"':
397 buf.append("\\\"");
398 continue;
399 case '\\':
400 buf.append("\\\\");
401 continue;
402 case '\n':
403 buf.append("\\n");
404 continue;
405 case '\r':
406 buf.append("\\r");
407 continue;
408 case '\t':
409 buf.append("\\t");
410 continue;
411 case '\f':
412 buf.append("\\f");
413 continue;
414 case '\b':
415 buf.append("\\b");
416 continue;
417
418 default:
419 buf.append(c);
420 continue;
421 }
422 }
423 buf.append('"');
424 }
425 }
426
427 /* ------------------------------------------------------------ */
428 /** Unquote a string.
429 * @param s The string to unquote.
430 * @return quoted string
431 */
432 public static String unquote(String s)
433 {
434 if (s==null)
435 return null;
436 if (s.length()<2)
437 return s;
438
439 char first=s.charAt(0);
440 char last=s.charAt(s.length()-1);
441 if (first!=last || (first!='"' && first!='\''))
442 return s;
443
444 StringBuilder b=new StringBuilder(s.length()-2);
445 boolean escape=false;
446 for (int i=1;i<s.length()-1;i++)
447 {
448 char c = s.charAt(i);
449
450 if (escape)
451 {
452 escape=false;
453 switch (c)
454 {
455 case 'n':
456 b.append('\n');
457 break;
458 case 'r':
459 b.append('\r');
460 break;
461 case 't':
462 b.append('\t');
463 break;
464 case 'f':
465 b.append('\f');
466 break;
467 case 'b':
468 b.append('\b');
469 break;
470 case 'u':
471 b.append((char)(
472 (convertHexDigit((byte)s.charAt(i++))<<24)+
473 (convertHexDigit((byte)s.charAt(i++))<<16)+
474 (convertHexDigit((byte)s.charAt(i++))<<8)+
475 (convertHexDigit((byte)s.charAt(i++)))
476 )
477 );
478 break;
479 default:
480 b.append(c);
481 }
482 }
483 else if (c=='\\')
484 {
485 escape=true;
486 continue;
487 }
488 else
489 b.append(c);
490 }
491
492 return b.toString();
493 }
494
495 /* ------------------------------------------------------------ */
496 /**
497 * @return handle double quotes if true
498 */
499 public boolean getDouble()
500 {
501 return _double;
502 }
503
504 /* ------------------------------------------------------------ */
505 /**
506 * @param d handle double quotes if true
507 */
508 public void setDouble(boolean d)
509 {
510 _double=d;
511 }
512
513 /* ------------------------------------------------------------ */
514 /**
515 * @return handle single quotes if true
516 */
517 public boolean getSingle()
518 {
519 return _single;
520 }
521
522 /* ------------------------------------------------------------ */
523 /**
524 * @param single handle single quotes if true
525 */
526 public void setSingle(boolean single)
527 {
528 _single=single;
529 }
530
531 /**
532 * @param b An ASCII encoded character 0-9 a-f A-F
533 * @return The byte value of the character 0-16.
534 */
535 public static byte convertHexDigit( byte b )
536 {
537 if ((b >= '0') && (b <= '9')) return (byte)(b - '0');
538 if ((b >= 'a') && (b <= 'f')) return (byte)(b - 'a' + 10);
539 if ((b >= 'A') && (b <= 'F')) return (byte)(b - 'A' + 10);
540 return 0;
541 }
542
543 /**
544 * Characters that can be escaped with \.
545 *
546 * Others, like, say, \W will be left alone instead of becoming just W.
547 * This is important to keep Hudson behave on Windows, which uses '\' as
548 * the directory separator.
549 */
550 private static final String ESCAPABLE_CHARS = "\\\"' ";
551 }
552
553
554
555
556
557
558
559
560
561
562
563