View Javadoc

1   // ========================================================================
2   // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd.
3   // ------------------------------------------------------------------------
4   // All rights reserved. This program and the accompanying materials
5   // are made available under the terms of the Eclipse Public License v1.0
6   // and Apache License v2.0 which accompanies this distribution.
7   // The Eclipse Public License is available at 
8   // http://www.eclipse.org/legal/epl-v10.html
9   // The Apache License v2.0 is available at
10  // http://www.opensource.org/licenses/apache2.0.php
11  // You may elect to redistribute this code under either of these licenses. 
12  // ========================================================================
13  
14  package org.eclipse.jetty.util;
15  
16  import java.io.IOException;
17  import java.io.InputStream;
18  import java.lang.reflect.Constructor;
19  import java.lang.reflect.InvocationTargetException;
20  import java.lang.reflect.Method;
21  import java.net.URL;
22  import java.util.HashMap;
23  
24  import org.eclipse.jetty.util.log.Log;
25  
26  
27  /* ------------------------------------------------------------ */
28  /** TYPE Utilities.
29   * Provides various static utiltiy methods for manipulating types and their
30   * string representations.
31   *
32   * @since Jetty 4.1
33   * 
34   */
35  public class TypeUtil
36  {
37      public static int CR = '\015';
38      public static int LF = '\012';
39      
40      /* ------------------------------------------------------------ */
41      private static final HashMap name2Class=new HashMap();
42      static
43      {
44          name2Class.put("boolean",java.lang.Boolean.TYPE);
45          name2Class.put("byte",java.lang.Byte.TYPE);
46          name2Class.put("char",java.lang.Character.TYPE);
47          name2Class.put("double",java.lang.Double.TYPE);
48          name2Class.put("float",java.lang.Float.TYPE);
49          name2Class.put("int",java.lang.Integer.TYPE);
50          name2Class.put("long",java.lang.Long.TYPE);
51          name2Class.put("short",java.lang.Short.TYPE);
52          name2Class.put("void",java.lang.Void.TYPE);
53          
54          name2Class.put("java.lang.Boolean.TYPE",java.lang.Boolean.TYPE);
55          name2Class.put("java.lang.Byte.TYPE",java.lang.Byte.TYPE);
56          name2Class.put("java.lang.Character.TYPE",java.lang.Character.TYPE);
57          name2Class.put("java.lang.Double.TYPE",java.lang.Double.TYPE);
58          name2Class.put("java.lang.Float.TYPE",java.lang.Float.TYPE);
59          name2Class.put("java.lang.Integer.TYPE",java.lang.Integer.TYPE);
60          name2Class.put("java.lang.Long.TYPE",java.lang.Long.TYPE);
61          name2Class.put("java.lang.Short.TYPE",java.lang.Short.TYPE);
62          name2Class.put("java.lang.Void.TYPE",java.lang.Void.TYPE);
63  
64          name2Class.put("java.lang.Boolean",java.lang.Boolean.class);
65          name2Class.put("java.lang.Byte",java.lang.Byte.class);
66          name2Class.put("java.lang.Character",java.lang.Character.class);
67          name2Class.put("java.lang.Double",java.lang.Double.class);
68          name2Class.put("java.lang.Float",java.lang.Float.class);
69          name2Class.put("java.lang.Integer",java.lang.Integer.class);
70          name2Class.put("java.lang.Long",java.lang.Long.class);
71          name2Class.put("java.lang.Short",java.lang.Short.class);
72  
73          name2Class.put("Boolean",java.lang.Boolean.class);
74          name2Class.put("Byte",java.lang.Byte.class);
75          name2Class.put("Character",java.lang.Character.class);
76          name2Class.put("Double",java.lang.Double.class);
77          name2Class.put("Float",java.lang.Float.class);
78          name2Class.put("Integer",java.lang.Integer.class);
79          name2Class.put("Long",java.lang.Long.class);
80          name2Class.put("Short",java.lang.Short.class);
81  
82          name2Class.put(null,java.lang.Void.TYPE);
83          name2Class.put("string",java.lang.String.class);
84          name2Class.put("String",java.lang.String.class);
85          name2Class.put("java.lang.String",java.lang.String.class);
86      }
87      
88      /* ------------------------------------------------------------ */
89      private static final HashMap class2Name=new HashMap();
90      static
91      {
92          class2Name.put(java.lang.Boolean.TYPE,"boolean");
93          class2Name.put(java.lang.Byte.TYPE,"byte");
94          class2Name.put(java.lang.Character.TYPE,"char");
95          class2Name.put(java.lang.Double.TYPE,"double");
96          class2Name.put(java.lang.Float.TYPE,"float");
97          class2Name.put(java.lang.Integer.TYPE,"int");
98          class2Name.put(java.lang.Long.TYPE,"long");
99          class2Name.put(java.lang.Short.TYPE,"short");
100         class2Name.put(java.lang.Void.TYPE,"void");
101 
102         class2Name.put(java.lang.Boolean.class,"java.lang.Boolean");
103         class2Name.put(java.lang.Byte.class,"java.lang.Byte");
104         class2Name.put(java.lang.Character.class,"java.lang.Character");
105         class2Name.put(java.lang.Double.class,"java.lang.Double");
106         class2Name.put(java.lang.Float.class,"java.lang.Float");
107         class2Name.put(java.lang.Integer.class,"java.lang.Integer");
108         class2Name.put(java.lang.Long.class,"java.lang.Long");
109         class2Name.put(java.lang.Short.class,"java.lang.Short");
110         
111         class2Name.put(null,"void");
112         class2Name.put(java.lang.String.class,"java.lang.String");
113     }
114     
115     /* ------------------------------------------------------------ */
116     private static final HashMap class2Value=new HashMap();
117     static
118     {
119         try
120         {
121             Class[] s ={java.lang.String.class};
122             
123             class2Value.put(java.lang.Boolean.TYPE,
124                            java.lang.Boolean.class.getMethod("valueOf",s));
125             class2Value.put(java.lang.Byte.TYPE,
126                            java.lang.Byte.class.getMethod("valueOf",s));
127             class2Value.put(java.lang.Double.TYPE,
128                            java.lang.Double.class.getMethod("valueOf",s));
129             class2Value.put(java.lang.Float.TYPE,
130                            java.lang.Float.class.getMethod("valueOf",s));
131             class2Value.put(java.lang.Integer.TYPE,
132                            java.lang.Integer.class.getMethod("valueOf",s));
133             class2Value.put(java.lang.Long.TYPE,
134                            java.lang.Long.class.getMethod("valueOf",s));
135             class2Value.put(java.lang.Short.TYPE,
136                            java.lang.Short.class.getMethod("valueOf",s));
137 
138             class2Value.put(java.lang.Boolean.class,
139                            java.lang.Boolean.class.getMethod("valueOf",s));
140             class2Value.put(java.lang.Byte.class,
141                            java.lang.Byte.class.getMethod("valueOf",s));
142             class2Value.put(java.lang.Double.class,
143                            java.lang.Double.class.getMethod("valueOf",s));
144             class2Value.put(java.lang.Float.class,
145                            java.lang.Float.class.getMethod("valueOf",s));
146             class2Value.put(java.lang.Integer.class,
147                            java.lang.Integer.class.getMethod("valueOf",s));
148             class2Value.put(java.lang.Long.class,
149                            java.lang.Long.class.getMethod("valueOf",s));
150             class2Value.put(java.lang.Short.class,
151                            java.lang.Short.class.getMethod("valueOf",s));
152         }
153         catch(Exception e)
154         {
155             e.printStackTrace();
156         }
157     }
158 
159     /* ------------------------------------------------------------ */
160     private static Class[] stringArg = { java.lang.String.class };
161     
162     /* ------------------------------------------------------------ */
163     private static int intCacheSize=
164         Integer.getInteger("org.eclipse.jetty.util.TypeUtil.IntegerCacheSize",600).intValue();
165     private static Integer[] integerCache = new Integer[intCacheSize];
166     private static String[] integerStrCache = new String[intCacheSize];
167     private static Integer minusOne = new Integer(-1);
168     private static int longCacheSize=
169         Integer.getInteger("org.eclipse.jetty.util.TypeUtil.LongCacheSize",64).intValue();
170     private static Long[] longCache = new Long[longCacheSize];
171     private static Long minusOneL = new Long(-1);
172     
173     /* ------------------------------------------------------------ */
174     /** Class from a canonical name for a type.
175      * @param name A class or type name.
176      * @return A class , which may be a primitive TYPE field..
177      */
178     public static Class fromName(String name)
179     {
180         return (Class)name2Class.get(name);
181     }
182     
183     /* ------------------------------------------------------------ */
184     /** Canonical name for a type.
185      * @param type A class , which may be a primitive TYPE field.
186      * @return Canonical name.
187      */
188     public static String toName(Class type)
189     {
190         return (String)class2Name.get(type);
191     }
192     
193     /* ------------------------------------------------------------ */
194     /** Convert String value to instance.
195      * @param type The class of the instance, which may be a primitive TYPE field.
196      * @param value The value as a string.
197      * @return The value as an Object.
198      */
199     public static Object valueOf(Class type, String value)
200     {
201         try
202         {
203             if (type.equals(java.lang.String.class))
204                 return value;
205             
206             Method m = (Method)class2Value.get(type);
207             if (m!=null)
208                 return m.invoke(null,new Object[] {value});
209 
210             if (type.equals(java.lang.Character.TYPE) ||
211                 type.equals(java.lang.Character.class))
212                 return new Character(value.charAt(0));
213 
214             Constructor c = type.getConstructor(stringArg);
215             return c.newInstance(new Object[] {value});   
216         }
217         catch(NoSuchMethodException e)
218         {
219             // LogSupport.ignore(log,e);
220         }
221         catch(IllegalAccessException e)
222         {
223             // LogSupport.ignore(log,e);
224         }
225         catch(InstantiationException e)
226         {
227             // LogSupport.ignore(log,e);
228         }
229         catch(InvocationTargetException e)
230         {
231             if (e.getTargetException() instanceof Error)
232                 throw (Error)(e.getTargetException());
233             // LogSupport.ignore(log,e);
234         }
235         return null;
236     }
237     
238     /* ------------------------------------------------------------ */
239     /** Convert String value to instance.
240      * @param type classname or type (eg int)
241      * @param value The value as a string.
242      * @return The value as an Object.
243      */
244     public static Object valueOf(String type, String value)
245     {
246         return valueOf(fromName(type),value);
247     }
248     
249     /* ------------------------------------------------------------ */
250     /** Convert int to Integer using cache. 
251      */
252     public static Integer newInteger(int i)
253     {
254         if (i>=0 && i<intCacheSize)
255         {
256             if (integerCache[i]==null)
257                 integerCache[i]=new Integer(i);
258             return integerCache[i];
259         }
260         else if (i==-1)
261             return minusOne;
262         return new Integer(i);
263     }
264     
265     /* ------------------------------------------------------------ */
266     /** Convert int to Integer using cache. 
267      */
268     public static Long newLong(long i)
269     {
270         if (i>=0 && i<longCacheSize)
271         {
272             if (longCache[(int)i]==null)
273                 longCache[(int)i]=new Long(i);
274             return longCache[(int)i];
275         }
276         else if (i==-1)
277             return minusOneL;
278         return new Long(i);
279     }
280 
281     
282     /* ------------------------------------------------------------ */
283     /** Convert int to String using cache. 
284      */
285     public static String toString(int i)
286     {
287         if (i>=0 && i<intCacheSize)
288         {
289             if (integerStrCache[i]==null)
290                 integerStrCache[i]=Integer.toString(i);
291             return integerStrCache[i];
292         }
293         else if (i==-1)
294             return "-1";
295         return Integer.toString(i);
296     }
297     
298     /* ------------------------------------------------------------ */
299     /** Convert long to String using cache. 
300      */
301     public static String toString(long i)
302     {
303         if (i>=0 && i<intCacheSize)
304         {
305             if (integerStrCache[(int)i]==null)
306                 integerStrCache[(int)i]=Long.toString(i);
307             return integerStrCache[(int)i];
308         }
309         else if (i==-1)
310             return "-1";
311         return Long.toString(i);
312     }
313 
314 
315     /* ------------------------------------------------------------ */
316     /** Parse an int from a substring.
317      * Negative numbers are not handled.
318      * @param s String
319      * @param offset Offset within string
320      * @param length Length of integer or -1 for remainder of string
321      * @param base base of the integer
322      * @exception NumberFormatException 
323      */
324     public static int parseInt(String s, int offset, int length, int base)
325         throws NumberFormatException
326     {
327         int value=0;
328 
329         if (length<0)
330             length=s.length()-offset;
331 
332         for (int i=0;i<length;i++)
333         {
334             char c=s.charAt(offset+i);
335             
336             int digit=c-'0';
337             if (digit<0 || digit>=base || digit>=10)
338             {
339                 digit=10+c-'A';
340                 if (digit<10 || digit>=base)
341                     digit=10+c-'a';
342             }
343             if (digit<0 || digit>=base)
344                 throw new NumberFormatException(s.substring(offset,offset+length));
345             value=value*base+digit;
346         }
347         return value;
348     }
349 
350     /* ------------------------------------------------------------ */
351     /** Parse an int from a byte array of ascii characters.
352      * Negative numbers are not handled.
353      * @param b byte array
354      * @param offset Offset within string
355      * @param length Length of integer or -1 for remainder of string
356      * @param base base of the integer
357      * @exception NumberFormatException 
358      */
359     public static int parseInt(byte[] b, int offset, int length, int base)
360         throws NumberFormatException
361     {
362         int value=0;
363 
364         if (length<0)
365             length=b.length-offset;
366 
367         for (int i=0;i<length;i++)
368         {
369             char c=(char)(0xff&b[offset+i]);
370             
371             int digit=c-'0';
372             if (digit<0 || digit>=base || digit>=10)
373             {
374                 digit=10+c-'A';
375                 if (digit<10 || digit>=base)
376                     digit=10+c-'a';
377             }
378             if (digit<0 || digit>=base)
379                 throw new NumberFormatException(new String(b,offset,length));
380             value=value*base+digit;
381         }
382         return value;
383     }
384 
385     /* ------------------------------------------------------------ */
386     public static byte[] parseBytes(String s, int base)
387     {
388         byte[] bytes=new byte[s.length()/2];
389         for (int i=0;i<s.length();i+=2)
390             bytes[i/2]=(byte)TypeUtil.parseInt(s,i,2,base);
391         return bytes;
392     }
393 
394     /* ------------------------------------------------------------ */
395     public static String toString(byte[] bytes, int base)
396     {
397         StringBuilder buf = new StringBuilder();
398         for (int i=0;i<bytes.length;i++)
399         {
400             int bi=0xff&bytes[i];
401             int c='0'+(bi/base)%base;
402             if (c>'9')
403                 c= 'a'+(c-'0'-10);
404             buf.append((char)c);
405             c='0'+bi%base;
406             if (c>'9')
407                 c= 'a'+(c-'0'-10);
408             buf.append((char)c);
409         }
410         return buf.toString();
411     }
412 
413     /* ------------------------------------------------------------ */
414     /** 
415      * @param b An ASCII encoded character 0-9 a-f A-F
416      * @return The byte value of the character 0-16.
417      */
418     public static byte convertHexDigit( byte b )
419     {
420         if ((b >= '0') && (b <= '9')) return (byte)(b - '0');
421         if ((b >= 'a') && (b <= 'f')) return (byte)(b - 'a' + 10);
422         if ((b >= 'A') && (b <= 'F')) return (byte)(b - 'A' + 10);
423         return 0;
424     }
425 
426     /* ------------------------------------------------------------ */
427     public static String toHexString(byte[] b)
428     {   
429         StringBuilder buf = new StringBuilder();
430         for (int i=0;i<b.length;i++)
431         {
432             int bi=0xff&b[i];
433             int c='0'+(bi/16)%16;
434             if (c>'9')
435                 c= 'A'+(c-'0'-10);
436             buf.append((char)c);
437             c='0'+bi%16;
438             if (c>'9')
439                 c= 'a'+(c-'0'-10);
440             buf.append((char)c);
441         }
442         return buf.toString();
443     }
444     
445     /* ------------------------------------------------------------ */
446     public static String toHexString(byte[] b,int offset,int length)
447     {   
448         StringBuilder buf = new StringBuilder();
449         for (int i=offset;i<offset+length;i++)
450         {
451             int bi=0xff&b[i];
452             int c='0'+(bi/16)%16;
453             if (c>'9')
454                 c= 'A'+(c-'0'-10);
455             buf.append((char)c);
456             c='0'+bi%16;
457             if (c>'9')
458                 c= 'a'+(c-'0'-10);
459             buf.append((char)c);
460         }
461         return buf.toString();
462     }
463     
464     /* ------------------------------------------------------------ */
465     public static byte[] fromHexString(String s)
466     {   
467         if (s.length()%2!=0)
468             throw new IllegalArgumentException(s);
469         byte[] array = new byte[s.length()/2];
470         for (int i=0;i<array.length;i++)
471         {
472             int b = Integer.parseInt(s.substring(i*2,i*2+2),16);
473             array[i]=(byte)(0xff&b);
474         }    
475         return array;
476     }
477     
478 
479     public static void dump(Class c)
480     {
481         System.err.println("Dump: "+c);
482         dump(c.getClassLoader());
483     }
484 
485     public static void dump(ClassLoader cl)
486     {
487         System.err.println("Dump Loaders:");
488         while(cl!=null)
489         {
490             System.err.println("  loader "+cl);
491             cl = cl.getParent();
492         }
493     }
494     
495 
496     /* ------------------------------------------------------------ */
497     public static byte[] readLine(InputStream in) throws IOException
498     {
499         byte[] buf = new byte[256];
500         
501         int i=0;
502         int loops=0;
503         int ch=0;
504         
505         while (true)
506         {
507             ch=in.read();
508             if (ch<0)
509                 break;
510             loops++;
511             
512             // skip a leading LF's
513             if (loops==1 && ch==LF)
514                 continue;
515             
516             if (ch==CR || ch==LF)
517                 break;
518             
519             if (i>=buf.length)
520             {
521                 byte[] old_buf=buf;
522                 buf=new byte[old_buf.length+256];
523                 System.arraycopy(old_buf, 0, buf, 0, old_buf.length);
524             }
525             buf[i++]=(byte)ch;
526         }
527         
528         if (ch==-1 && i==0)
529             return null;
530         
531         // skip a trailing LF if it exists
532         if (ch==CR && in.available()>=1 && in.markSupported())
533         {
534             in.mark(1);
535             ch=in.read();
536             if (ch!=LF)
537                 in.reset();
538         }
539 
540         byte[] old_buf=buf;
541         buf=new byte[i];
542         System.arraycopy(old_buf, 0, buf, 0, i);
543         
544         return buf;
545     }
546     
547     public static URL jarFor(String className)
548     {
549         try
550         {
551             className=className.replace('.','/')+".class";
552             // hack to discover jstl libraries
553             URL url = Loader.getResource(null,className,false);
554             String s=url.toString();
555             if (s.startsWith("jar:file:"))
556                 return new URL(s.substring(4,s.indexOf("!/")));
557         }
558         catch(Exception e)
559         {
560             Log.ignore(e);
561         }
562         return null;
563     }
564 }