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  /**
29   * TYPE Utilities.
30   * Provides various static utiltiy methods for manipulating types and their
31   * string representations.
32   *
33   * @since Jetty 4.1
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<String, Class> name2Class=new HashMap<String, Class>();
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<Class, String> class2Name=new HashMap<Class, String>();
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<Class, Method> class2Value=new HashMap<Class, Method>();
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     /** Class from a canonical name for a type.
161      * @param name A class or type name.
162      * @return A class , which may be a primitive TYPE field..
163      */
164     public static Class fromName(String name)
165     {
166         return name2Class.get(name);
167     }
168 
169     /* ------------------------------------------------------------ */
170     /** Canonical name for a type.
171      * @param type A class , which may be a primitive TYPE field.
172      * @return Canonical name.
173      */
174     public static String toName(Class type)
175     {
176         return class2Name.get(type);
177     }
178 
179     /* ------------------------------------------------------------ */
180     /** Convert String value to instance.
181      * @param type The class of the instance, which may be a primitive TYPE field.
182      * @param value The value as a string.
183      * @return The value as an Object.
184      */
185     public static Object valueOf(Class type, String value)
186     {
187         try
188         {
189             if (type.equals(java.lang.String.class))
190                 return value;
191 
192             Method m = class2Value.get(type);
193             if (m!=null)
194                 return m.invoke(null, value);
195 
196             if (type.equals(java.lang.Character.TYPE) ||
197                 type.equals(java.lang.Character.class))
198                 return new Character(value.charAt(0));
199 
200             Constructor c = type.getConstructor(java.lang.String.class);
201             return c.newInstance(value);
202         }
203         catch(NoSuchMethodException e)
204         {
205             // LogSupport.ignore(log,e);
206         }
207         catch(IllegalAccessException e)
208         {
209             // LogSupport.ignore(log,e);
210         }
211         catch(InstantiationException e)
212         {
213             // LogSupport.ignore(log,e);
214         }
215         catch(InvocationTargetException e)
216         {
217             if (e.getTargetException() instanceof Error)
218                 throw (Error)(e.getTargetException());
219             // LogSupport.ignore(log,e);
220         }
221         return null;
222     }
223 
224     /* ------------------------------------------------------------ */
225     /** Convert String value to instance.
226      * @param type classname or type (eg int)
227      * @param value The value as a string.
228      * @return The value as an Object.
229      */
230     public static Object valueOf(String type, String value)
231     {
232         return valueOf(fromName(type),value);
233     }
234 
235     /* ------------------------------------------------------------ */
236     /** Parse an int from a substring.
237      * Negative numbers are not handled.
238      * @param s String
239      * @param offset Offset within string
240      * @param length Length of integer or -1 for remainder of string
241      * @param base base of the integer
242      * @return the parsed integer
243      * @throws NumberFormatException if the string cannot be parsed
244      */
245     public static int parseInt(String s, int offset, int length, int base)
246         throws NumberFormatException
247     {
248         int value=0;
249 
250         if (length<0)
251             length=s.length()-offset;
252 
253         for (int i=0;i<length;i++)
254         {
255             char c=s.charAt(offset+i);
256 
257             int digit=c-'0';
258             if (digit<0 || digit>=base || digit>=10)
259             {
260                 digit=10+c-'A';
261                 if (digit<10 || digit>=base)
262                     digit=10+c-'a';
263             }
264             if (digit<0 || digit>=base)
265                 throw new NumberFormatException(s.substring(offset,offset+length));
266             value=value*base+digit;
267         }
268         return value;
269     }
270 
271     /* ------------------------------------------------------------ */
272     /** Parse an int from a byte array of ascii characters.
273      * Negative numbers are not handled.
274      * @param b byte array
275      * @param offset Offset within string
276      * @param length Length of integer or -1 for remainder of string
277      * @param base base of the integer
278      * @return the parsed integer
279      * @throws NumberFormatException if the array cannot be parsed into an integer
280      */
281     public static int parseInt(byte[] b, int offset, int length, int base)
282         throws NumberFormatException
283     {
284         int value=0;
285 
286         if (length<0)
287             length=b.length-offset;
288 
289         for (int i=0;i<length;i++)
290         {
291             char c=(char)(0xff&b[offset+i]);
292 
293             int digit=c-'0';
294             if (digit<0 || digit>=base || digit>=10)
295             {
296                 digit=10+c-'A';
297                 if (digit<10 || digit>=base)
298                     digit=10+c-'a';
299             }
300             if (digit<0 || digit>=base)
301                 throw new NumberFormatException(new String(b,offset,length));
302             value=value*base+digit;
303         }
304         return value;
305     }
306 
307     /* ------------------------------------------------------------ */
308     public static byte[] parseBytes(String s, int base)
309     {
310         byte[] bytes=new byte[s.length()/2];
311         for (int i=0;i<s.length();i+=2)
312             bytes[i/2]=(byte)TypeUtil.parseInt(s,i,2,base);
313         return bytes;
314     }
315 
316     /* ------------------------------------------------------------ */
317     public static String toString(byte[] bytes, int base)
318     {
319         StringBuilder buf = new StringBuilder();
320         for (byte b : bytes)
321         {
322             int bi=0xff&b;
323             int c='0'+(bi/base)%base;
324             if (c>'9')
325                 c= 'a'+(c-'0'-10);
326             buf.append((char)c);
327             c='0'+bi%base;
328             if (c>'9')
329                 c= 'a'+(c-'0'-10);
330             buf.append((char)c);
331         }
332         return buf.toString();
333     }
334 
335     /* ------------------------------------------------------------ */
336     /**
337      * @param b An ASCII encoded character 0-9 a-f A-F
338      * @return The byte value of the character 0-16.
339      */
340     public static byte convertHexDigit( byte b )
341     {
342         if ((b >= '0') && (b <= '9')) return (byte)(b - '0');
343         if ((b >= 'a') && (b <= 'f')) return (byte)(b - 'a' + 10);
344         if ((b >= 'A') && (b <= 'F')) return (byte)(b - 'A' + 10);
345         return 0;
346     }
347 
348     /* ------------------------------------------------------------ */
349     public static void toHex(byte b,Appendable buf)
350     {
351         try
352         {
353             int bi=0xff&b;
354             int c='0'+(bi/16)%16;
355             if (c>'9')
356                 c= 'A'+(c-'0'-10);
357             buf.append((char)c);
358             c='0'+bi%16;
359             if (c>'9')
360                 c= 'A'+(c-'0'-10);
361             buf.append((char)c);
362         }
363         catch(IOException e)
364         {
365             throw new RuntimeException(e);
366         }
367     }
368 
369     /* ------------------------------------------------------------ */
370     public static String toHexString(byte[] b)
371     {
372         return toHexString(b, 0, b.length);
373     }
374 
375     /* ------------------------------------------------------------ */
376     public static String toHexString(byte[] b,int offset,int length)
377     {
378         StringBuilder buf = new StringBuilder();
379         for (int i=offset;i<offset+length;i++)
380         {
381             int bi=0xff&b[i];
382             int c='0'+(bi/16)%16;
383             if (c>'9')
384                 c= 'A'+(c-'0'-10);
385             buf.append((char)c);
386             c='0'+bi%16;
387             if (c>'9')
388                 c= 'a'+(c-'0'-10);
389             buf.append((char)c);
390         }
391         return buf.toString();
392     }
393 
394     /* ------------------------------------------------------------ */
395     public static byte[] fromHexString(String s)
396     {
397         if (s.length()%2!=0)
398             throw new IllegalArgumentException(s);
399         byte[] array = new byte[s.length()/2];
400         for (int i=0;i<array.length;i++)
401         {
402             int b = Integer.parseInt(s.substring(i*2,i*2+2),16);
403             array[i]=(byte)(0xff&b);
404         }
405         return array;
406     }
407 
408 
409     public static void dump(Class c)
410     {
411         System.err.println("Dump: "+c);
412         dump(c.getClassLoader());
413     }
414 
415     public static void dump(ClassLoader cl)
416     {
417         System.err.println("Dump Loaders:");
418         while(cl!=null)
419         {
420             System.err.println("  loader "+cl);
421             cl = cl.getParent();
422         }
423     }
424 
425 
426     /* ------------------------------------------------------------ */
427     public static byte[] readLine(InputStream in) throws IOException
428     {
429         byte[] buf = new byte[256];
430 
431         int i=0;
432         int loops=0;
433         int ch=0;
434 
435         while (true)
436         {
437             ch=in.read();
438             if (ch<0)
439                 break;
440             loops++;
441 
442             // skip a leading LF's
443             if (loops==1 && ch==LF)
444                 continue;
445 
446             if (ch==CR || ch==LF)
447                 break;
448 
449             if (i>=buf.length)
450             {
451                 byte[] old_buf=buf;
452                 buf=new byte[old_buf.length+256];
453                 System.arraycopy(old_buf, 0, buf, 0, old_buf.length);
454             }
455             buf[i++]=(byte)ch;
456         }
457 
458         if (ch==-1 && i==0)
459             return null;
460 
461         // skip a trailing LF if it exists
462         if (ch==CR && in.available()>=1 && in.markSupported())
463         {
464             in.mark(1);
465             ch=in.read();
466             if (ch!=LF)
467                 in.reset();
468         }
469 
470         byte[] old_buf=buf;
471         buf=new byte[i];
472         System.arraycopy(old_buf, 0, buf, 0, i);
473 
474         return buf;
475     }
476 
477     public static URL jarFor(String className)
478     {
479         try
480         {
481             className=className.replace('.','/')+".class";
482             // hack to discover jstl libraries
483             URL url = Loader.getResource(null,className,false);
484             String s=url.toString();
485             if (s.startsWith("jar:file:"))
486                 return new URL(s.substring(4,s.indexOf("!/")));
487         }
488         catch(Exception e)
489         {
490             Log.ignore(e);
491         }
492         return null;
493     }
494 }