View Javadoc

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