• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 //  ========================================================================
3 //  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
4 //  ------------------------------------------------------------------------
5 //  All rights reserved. This program and the accompanying materials
6 //  are made available under the terms of the Eclipse Public License v1.0
7 //  and Apache License v2.0 which accompanies this distribution.
8 //
9 //      The Eclipse Public License is available at
10 //      http://www.eclipse.org/legal/epl-v10.html
11 //
12 //      The Apache License v2.0 is available at
13 //      http://www.opensource.org/licenses/apache2.0.php
14 //
15 //  You may elect to redistribute this code under either of these licenses.
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  * TYPE Utilities.
40  * Provides various static utiltiy methods for manipulating types and their
41  * string representations.
42  *
43  * @since Jetty 4.1
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 
name2Class.put(null,java.lang.Void.TYPE)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     {
class2Name.put(java.lang.Boolean.TYPE,"boolean")103         class2Name.put(java.lang.Boolean.TYPE,"boolean");
class2Name.put(java.lang.Byte.TYPE,"byte")104         class2Name.put(java.lang.Byte.TYPE,"byte");
class2Name.put(java.lang.Character.TYPE,"char")105         class2Name.put(java.lang.Character.TYPE,"char");
class2Name.put(java.lang.Double.TYPE,"double")106         class2Name.put(java.lang.Double.TYPE,"double");
class2Name.put(java.lang.Float.TYPE,"float")107         class2Name.put(java.lang.Float.TYPE,"float");
class2Name.put(java.lang.Integer.TYPE,"int")108         class2Name.put(java.lang.Integer.TYPE,"int");
class2Name.put(java.lang.Long.TYPE,"long")109         class2Name.put(java.lang.Long.TYPE,"long");
class2Name.put(java.lang.Short.TYPE,"short")110         class2Name.put(java.lang.Short.TYPE,"short");
class2Name.put(java.lang.Void.TYPE,"void")111         class2Name.put(java.lang.Void.TYPE,"void");
112 
class2Name.put(java.lang.Boolean.class,"java.lang.Boolean")113         class2Name.put(java.lang.Boolean.class,"java.lang.Boolean");
class2Name.put(java.lang.Byte.class,"java.lang.Byte")114         class2Name.put(java.lang.Byte.class,"java.lang.Byte");
class2Name.put(java.lang.Character.class,"java.lang.Character")115         class2Name.put(java.lang.Character.class,"java.lang.Character");
class2Name.put(java.lang.Double.class,"java.lang.Double")116         class2Name.put(java.lang.Double.class,"java.lang.Double");
class2Name.put(java.lang.Float.class,"java.lang.Float")117         class2Name.put(java.lang.Float.class,"java.lang.Float");
class2Name.put(java.lang.Integer.class,"java.lang.Integer")118         class2Name.put(java.lang.Integer.class,"java.lang.Integer");
class2Name.put(java.lang.Long.class,"java.lang.Long")119         class2Name.put(java.lang.Long.class,"java.lang.Long");
class2Name.put(java.lang.Short.class,"java.lang.Short")120         class2Name.put(java.lang.Short.class,"java.lang.Short");
121 
class2Name.put(null,"void")122         class2Name.put(null,"void");
class2Name.put(java.lang.String.class,"java.lang.String")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 
class2Value.put(java.lang.Boolean.TYPE, java.lang.Boolean.class.getMethod("valueOf",s))134             class2Value.put(java.lang.Boolean.TYPE,
135                            java.lang.Boolean.class.getMethod("valueOf",s));
class2Value.put(java.lang.Byte.TYPE, java.lang.Byte.class.getMethod("valueOf",s))136             class2Value.put(java.lang.Byte.TYPE,
137                            java.lang.Byte.class.getMethod("valueOf",s));
class2Value.put(java.lang.Double.TYPE, java.lang.Double.class.getMethod("valueOf",s))138             class2Value.put(java.lang.Double.TYPE,
139                            java.lang.Double.class.getMethod("valueOf",s));
class2Value.put(java.lang.Float.TYPE, java.lang.Float.class.getMethod("valueOf",s))140             class2Value.put(java.lang.Float.TYPE,
141                            java.lang.Float.class.getMethod("valueOf",s));
class2Value.put(java.lang.Integer.TYPE, java.lang.Integer.class.getMethod("valueOf",s))142             class2Value.put(java.lang.Integer.TYPE,
143                            java.lang.Integer.class.getMethod("valueOf",s));
class2Value.put(java.lang.Long.TYPE, java.lang.Long.class.getMethod("valueOf",s))144             class2Value.put(java.lang.Long.TYPE,
145                            java.lang.Long.class.getMethod("valueOf",s));
class2Value.put(java.lang.Short.TYPE, java.lang.Short.class.getMethod("valueOf",s))146             class2Value.put(java.lang.Short.TYPE,
147                            java.lang.Short.class.getMethod("valueOf",s));
148 
class2Value.put(java.lang.Boolean.class, java.lang.Boolean.class.getMethod("valueOf",s))149             class2Value.put(java.lang.Boolean.class,
150                            java.lang.Boolean.class.getMethod("valueOf",s));
class2Value.put(java.lang.Byte.class, java.lang.Byte.class.getMethod("valueOf",s))151             class2Value.put(java.lang.Byte.class,
152                            java.lang.Byte.class.getMethod("valueOf",s));
class2Value.put(java.lang.Double.class, java.lang.Double.class.getMethod("valueOf",s))153             class2Value.put(java.lang.Double.class,
154                            java.lang.Double.class.getMethod("valueOf",s));
class2Value.put(java.lang.Float.class, java.lang.Float.class.getMethod("valueOf",s))155             class2Value.put(java.lang.Float.class,
156                            java.lang.Float.class.getMethod("valueOf",s));
class2Value.put(java.lang.Integer.class, java.lang.Integer.class.getMethod("valueOf",s))157             class2Value.put(java.lang.Integer.class,
158                            java.lang.Integer.class.getMethod("valueOf",s));
class2Value.put(java.lang.Long.class, java.lang.Long.class.getMethod("valueOf",s))159             class2Value.put(java.lang.Long.class,
160                            java.lang.Long.class.getMethod("valueOf",s));
class2Value.put(java.lang.Short.class, java.lang.Short.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     /** Array to List.
172      * <p>
173      * Works like {@link Arrays#asList(Object...)}, but handles null arrays.
174      * @return a list backed by the array.
175      */
asList(T[] a)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     /** Class from a canonical name for a type.
185      * @param name A class or type name.
186      * @return A class , which may be a primitive TYPE field..
187      */
fromName(String name)188     public static Class<?> fromName(String name)
189     {
190         return name2Class.get(name);
191     }
192 
193     /* ------------------------------------------------------------ */
194     /** Canonical name for a type.
195      * @param type A class , which may be a primitive TYPE field.
196      * @return Canonical name.
197      */
toName(Class<?> type)198     public static String toName(Class<?> type)
199     {
200         return class2Name.get(type);
201     }
202 
203     /* ------------------------------------------------------------ */
204     /** Convert String value to instance.
205      * @param type The class of the instance, which may be a primitive TYPE field.
206      * @param value The value as a string.
207      * @return The value as an Object.
208      */
valueOf(Class<?> type, String value)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             // LogSupport.ignore(log,e);
230         }
231         catch(IllegalAccessException e)
232         {
233             // LogSupport.ignore(log,e);
234         }
235         catch(InstantiationException e)
236         {
237             // LogSupport.ignore(log,e);
238         }
239         catch(InvocationTargetException e)
240         {
241             if (e.getTargetException() instanceof Error)
242                 throw (Error)(e.getTargetException());
243             // LogSupport.ignore(log,e);
244         }
245         return null;
246     }
247 
248     /* ------------------------------------------------------------ */
249     /** Convert String value to instance.
250      * @param type classname or type (eg int)
251      * @param value The value as a string.
252      * @return The value as an Object.
253      */
valueOf(String type, String value)254     public static Object valueOf(String type, String value)
255     {
256         return valueOf(fromName(type),value);
257     }
258 
259     /* ------------------------------------------------------------ */
260     /** Parse an int from a substring.
261      * Negative numbers are not handled.
262      * @param s String
263      * @param offset Offset within string
264      * @param length Length of integer or -1 for remainder of string
265      * @param base base of the integer
266      * @return the parsed integer
267      * @throws NumberFormatException if the string cannot be parsed
268      */
parseInt(String s, int offset, int length, int base)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     /** Parse an int from a byte array of ascii characters.
291      * Negative numbers are not handled.
292      * @param b byte array
293      * @param offset Offset within string
294      * @param length Length of integer or -1 for remainder of string
295      * @param base base of the integer
296      * @return the parsed integer
297      * @throws NumberFormatException if the array cannot be parsed into an integer
298      */
parseInt(byte[] b, int offset, int length, int base)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     /* ------------------------------------------------------------ */
parseBytes(String s, int base)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     /* ------------------------------------------------------------ */
toString(byte[] bytes, int base)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      * @param c An ASCII encoded character 0-9 a-f A-F
356      * @return The byte value of the character 0-16.
357      */
convertHexDigit( byte c )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      * @param c An ASCII encoded character 0-9 a-f A-F
369      * @return The byte value of the character 0-16.
370      */
convertHexDigit( int c )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     /* ------------------------------------------------------------ */
toHex(byte b,Appendable buf)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     /* ------------------------------------------------------------ */
toHex(int value,Appendable buf)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     /* ------------------------------------------------------------ */
toHex(long value,Appendable buf)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     /* ------------------------------------------------------------ */
toHexString(byte b)427     public static String toHexString(byte b)
428     {
429         return toHexString(new byte[]{b}, 0, 1);
430     }
431 
432     /* ------------------------------------------------------------ */
toHexString(byte[] b)433     public static String toHexString(byte[] b)
434     {
435         return toHexString(b, 0, b.length);
436     }
437 
438     /* ------------------------------------------------------------ */
toHexString(byte[] b,int offset,int length)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     /* ------------------------------------------------------------ */
fromHexString(String s)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 
dump(Class<?> c)472     public static void dump(Class<?> c)
473     {
474         System.err.println("Dump: "+c);
475         dump(c.getClassLoader());
476     }
477 
dump(ClassLoader cl)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     /**
491      * @deprecated
492      */
readLine(InputStream in)493     public static byte[] readLine(InputStream in) throws IOException
494     {
495         byte[] buf = new byte[256];
496 
497         int i=0;
498         int loops=0;
499         int ch=0;
500 
501         while (true)
502         {
503             ch=in.read();
504             if (ch<0)
505                 break;
506             loops++;
507 
508             // skip a leading LF's
509             if (loops==1 && ch==LF)
510                 continue;
511 
512             if (ch==CR || ch==LF)
513                 break;
514 
515             if (i>=buf.length)
516             {
517                 byte[] old_buf=buf;
518                 buf=new byte[old_buf.length+256];
519                 System.arraycopy(old_buf, 0, buf, 0, old_buf.length);
520             }
521             buf[i++]=(byte)ch;
522         }
523 
524         if (ch==-1 && i==0)
525             return null;
526 
527         // skip a trailing LF if it exists
528         if (ch==CR && in.available()>=1 && in.markSupported())
529         {
530             in.mark(1);
531             ch=in.read();
532             if (ch!=LF)
533                 in.reset();
534         }
535 
536         byte[] old_buf=buf;
537         buf=new byte[i];
538         System.arraycopy(old_buf, 0, buf, 0, i);
539 
540         return buf;
541     }
542 
jarFor(String className)543     public static URL jarFor(String className)
544     {
545         try
546         {
547             className=className.replace('.','/')+".class";
548             // hack to discover jstl libraries
549             URL url = Loader.getResource(null,className,false);
550             String s=url.toString();
551             if (s.startsWith("jar:file:"))
552                 return new URL(s.substring(4,s.indexOf("!/")));
553         }
554         catch(Exception e)
555         {
556             LOG.ignore(e);
557         }
558         return null;
559     }
560 
call(Class<?> oClass, String method, Object obj, Object[] arg)561     public static Object call(Class<?> oClass, String method, Object obj, Object[] arg)
562        throws InvocationTargetException, NoSuchMethodException
563     {
564         // Lets just try all methods for now
565         Method[] methods = oClass.getMethods();
566         for (int c = 0; methods != null && c < methods.length; c++)
567         {
568             if (!methods[c].getName().equals(method))
569                 continue;
570             if (methods[c].getParameterTypes().length != arg.length)
571                 continue;
572             if (Modifier.isStatic(methods[c].getModifiers()) != (obj == null))
573                 continue;
574             if ((obj == null) && methods[c].getDeclaringClass() != oClass)
575                 continue;
576 
577             try
578             {
579                 return methods[c].invoke(obj,arg);
580             }
581             catch (IllegalAccessException e)
582             {
583                 LOG.ignore(e);
584             }
585             catch (IllegalArgumentException e)
586             {
587                 LOG.ignore(e);
588             }
589         }
590 
591         throw new NoSuchMethodException(method);
592     }
593 }
594