1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.util;
15
16 import java.io.UnsupportedEncodingException;
17 import java.nio.charset.Charset;
18
19 import org.eclipse.jetty.util.log.Log;
20 import org.eclipse.jetty.util.log.Logger;
21
22
23
24
25
26
27
28
29
30
31
32 public class StringUtil
33 {
34 private static final Logger LOG = Log.getLogger(StringUtil.class);
35
36 public static final String ALL_INTERFACES="0.0.0.0";
37 public static final String CRLF="\015\012";
38 public static final String __LINE_SEPARATOR=
39 System.getProperty("line.separator","\n");
40
41 public static final String __ISO_8859_1="ISO-8859-1";
42 public final static String __UTF8="UTF-8";
43 public final static String __UTF8Alt="UTF8";
44 public final static String __UTF16="UTF-16";
45
46 public final static Charset __UTF8_CHARSET;
47 public final static Charset __ISO_8859_1_CHARSET;
48
49 static
50 {
51 __UTF8_CHARSET=Charset.forName(__UTF8);
52 __ISO_8859_1_CHARSET=Charset.forName(__ISO_8859_1);
53 }
54
55 private static char[] lowercases = {
56 '\000','\001','\002','\003','\004','\005','\006','\007',
57 '\010','\011','\012','\013','\014','\015','\016','\017',
58 '\020','\021','\022','\023','\024','\025','\026','\027',
59 '\030','\031','\032','\033','\034','\035','\036','\037',
60 '\040','\041','\042','\043','\044','\045','\046','\047',
61 '\050','\051','\052','\053','\054','\055','\056','\057',
62 '\060','\061','\062','\063','\064','\065','\066','\067',
63 '\070','\071','\072','\073','\074','\075','\076','\077',
64 '\100','\141','\142','\143','\144','\145','\146','\147',
65 '\150','\151','\152','\153','\154','\155','\156','\157',
66 '\160','\161','\162','\163','\164','\165','\166','\167',
67 '\170','\171','\172','\133','\134','\135','\136','\137',
68 '\140','\141','\142','\143','\144','\145','\146','\147',
69 '\150','\151','\152','\153','\154','\155','\156','\157',
70 '\160','\161','\162','\163','\164','\165','\166','\167',
71 '\170','\171','\172','\173','\174','\175','\176','\177' };
72
73
74
75
76
77
78
79 public static String asciiToLowerCase(String s)
80 {
81 char[] c = null;
82 int i=s.length();
83
84
85 while (i-->0)
86 {
87 char c1=s.charAt(i);
88 if (c1<=127)
89 {
90 char c2=lowercases[c1];
91 if (c1!=c2)
92 {
93 c=s.toCharArray();
94 c[i]=c2;
95 break;
96 }
97 }
98 }
99
100 while (i-->0)
101 {
102 if(c[i]<=127)
103 c[i] = lowercases[c[i]];
104 }
105
106 return c==null?s:new String(c);
107 }
108
109
110
111 public static boolean startsWithIgnoreCase(String s,String w)
112 {
113 if (w==null)
114 return true;
115
116 if (s==null || s.length()<w.length())
117 return false;
118
119 for (int i=0;i<w.length();i++)
120 {
121 char c1=s.charAt(i);
122 char c2=w.charAt(i);
123 if (c1!=c2)
124 {
125 if (c1<=127)
126 c1=lowercases[c1];
127 if (c2<=127)
128 c2=lowercases[c2];
129 if (c1!=c2)
130 return false;
131 }
132 }
133 return true;
134 }
135
136
137 public static boolean endsWithIgnoreCase(String s,String w)
138 {
139 if (w==null)
140 return true;
141
142 if (s==null)
143 return false;
144
145 int sl=s.length();
146 int wl=w.length();
147
148 if (sl<wl)
149 return false;
150
151 for (int i=wl;i-->0;)
152 {
153 char c1=s.charAt(--sl);
154 char c2=w.charAt(i);
155 if (c1!=c2)
156 {
157 if (c1<=127)
158 c1=lowercases[c1];
159 if (c2<=127)
160 c2=lowercases[c2];
161 if (c1!=c2)
162 return false;
163 }
164 }
165 return true;
166 }
167
168
169
170
171
172 public static int indexFrom(String s,String chars)
173 {
174 for (int i=0;i<s.length();i++)
175 if (chars.indexOf(s.charAt(i))>=0)
176 return i;
177 return -1;
178 }
179
180
181
182
183
184 public static String replace(String s, String sub, String with)
185 {
186 int c=0;
187 int i=s.indexOf(sub,c);
188 if (i == -1)
189 return s;
190
191 StringBuilder buf = new StringBuilder(s.length()+with.length());
192
193 do
194 {
195 buf.append(s.substring(c,i));
196 buf.append(with);
197 c=i+sub.length();
198 } while ((i=s.indexOf(sub,c))!=-1);
199
200 if (c<s.length())
201 buf.append(s.substring(c,s.length()));
202
203 return buf.toString();
204
205 }
206
207
208
209
210
211 public static String unquote(String s)
212 {
213 return QuotedStringTokenizer.unquote(s);
214 }
215
216
217
218
219
220
221
222
223
224 public static void append(StringBuilder buf,
225 String s,
226 int offset,
227 int length)
228 {
229 synchronized(buf)
230 {
231 int end=offset+length;
232 for (int i=offset; i<end;i++)
233 {
234 if (i>=s.length())
235 break;
236 buf.append(s.charAt(i));
237 }
238 }
239 }
240
241
242
243
244
245
246
247 public static void append(StringBuilder buf,byte b,int base)
248 {
249 int bi=0xff&b;
250 int c='0'+(bi/base)%base;
251 if (c>'9')
252 c= 'a'+(c-'0'-10);
253 buf.append((char)c);
254 c='0'+bi%base;
255 if (c>'9')
256 c= 'a'+(c-'0'-10);
257 buf.append((char)c);
258 }
259
260
261 public static void append2digits(StringBuffer buf,int i)
262 {
263 if (i<100)
264 {
265 buf.append((char)(i/10+'0'));
266 buf.append((char)(i%10+'0'));
267 }
268 }
269
270
271 public static void append2digits(StringBuilder buf,int i)
272 {
273 if (i<100)
274 {
275 buf.append((char)(i/10+'0'));
276 buf.append((char)(i%10+'0'));
277 }
278 }
279
280
281
282
283
284
285 public static String nonNull(String s)
286 {
287 if (s==null)
288 return "";
289 return s;
290 }
291
292
293 public static boolean equals(String s,char[] buf, int offset, int length)
294 {
295 if (s.length()!=length)
296 return false;
297 for (int i=0;i<length;i++)
298 if (buf[offset+i]!=s.charAt(i))
299 return false;
300 return true;
301 }
302
303
304 public static String toUTF8String(byte[] b,int offset,int length)
305 {
306 try
307 {
308 return new String(b,offset,length,__UTF8);
309 }
310 catch (UnsupportedEncodingException e)
311 {
312 throw new IllegalArgumentException(e);
313 }
314 }
315
316
317 public static String toString(byte[] b,int offset,int length,String charset)
318 {
319 try
320 {
321 return new String(b,offset,length,charset);
322 }
323 catch (UnsupportedEncodingException e)
324 {
325 throw new IllegalArgumentException(e);
326 }
327 }
328
329
330
331 public static boolean isUTF8(String charset)
332 {
333 return charset==__UTF8||__UTF8.equalsIgnoreCase(charset)||__UTF8Alt.equalsIgnoreCase(charset);
334 }
335
336
337
338 public static String printable(String name)
339 {
340 if (name==null)
341 return null;
342 StringBuilder buf = new StringBuilder(name.length());
343 for (int i=0;i<name.length();i++)
344 {
345 char c=name.charAt(i);
346 if (!Character.isISOControl(c))
347 buf.append(c);
348 }
349 return buf.toString();
350 }
351
352
353 public static String printable(byte[] b)
354 {
355 StringBuilder buf = new StringBuilder();
356 for (int i=0;i<b.length;i++)
357 {
358 char c=(char)b[i];
359 if (Character.isWhitespace(c)|| c>' ' && c<0x7f)
360 buf.append(c);
361 else
362 {
363 buf.append("0x");
364 TypeUtil.toHex(b[i],buf);
365 }
366 }
367 return buf.toString();
368 }
369
370 public static byte[] getBytes(String s)
371 {
372 try
373 {
374 return s.getBytes(__ISO_8859_1);
375 }
376 catch(Exception e)
377 {
378 LOG.warn(e);
379 return s.getBytes();
380 }
381 }
382
383 public static byte[] getBytes(String s,String charset)
384 {
385 try
386 {
387 return s.getBytes(charset);
388 }
389 catch(Exception e)
390 {
391 LOG.warn(e);
392 return s.getBytes();
393 }
394 }
395
396
397
398
399
400
401
402
403
404
405 public static String sidBytesToString(byte[] sidBytes)
406 {
407 StringBuilder sidString = new StringBuilder();
408
409
410 sidString.append("S-");
411
412
413 sidString.append(Byte.toString(sidBytes[0])).append('-');
414
415 StringBuilder tmpBuilder = new StringBuilder();
416
417
418 for (int i = 2; i <= 7; ++i)
419 {
420 tmpBuilder.append(Integer.toHexString(sidBytes[i] & 0xFF));
421 }
422
423 sidString.append(Long.parseLong(tmpBuilder.toString(), 16));
424
425
426 int subAuthorityCount = sidBytes[1];
427
428
429 for (int i = 0; i < subAuthorityCount; ++i)
430 {
431 int offset = i * 4;
432 tmpBuilder.setLength(0);
433
434 tmpBuilder.append(String.format("%02X%02X%02X%02X",
435 (sidBytes[11 + offset] & 0xFF),
436 (sidBytes[10 + offset] & 0xFF),
437 (sidBytes[9 + offset] & 0xFF),
438 (sidBytes[8 + offset] & 0xFF)));
439 sidString.append('-').append(Long.parseLong(tmpBuilder.toString(), 16));
440 }
441
442 return sidString.toString();
443 }
444
445
446
447
448
449
450
451
452 public static byte[] sidStringToBytes( String sidString )
453 {
454 String[] sidTokens = sidString.split("-");
455
456 int subAuthorityCount = sidTokens.length - 3;
457
458 int byteCount = 0;
459 byte[] sidBytes = new byte[1 + 1 + 6 + (4 * subAuthorityCount)];
460
461
462 sidBytes[byteCount++] = (byte)Integer.parseInt(sidTokens[1]);
463
464
465 sidBytes[byteCount++] = (byte)subAuthorityCount;
466
467
468 String hexStr = Long.toHexString(Long.parseLong(sidTokens[2]));
469
470 while( hexStr.length() < 12)
471 {
472 hexStr = "0" + hexStr;
473 }
474
475
476 for ( int i = 0 ; i < hexStr.length(); i = i + 2)
477 {
478 sidBytes[byteCount++] = (byte)Integer.parseInt(hexStr.substring(i, i + 2),16);
479 }
480
481
482 for ( int i = 3; i < sidTokens.length ; ++i)
483 {
484 hexStr = Long.toHexString(Long.parseLong(sidTokens[i]));
485
486 while( hexStr.length() < 8)
487 {
488 hexStr = "0" + hexStr;
489 }
490
491
492 for ( int j = hexStr.length(); j > 0; j = j - 2)
493 {
494 sidBytes[byteCount++] = (byte)Integer.parseInt(hexStr.substring(j-2, j),16);
495 }
496 }
497
498 return sidBytes;
499 }
500 }