1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.util;
20
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.lang.reflect.Constructor;
24 import java.lang.reflect.InvocationTargetException;
25 import java.lang.reflect.Method;
26 import java.lang.reflect.Modifier;
27 import java.net.URL;
28 import java.util.Arrays;
29 import java.util.Collections;
30 import java.util.HashMap;
31 import java.util.List;
32
33 import org.eclipse.jetty.util.log.Log;
34 import org.eclipse.jetty.util.log.Logger;
35
36
37
38
39
40
41
42
43
44
45 public class TypeUtil
46 {
47 private static final Logger LOG = Log.getLogger(TypeUtil.class);
48 public static int CR = '\015';
49 public static int LF = '\012';
50
51
52 private static final HashMap<String, Class<?>> name2Class=new HashMap<String, Class<?>>();
53 static
54 {
55 name2Class.put("boolean",java.lang.Boolean.TYPE);
56 name2Class.put("byte",java.lang.Byte.TYPE);
57 name2Class.put("char",java.lang.Character.TYPE);
58 name2Class.put("double",java.lang.Double.TYPE);
59 name2Class.put("float",java.lang.Float.TYPE);
60 name2Class.put("int",java.lang.Integer.TYPE);
61 name2Class.put("long",java.lang.Long.TYPE);
62 name2Class.put("short",java.lang.Short.TYPE);
63 name2Class.put("void",java.lang.Void.TYPE);
64
65 name2Class.put("java.lang.Boolean.TYPE",java.lang.Boolean.TYPE);
66 name2Class.put("java.lang.Byte.TYPE",java.lang.Byte.TYPE);
67 name2Class.put("java.lang.Character.TYPE",java.lang.Character.TYPE);
68 name2Class.put("java.lang.Double.TYPE",java.lang.Double.TYPE);
69 name2Class.put("java.lang.Float.TYPE",java.lang.Float.TYPE);
70 name2Class.put("java.lang.Integer.TYPE",java.lang.Integer.TYPE);
71 name2Class.put("java.lang.Long.TYPE",java.lang.Long.TYPE);
72 name2Class.put("java.lang.Short.TYPE",java.lang.Short.TYPE);
73 name2Class.put("java.lang.Void.TYPE",java.lang.Void.TYPE);
74
75 name2Class.put("java.lang.Boolean",java.lang.Boolean.class);
76 name2Class.put("java.lang.Byte",java.lang.Byte.class);
77 name2Class.put("java.lang.Character",java.lang.Character.class);
78 name2Class.put("java.lang.Double",java.lang.Double.class);
79 name2Class.put("java.lang.Float",java.lang.Float.class);
80 name2Class.put("java.lang.Integer",java.lang.Integer.class);
81 name2Class.put("java.lang.Long",java.lang.Long.class);
82 name2Class.put("java.lang.Short",java.lang.Short.class);
83
84 name2Class.put("Boolean",java.lang.Boolean.class);
85 name2Class.put("Byte",java.lang.Byte.class);
86 name2Class.put("Character",java.lang.Character.class);
87 name2Class.put("Double",java.lang.Double.class);
88 name2Class.put("Float",java.lang.Float.class);
89 name2Class.put("Integer",java.lang.Integer.class);
90 name2Class.put("Long",java.lang.Long.class);
91 name2Class.put("Short",java.lang.Short.class);
92
93 name2Class.put(null,java.lang.Void.TYPE);
94 name2Class.put("string",java.lang.String.class);
95 name2Class.put("String",java.lang.String.class);
96 name2Class.put("java.lang.String",java.lang.String.class);
97 }
98
99
100 private static final HashMap<Class<?>, String> class2Name=new HashMap<Class<?>, String>();
101 static
102 {
103 class2Name.put(java.lang.Boolean.TYPE,"boolean");
104 class2Name.put(java.lang.Byte.TYPE,"byte");
105 class2Name.put(java.lang.Character.TYPE,"char");
106 class2Name.put(java.lang.Double.TYPE,"double");
107 class2Name.put(java.lang.Float.TYPE,"float");
108 class2Name.put(java.lang.Integer.TYPE,"int");
109 class2Name.put(java.lang.Long.TYPE,"long");
110 class2Name.put(java.lang.Short.TYPE,"short");
111 class2Name.put(java.lang.Void.TYPE,"void");
112
113 class2Name.put(java.lang.Boolean.class,"java.lang.Boolean");
114 class2Name.put(java.lang.Byte.class,"java.lang.Byte");
115 class2Name.put(java.lang.Character.class,"java.lang.Character");
116 class2Name.put(java.lang.Double.class,"java.lang.Double");
117 class2Name.put(java.lang.Float.class,"java.lang.Float");
118 class2Name.put(java.lang.Integer.class,"java.lang.Integer");
119 class2Name.put(java.lang.Long.class,"java.lang.Long");
120 class2Name.put(java.lang.Short.class,"java.lang.Short");
121
122 class2Name.put(null,"void");
123 class2Name.put(java.lang.String.class,"java.lang.String");
124 }
125
126
127 private static final HashMap<Class<?>, Method> class2Value=new HashMap<Class<?>, Method>();
128 static
129 {
130 try
131 {
132 Class<?>[] s ={java.lang.String.class};
133
134 class2Value.put(java.lang.Boolean.TYPE,
135 java.lang.Boolean.class.getMethod("valueOf",s));
136 class2Value.put(java.lang.Byte.TYPE,
137 java.lang.Byte.class.getMethod("valueOf",s));
138 class2Value.put(java.lang.Double.TYPE,
139 java.lang.Double.class.getMethod("valueOf",s));
140 class2Value.put(java.lang.Float.TYPE,
141 java.lang.Float.class.getMethod("valueOf",s));
142 class2Value.put(java.lang.Integer.TYPE,
143 java.lang.Integer.class.getMethod("valueOf",s));
144 class2Value.put(java.lang.Long.TYPE,
145 java.lang.Long.class.getMethod("valueOf",s));
146 class2Value.put(java.lang.Short.TYPE,
147 java.lang.Short.class.getMethod("valueOf",s));
148
149 class2Value.put(java.lang.Boolean.class,
150 java.lang.Boolean.class.getMethod("valueOf",s));
151 class2Value.put(java.lang.Byte.class,
152 java.lang.Byte.class.getMethod("valueOf",s));
153 class2Value.put(java.lang.Double.class,
154 java.lang.Double.class.getMethod("valueOf",s));
155 class2Value.put(java.lang.Float.class,
156 java.lang.Float.class.getMethod("valueOf",s));
157 class2Value.put(java.lang.Integer.class,
158 java.lang.Integer.class.getMethod("valueOf",s));
159 class2Value.put(java.lang.Long.class,
160 java.lang.Long.class.getMethod("valueOf",s));
161 class2Value.put(java.lang.Short.class,
162 java.lang.Short.class.getMethod("valueOf",s));
163 }
164 catch(Exception e)
165 {
166 throw new Error(e);
167 }
168 }
169
170
171
172
173
174
175
176 public static <T> List<T> asList(T[] a)
177 {
178 if (a==null)
179 return Collections.emptyList();
180 return Arrays.asList(a);
181 }
182
183
184
185
186
187
188 public static Class<?> fromName(String name)
189 {
190 return name2Class.get(name);
191 }
192
193
194
195
196
197
198 public static String toName(Class<?> type)
199 {
200 return class2Name.get(type);
201 }
202
203
204
205
206
207
208
209 public static Object valueOf(Class<?> type, String value)
210 {
211 try
212 {
213 if (type.equals(java.lang.String.class))
214 return value;
215
216 Method m = class2Value.get(type);
217 if (m!=null)
218 return m.invoke(null, value);
219
220 if (type.equals(java.lang.Character.TYPE) ||
221 type.equals(java.lang.Character.class))
222 return new Character(value.charAt(0));
223
224 Constructor<?> c = type.getConstructor(java.lang.String.class);
225 return c.newInstance(value);
226 }
227 catch(NoSuchMethodException e)
228 {
229
230 }
231 catch(IllegalAccessException e)
232 {
233
234 }
235 catch(InstantiationException e)
236 {
237
238 }
239 catch(InvocationTargetException e)
240 {
241 if (e.getTargetException() instanceof Error)
242 throw (Error)(e.getTargetException());
243
244 }
245 return null;
246 }
247
248
249
250
251
252
253
254 public static Object valueOf(String type, String value)
255 {
256 return valueOf(fromName(type),value);
257 }
258
259
260
261
262
263
264
265
266
267
268
269 public static int parseInt(String s, int offset, int length, int base)
270 throws NumberFormatException
271 {
272 int value=0;
273
274 if (length<0)
275 length=s.length()-offset;
276
277 for (int i=0;i<length;i++)
278 {
279 char c=s.charAt(offset+i);
280
281 int digit=convertHexDigit((int)c);
282 if (digit<0 || digit>=base)
283 throw new NumberFormatException(s.substring(offset,offset+length));
284 value=value*base+digit;
285 }
286 return value;
287 }
288
289
290
291
292
293
294
295
296
297
298
299 public static int parseInt(byte[] b, int offset, int length, int base)
300 throws NumberFormatException
301 {
302 int value=0;
303
304 if (length<0)
305 length=b.length-offset;
306
307 for (int i=0;i<length;i++)
308 {
309 char c=(char)(0xff&b[offset+i]);
310
311 int digit=c-'0';
312 if (digit<0 || digit>=base || digit>=10)
313 {
314 digit=10+c-'A';
315 if (digit<10 || digit>=base)
316 digit=10+c-'a';
317 }
318 if (digit<0 || digit>=base)
319 throw new NumberFormatException(new String(b,offset,length));
320 value=value*base+digit;
321 }
322 return value;
323 }
324
325
326 public static byte[] parseBytes(String s, int base)
327 {
328 byte[] bytes=new byte[s.length()/2];
329 for (int i=0;i<s.length();i+=2)
330 bytes[i/2]=(byte)TypeUtil.parseInt(s,i,2,base);
331 return bytes;
332 }
333
334
335 public static String toString(byte[] bytes, int base)
336 {
337 StringBuilder buf = new StringBuilder();
338 for (byte b : bytes)
339 {
340 int bi=0xff&b;
341 int c='0'+(bi/base)%base;
342 if (c>'9')
343 c= 'a'+(c-'0'-10);
344 buf.append((char)c);
345 c='0'+bi%base;
346 if (c>'9')
347 c= 'a'+(c-'0'-10);
348 buf.append((char)c);
349 }
350 return buf.toString();
351 }
352
353
354
355
356
357
358 public static byte convertHexDigit( byte c )
359 {
360 byte b = (byte)((c & 0x1f) + ((c >> 6) * 0x19) - 0x10);
361 if (b<0 || b>15)
362 throw new IllegalArgumentException("!hex "+c);
363 return b;
364 }
365
366
367
368
369
370
371 public static int convertHexDigit( int c )
372 {
373 int d= ((c & 0x1f) + ((c >> 6) * 0x19) - 0x10);
374 if (d<0 || d>15)
375 throw new NumberFormatException("!hex "+c);
376 return d;
377 }
378
379
380 public static void toHex(byte b,Appendable buf)
381 {
382 try
383 {
384 int d=0xf&((0xF0&b)>>4);
385 buf.append((char)((d>9?('A'-10):'0')+d));
386 d=0xf&b;
387 buf.append((char)((d>9?('A'-10):'0')+d));
388 }
389 catch(IOException e)
390 {
391 throw new RuntimeException(e);
392 }
393 }
394
395
396 public static void toHex(int value,Appendable buf) throws IOException
397 {
398 int d=0xf&((0xF0000000&value)>>28);
399 buf.append((char)((d>9?('A'-10):'0')+d));
400 d=0xf&((0x0F000000&value)>>24);
401 buf.append((char)((d>9?('A'-10):'0')+d));
402 d=0xf&((0x00F00000&value)>>20);
403 buf.append((char)((d>9?('A'-10):'0')+d));
404 d=0xf&((0x000F0000&value)>>16);
405 buf.append((char)((d>9?('A'-10):'0')+d));
406 d=0xf&((0x0000F000&value)>>12);
407 buf.append((char)((d>9?('A'-10):'0')+d));
408 d=0xf&((0x00000F00&value)>>8);
409 buf.append((char)((d>9?('A'-10):'0')+d));
410 d=0xf&((0x000000F0&value)>>4);
411 buf.append((char)((d>9?('A'-10):'0')+d));
412 d=0xf&value;
413 buf.append((char)((d>9?('A'-10):'0')+d));
414
415 Integer.toString(0,36);
416 }
417
418
419
420 public static void toHex(long value,Appendable buf) throws IOException
421 {
422 toHex((int)(value>>32),buf);
423 toHex((int)value,buf);
424 }
425
426
427 public static String toHexString(byte b)
428 {
429 return toHexString(new byte[]{b}, 0, 1);
430 }
431
432
433 public static String toHexString(byte[] b)
434 {
435 return toHexString(b, 0, b.length);
436 }
437
438
439 public static String toHexString(byte[] b,int offset,int length)
440 {
441 StringBuilder buf = new StringBuilder();
442 for (int i=offset;i<offset+length;i++)
443 {
444 int bi=0xff&b[i];
445 int c='0'+(bi/16)%16;
446 if (c>'9')
447 c= 'A'+(c-'0'-10);
448 buf.append((char)c);
449 c='0'+bi%16;
450 if (c>'9')
451 c= 'a'+(c-'0'-10);
452 buf.append((char)c);
453 }
454 return buf.toString();
455 }
456
457
458 public static byte[] fromHexString(String s)
459 {
460 if (s.length()%2!=0)
461 throw new IllegalArgumentException(s);
462 byte[] array = new byte[s.length()/2];
463 for (int i=0;i<array.length;i++)
464 {
465 int b = Integer.parseInt(s.substring(i*2,i*2+2),16);
466 array[i]=(byte)(0xff&b);
467 }
468 return array;
469 }
470
471
472 public static void dump(Class<?> c)
473 {
474 System.err.println("Dump: "+c);
475 dump(c.getClassLoader());
476 }
477
478 public static void dump(ClassLoader cl)
479 {
480 System.err.println("Dump Loaders:");
481 while(cl!=null)
482 {
483 System.err.println(" loader "+cl);
484 cl = cl.getParent();
485 }
486 }
487
488
489
490 public static byte[] readLine(InputStream in) throws IOException
491 {
492 byte[] buf = new byte[256];
493
494 int i=0;
495 int loops=0;
496 int ch=0;
497
498 while (true)
499 {
500 ch=in.read();
501 if (ch<0)
502 break;
503 loops++;
504
505
506 if (loops==1 && ch==LF)
507 continue;
508
509 if (ch==CR || ch==LF)
510 break;
511
512 if (i>=buf.length)
513 {
514 byte[] old_buf=buf;
515 buf=new byte[old_buf.length+256];
516 System.arraycopy(old_buf, 0, buf, 0, old_buf.length);
517 }
518 buf[i++]=(byte)ch;
519 }
520
521 if (ch==-1 && i==0)
522 return null;
523
524
525 if (ch==CR && in.available()>=1 && in.markSupported())
526 {
527 in.mark(1);
528 ch=in.read();
529 if (ch!=LF)
530 in.reset();
531 }
532
533 byte[] old_buf=buf;
534 buf=new byte[i];
535 System.arraycopy(old_buf, 0, buf, 0, i);
536
537 return buf;
538 }
539
540 public static URL jarFor(String className)
541 {
542 try
543 {
544 className=className.replace('.','/')+".class";
545
546 URL url = Loader.getResource(null,className,false);
547 String s=url.toString();
548 if (s.startsWith("jar:file:"))
549 return new URL(s.substring(4,s.indexOf("!/")));
550 }
551 catch(Exception e)
552 {
553 LOG.ignore(e);
554 }
555 return null;
556 }
557
558 public static Object call(Class<?> oClass, String method, Object obj, Object[] arg)
559 throws InvocationTargetException, NoSuchMethodException
560 {
561
562 Method[] methods = oClass.getMethods();
563 for (int c = 0; methods != null && c < methods.length; c++)
564 {
565 if (!methods[c].getName().equals(method))
566 continue;
567 if (methods[c].getParameterTypes().length != arg.length)
568 continue;
569 if (Modifier.isStatic(methods[c].getModifiers()) != (obj == null))
570 continue;
571 if ((obj == null) && methods[c].getDeclaringClass() != oClass)
572 continue;
573
574 try
575 {
576 return methods[c].invoke(obj,arg);
577 }
578 catch (IllegalAccessException e)
579 {
580 LOG.ignore(e);
581 }
582 catch (IllegalArgumentException e)
583 {
584 LOG.ignore(e);
585 }
586 }
587
588 throw new NoSuchMethodException(method);
589 }
590 }