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