1 package org.apache.maven.surefire.util.internal;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.nio.ByteBuffer;
23 import java.nio.CharBuffer;
24 import java.nio.charset.CharacterCodingException;
25 import java.nio.charset.Charset;
26 import java.util.StringTokenizer;
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 public final class StringUtils
54 {
55 public static final String NL = System.getProperty( "line.separator" );
56
57 private static final byte[] HEX_CHARS = {
58 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
59
60 private static final Charset DEFAULT_CHARSET = Charset.defaultCharset();
61
62
63
64
65
66 public static final Charset US_ASCII = Charset.forName( "US-ASCII" );
67
68
69 public static final Charset ISO_8859_1 = Charset.forName( "ISO-8859-1" );
70
71 public static final Charset UTF_8 = Charset.forName( "UTF-8" );
72
73 private StringUtils()
74 {
75 throw new IllegalStateException( "no instantiable constructor" );
76 }
77
78 public static String[] split( String text, String separator )
79 {
80 final StringTokenizer tok;
81 if ( separator == null )
82 {
83
84
85 tok = new StringTokenizer( text );
86 }
87 else
88 {
89 tok = new StringTokenizer( text, separator );
90 }
91
92 String[] list = new String[tok.countTokens()];
93 for ( int i = 0; tok.hasMoreTokens(); i++ )
94 {
95 list[i] = tok.nextToken();
96 }
97 return list;
98 }
99
100
101
102
103
104
105
106
107
108 public static boolean isBlank( String str )
109 {
110 return str == null || str.trim().isEmpty();
111 }
112
113
114
115
116
117
118
119
120
121 public static boolean isNotBlank( String str )
122 {
123 return !isBlank( str );
124 }
125
126
127
128
129
130
131
132
133
134
135 @SuppressWarnings( "checkstyle:magicnumber" )
136 public static void escapeToPrintable( StringBuilder target, CharSequence str )
137 {
138 if ( target == null )
139 {
140 throw new IllegalArgumentException( "The target buffer must not be null" );
141 }
142 if ( str == null )
143 {
144 return;
145 }
146
147 for ( int i = 0; i < str.length(); i++ )
148 {
149 char c = str.charAt( i );
150
151
152 if ( c < 32 || c > 126 || c == '\\' || c == ',' )
153 {
154 target.append( '\\' );
155 target.append( (char) HEX_CHARS[( 0xF000 & c ) >> 12] );
156 target.append( (char) HEX_CHARS[( 0x0F00 & c ) >> 8] );
157 target.append( (char) HEX_CHARS[( 0x00F0 & c ) >> 4] );
158 target.append( (char) HEX_CHARS[( 0x000F & c )] );
159 }
160 else
161 {
162 target.append( c );
163 }
164 }
165 }
166
167
168
169
170
171
172
173 public static void unescapeString( StringBuilder target, CharSequence str )
174 {
175 if ( target == null )
176 {
177 throw new IllegalArgumentException( "The target buffer must not be null" );
178 }
179 if ( str == null )
180 {
181 return;
182 }
183
184 for ( int i = 0; i < str.length(); i++ )
185 {
186 char ch = str.charAt( i );
187
188 if ( ch == '\\' )
189 {
190 target.append( (char) (
191 digit( str.charAt( ++i ) ) << 12
192 | digit( str.charAt( ++i ) ) << 8
193 | digit( str.charAt( ++i ) ) << 4
194 | digit( str.charAt( ++i ) )
195 ) );
196 }
197 else
198 {
199 target.append( ch );
200 }
201 }
202 }
203
204 private static int digit( char ch )
205 {
206 if ( ch >= 'a' )
207 {
208 return 10 + ch - 'a';
209 }
210 else if ( ch >= 'A' )
211 {
212 return 10 + ch - 'A';
213 }
214 else
215 {
216 return ch - '0';
217 }
218 }
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238 @SuppressWarnings( "checkstyle:magicnumber" )
239 public static EncodedArray escapeBytesToPrintable( final byte[] header, final byte[] input, final int off,
240 final int len )
241 {
242 if ( off < 0 || len < 0 || off >= input.length || len > input.length || off > len )
243 {
244 throw new IndexOutOfBoundsException(
245 "off < 0 || len < 0 || off >= input.length || len > input.length || off > len" );
246 }
247
248 final byte[] encodeBytes = new byte[header.length + 3 * len + 1];
249 System.arraycopy( header, 0, encodeBytes, 0, header.length );
250 int outputPos = header.length;
251 final int end = off + len;
252 for ( int i = off; i < end; i++ )
253 {
254 final byte b = input[i];
255
256
257 if ( b < 32 || b > 126 || b == '\\' || b == ',' )
258 {
259 final int upper = ( 0xF0 & b ) >> 4;
260 final int lower = ( 0x0F & b );
261 encodeBytes[outputPos++] = '\\';
262 encodeBytes[outputPos++] = HEX_CHARS[upper];
263 encodeBytes[outputPos++] = HEX_CHARS[lower];
264 }
265 else
266 {
267 encodeBytes[outputPos++] = b;
268 }
269 }
270 encodeBytes[outputPos++] = (byte) '\n';
271
272 return new EncodedArray( encodeBytes, outputPos );
273 }
274
275
276
277
278
279
280
281
282 public static ByteBuffer unescapeBytes( String str, String charsetName )
283 {
284 int outPos = 0;
285
286 if ( str == null )
287 {
288 return ByteBuffer.wrap( new byte[0] );
289 }
290
291 byte[] out = new byte[str.length()];
292 for ( int i = 0; i < str.length(); i++ )
293 {
294 char ch = str.charAt( i );
295
296 if ( ch == '\\' )
297 {
298 int upper = digit( str.charAt( ++i ) );
299 int lower = digit( str.charAt( ++i ) );
300 out[outPos++] = (byte) ( upper << 4 | lower );
301 }
302 else
303 {
304 out[outPos++] = (byte) ch;
305 }
306 }
307
308 Charset sourceCharset = Charset.forName( charsetName );
309 if ( !DEFAULT_CHARSET.equals( sourceCharset ) )
310 {
311 CharBuffer decodedFromSourceCharset;
312 try
313 {
314 decodedFromSourceCharset = sourceCharset.newDecoder().decode( ByteBuffer.wrap( out, 0, outPos ) );
315 return DEFAULT_CHARSET.encode( decodedFromSourceCharset );
316 }
317 catch ( CharacterCodingException e )
318 {
319
320 }
321 }
322
323 return ByteBuffer.wrap( out, 0, outPos );
324 }
325
326 public static byte[] encodeStringForForkCommunication( String string )
327 {
328 return string.getBytes( ISO_8859_1 );
329 }
330
331
332
333
334
335
336
337
338 public static boolean startsWith( StringBuffer buffer, String pattern )
339 {
340 if ( buffer.length() < pattern.length() )
341 {
342 return false;
343 }
344 else
345 {
346 for ( int i = 0, len = pattern.length(); i < len; i++ )
347 {
348 if ( buffer.charAt( i ) != pattern.charAt( i ) )
349 {
350 return false;
351 }
352 }
353 return true;
354 }
355 }
356
357
358
359
360 public static final class EncodedArray
361 {
362 private final byte[] array;
363 private final int size;
364
365 private EncodedArray( byte[] array, int size )
366 {
367 this.array = array;
368 this.size = size;
369 }
370
371 public byte[] getArray()
372 {
373 return array;
374 }
375
376 public int getSize()
377 {
378 return size;
379 }
380 }
381 }