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