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 = 600;
164     private static Integer[] integerCache = new Integer[intCacheSize];
165     private static String[] integerStrCache = new String[intCacheSize];
166     private static Integer minusOne = new Integer(-1);
167     private static int longCacheSize = 64;
168     private static Long[] longCache = new Long[longCacheSize];
169     private static Long minusOneL = new Long(-1);
170     
171     public static void setIntCacheSize(int size)
172     {
173         if (size > intCacheSize) {
174             Integer[] intCache = new Integer[size];
175             System.arraycopy(integerCache,0,intCache,0,intCacheSize);
176             
177             String [] strCache = new String[size];
178             System.arraycopy(integerStrCache,0,strCache,0,intCacheSize);
179             
180             intCacheSize = size;
181             integerCache = intCache;
182             integerStrCache = strCache;
183         }
184     }
185     
186     public static void setLongCacheSize(int size)
187     {
188         if (size > longCacheSize) {
189             Long[] lnCache = new Long[size];
190             System.arraycopy(longCache,0,lnCache,0,longCacheSize);
191             
192             longCacheSize = size;
193             longCache = lnCache;
194         }
195     }
196 
197     /* ------------------------------------------------------------ */
198     /** Class from a canonical name for a type.
199      * @param name A class or type name.
200      * @return A class , which may be a primitive TYPE field..
201      */
202     public static Class fromName(String name)
203     {
204         return (Class)name2Class.get(name);
205     }
206     
207     /* ------------------------------------------------------------ */
208     /** Canonical name for a type.
209      * @param type A class , which may be a primitive TYPE field.
210      * @return Canonical name.
211      */
212     public static String toName(Class type)
213     {
214         return (String)class2Name.get(type);
215     }
216     
217     /* ------------------------------------------------------------ */
218     /** Convert String value to instance.
219      * @param type The class of the instance, which may be a primitive TYPE field.
220      * @param value The value as a string.
221      * @return The value as an Object.
222      */
223     public static Object valueOf(Class type, String value)
224     {
225         try
226         {
227             if (type.equals(java.lang.String.class))
228                 return value;
229             
230             Method m = (Method)class2Value.get(type);
231             if (m!=null)
232                 return m.invoke(null,new Object[] {value});
233 
234             if (type.equals(java.lang.Character.TYPE) ||
235                 type.equals(java.lang.Character.class))
236                 return new Character(value.charAt(0));
237 
238             Constructor c = type.getConstructor(stringArg);
239             return c.newInstance(new Object[] {value});   
240         }
241         catch(NoSuchMethodException e)
242         {
243             // LogSupport.ignore(log,e);
244         }
245         catch(IllegalAccessException e)
246         {
247             // LogSupport.ignore(log,e);
248         }
249         catch(InstantiationException e)
250         {
251             // LogSupport.ignore(log,e);
252         }
253         catch(InvocationTargetException e)
254         {
255             if (e.getTargetException() instanceof Error)
256                 throw (Error)(e.getTargetException());
257             // LogSupport.ignore(log,e);
258         }
259         return null;
260     }
261     
262     /* ------------------------------------------------------------ */
263     /** Convert String value to instance.
264      * @param type classname or type (eg int)
265      * @param value The value as a string.
266      * @return The value as an Object.
267      */
268     public static Object valueOf(String type, String value)
269     {
270         return valueOf(fromName(type),value);
271     }
272     
273     /* ------------------------------------------------------------ */
274     /** Convert int to Integer using cache. 
275      */
276     public static Integer newInteger(int i)
277     {
278         if (i>=0 && i<intCacheSize)
279         {
280             if (integerCache[i]==null)
281                 integerCache[i]=new Integer(i);
282             return integerCache[i];
283         }
284         else if (i==-1)
285             return minusOne;
286         return new Integer(i);
287     }
288     
289     /* ------------------------------------------------------------ */
290     /** Convert int to Integer using cache. 
291      */
292     public static Long newLong(long i)
293     {
294         if (i>=0 && i<longCacheSize)
295         {
296             if (longCache[(int)i]==null)
297                 longCache[(int)i]=new Long(i);
298             return longCache[(int)i];
299         }
300         else if (i==-1)
301             return minusOneL;
302         return new Long(i);
303     }
304 
305     
306     /* ------------------------------------------------------------ */
307     /** Convert int to String using cache. 
308      */
309     public static String toString(int i)
310     {
311         if (i>=0 && i<intCacheSize)
312         {
313             if (integerStrCache[i]==null)
314                 integerStrCache[i]=Integer.toString(i);
315             return integerStrCache[i];
316         }
317         else if (i==-1)
318             return "-1";
319         return Integer.toString(i);
320     }
321     
322     /* ------------------------------------------------------------ */
323     /** Convert long to String using cache. 
324      */
325     public static String toString(long i)
326     {
327         if (i>=0 && i<intCacheSize)
328         {
329             if (integerStrCache[(int)i]==null)
330                 integerStrCache[(int)i]=Long.toString(i);
331             return integerStrCache[(int)i];
332         }
333         else if (i==-1)
334             return "-1";
335         return Long.toString(i);
336     }
337 
338 
339     /* ------------------------------------------------------------ */
340     /** Parse an int from a substring.
341      * Negative numbers are not handled.
342      * @param s String
343      * @param offset Offset within string
344      * @param length Length of integer or -1 for remainder of string
345      * @param base base of the integer
346      * @exception NumberFormatException 
347      */
348     public static int parseInt(String s, int offset, int length, int base)
349         throws NumberFormatException
350     {
351         int value=0;
352 
353         if (length<0)
354             length=s.length()-offset;
355 
356         for (int i=0;i<length;i++)
357         {
358             char c=s.charAt(offset+i);
359             
360             int digit=c-'0';
361             if (digit<0 || digit>=base || digit>=10)
362             {
363                 digit=10+c-'A';
364                 if (digit<10 || digit>=base)
365                     digit=10+c-'a';
366             }
367             if (digit<0 || digit>=base)
368                 throw new NumberFormatException(s.substring(offset,offset+length));
369             value=value*base+digit;
370         }
371         return value;
372     }
373 
374     /* ------------------------------------------------------------ */
375     /** Parse an int from a byte array of ascii characters.
376      * Negative numbers are not handled.
377      * @param b byte array
378      * @param offset Offset within string
379      * @param length Length of integer or -1 for remainder of string
380      * @param base base of the integer
381      * @exception NumberFormatException 
382      */
383     public static int parseInt(byte[] b, int offset, int length, int base)
384         throws NumberFormatException
385     {
386         int value=0;
387 
388         if (length<0)
389             length=b.length-offset;
390 
391         for (int i=0;i<length;i++)
392         {
393             char c=(char)(0xff&b[offset+i]);
394             
395             int digit=c-'0';
396             if (digit<0 || digit>=base || digit>=10)
397             {
398                 digit=10+c-'A';
399                 if (digit<10 || digit>=base)
400                     digit=10+c-'a';
401             }
402             if (digit<0 || digit>=base)
403                 throw new NumberFormatException(new String(b,offset,length));
404             value=value*base+digit;
405         }
406         return value;
407     }
408 
409     /* ------------------------------------------------------------ */
410     public static byte[] parseBytes(String s, int base)
411     {
412         byte[] bytes=new byte[s.length()/2];
413         for (int i=0;i<s.length();i+=2)
414             bytes[i/2]=(byte)TypeUtil.parseInt(s,i,2,base);
415         return bytes;
416     }
417 
418     /* ------------------------------------------------------------ */
419     public static String toString(byte[] bytes, int base)
420     {
421         StringBuilder buf = new StringBuilder();
422         for (int i=0;i<bytes.length;i++)
423         {
424             int bi=0xff&bytes[i];
425             int c='0'+(bi/base)%base;
426             if (c>'9')
427                 c= 'a'+(c-'0'-10);
428             buf.append((char)c);
429             c='0'+bi%base;
430             if (c>'9')
431                 c= 'a'+(c-'0'-10);
432             buf.append((char)c);
433         }
434         return buf.toString();
435     }
436 
437     /* ------------------------------------------------------------ */
438     /** 
439      * @param b An ASCII encoded character 0-9 a-f A-F
440      * @return The byte value of the character 0-16.
441      */
442     public static byte convertHexDigit( byte b )
443     {
444         if ((b >= '0') && (b <= '9')) return (byte)(b - '0');
445         if ((b >= 'a') && (b <= 'f')) return (byte)(b - 'a' + 10);
446         if ((b >= 'A') && (b <= 'F')) return (byte)(b - 'A' + 10);
447         return 0;
448     }
449 
450     /* ------------------------------------------------------------ */
451     public static String toHexString(byte[] b)
452     {   
453         StringBuilder buf = new StringBuilder();
454         for (int i=0;i<b.length;i++)
455         {
456             int bi=0xff&b[i];
457             int c='0'+(bi/16)%16;
458             if (c>'9')
459                 c= 'A'+(c-'0'-10);
460             buf.append((char)c);
461             c='0'+bi%16;
462             if (c>'9')
463                 c= 'a'+(c-'0'-10);
464             buf.append((char)c);
465         }
466         return buf.toString();
467     }
468     
469     /* ------------------------------------------------------------ */
470     public static String toHexString(byte[] b,int offset,int length)
471     {   
472         StringBuilder buf = new StringBuilder();
473         for (int i=offset;i<offset+length;i++)
474         {
475             int bi=0xff&b[i];
476             int c='0'+(bi/16)%16;
477             if (c>'9')
478                 c= 'A'+(c-'0'-10);
479             buf.append((char)c);
480             c='0'+bi%16;
481             if (c>'9')
482                 c= 'a'+(c-'0'-10);
483             buf.append((char)c);
484         }
485         return buf.toString();
486     }
487     
488     /* ------------------------------------------------------------ */
489     public static byte[] fromHexString(String s)
490     {   
491         if (s.length()%2!=0)
492             throw new IllegalArgumentException(s);
493         byte[] array = new byte[s.length()/2];
494         for (int i=0;i<array.length;i++)
495         {
496             int b = Integer.parseInt(s.substring(i*2,i*2+2),16);
497             array[i]=(byte)(0xff&b);
498         }    
499         return array;
500     }
501     
502 
503     public static void dump(Class c)
504     {
505         System.err.println("Dump: "+c);
506         dump(c.getClassLoader());
507     }
508 
509     public static void dump(ClassLoader cl)
510     {
511         System.err.println("Dump Loaders:");
512         while(cl!=null)
513         {
514             System.err.println("  loader "+cl);
515             cl = cl.getParent();
516         }
517     }
518     
519 
520     /* ------------------------------------------------------------ */
521     public static byte[] readLine(InputStream in) throws IOException
522     {
523         byte[] buf = new byte[256];
524         
525         int i=0;
526         int loops=0;
527         int ch=0;
528         
529         while (true)
530         {
531             ch=in.read();
532             if (ch<0)
533                 break;
534             loops++;
535             
536             // skip a leading LF's
537             if (loops==1 && ch==LF)
538                 continue;
539             
540             if (ch==CR || ch==LF)
541                 break;
542             
543             if (i>=buf.length)
544             {
545                 byte[] old_buf=buf;
546                 buf=new byte[old_buf.length+256];
547                 System.arraycopy(old_buf, 0, buf, 0, old_buf.length);
548             }
549             buf[i++]=(byte)ch;
550         }
551         
552         if (ch==-1 && i==0)
553             return null;
554         
555         // skip a trailing LF if it exists
556         if (ch==CR && in.available()>=1 && in.markSupported())
557         {
558             in.mark(1);
559             ch=in.read();
560             if (ch!=LF)
561                 in.reset();
562         }
563 
564         byte[] old_buf=buf;
565         buf=new byte[i];
566         System.arraycopy(old_buf, 0, buf, 0, i);
567         
568         return buf;
569     }
570     
571     public static URL jarFor(String className)
572     {
573         try
574         {
575             className=className.replace('.','/')+".class";
576             // hack to discover jstl libraries
577             URL url = Loader.getResource(null,className,false);
578             String s=url.toString();
579             if (s.startsWith("jar:file:"))
580                 return new URL(s.substring(4,s.indexOf("!/")));
581         }
582         catch(Exception e)
583         {
584             Log.ignore(e);
585         }
586         return null;
587     }
588 }