Coverage Report - org.mule.util.ClassUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
ClassUtils
66%
114/173
64%
85/132
4.152
ClassUtils$1
100%
3/3
50%
1/2
4.152
ClassUtils$10
100%
4/4
N/A
4.152
ClassUtils$2
100%
2/2
50%
1/2
4.152
ClassUtils$3
100%
2/2
N/A
4.152
ClassUtils$4
60%
3/5
50%
1/2
4.152
ClassUtils$5
0%
0/4
0%
0/2
4.152
ClassUtils$6
0%
0/4
N/A
4.152
ClassUtils$7
100%
5/5
50%
1/2
4.152
ClassUtils$8
100%
4/4
N/A
4.152
ClassUtils$9
100%
4/4
50%
1/2
4.152
 
 1  
 /*
 2  
  * $Id: ClassUtils.java 10623 2008-01-30 14:29:00Z aperepel $
 3  
  * --------------------------------------------------------------------------------------
 4  
  * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
 5  
  *
 6  
  * The software in this package is published under the terms of the CPAL v1.0
 7  
  * license, a copy of which has been included with this distribution in the
 8  
  * LICENSE.txt file.
 9  
  */
 10  
 
 11  
 package org.mule.util;
 12  
 
 13  
 import java.io.BufferedReader;
 14  
 import java.io.CharArrayReader;
 15  
 import java.io.IOException;
 16  
 import java.io.Reader;
 17  
 import java.lang.reflect.Constructor;
 18  
 import java.lang.reflect.InvocationTargetException;
 19  
 import java.lang.reflect.Method;
 20  
 import java.lang.reflect.Modifier;
 21  
 import java.net.URL;
 22  
 import java.security.AccessController;
 23  
 import java.security.PrivilegedAction;
 24  
 import java.util.ArrayList;
 25  
 import java.util.Collections;
 26  
 import java.util.Enumeration;
 27  
 import java.util.HashMap;
 28  
 import java.util.List;
 29  
 import java.util.Map;
 30  
 import java.util.Set;
 31  
 
 32  
 /**
 33  
  * Extend the Apache Commons ClassUtils to provide additional functionality.
 34  
  *
 35  
  * <p>This class is useful for loading resources and classes in a fault tolerant manner
 36  
  * that works across different applications servers. The resource and classloading
 37  
  * methods are SecurityManager friendly.</p>
 38  
  */
 39  
 // @ThreadSafe
 40  0
 public class ClassUtils extends org.apache.commons.lang.ClassUtils
 41  
 {
 42  2
     public static final Object[] NO_ARGS = new Object[]{};
 43  
 
 44  2
     private static final Map wrapperToPrimitiveMap = new HashMap();
 45  
     static
 46  
     {
 47  22
         wrapperToPrimitiveMap.put(Boolean.class, Boolean.TYPE);
 48  2
         wrapperToPrimitiveMap.put(Byte.class, Byte.TYPE);
 49  2
         wrapperToPrimitiveMap.put(Character.class, Character.TYPE);
 50  2
         wrapperToPrimitiveMap.put(Short.class, Short.TYPE);
 51  2
         wrapperToPrimitiveMap.put(Integer.class, Integer.TYPE);
 52  2
         wrapperToPrimitiveMap.put(Long.class, Long.TYPE);
 53  2
         wrapperToPrimitiveMap.put(Double.class, Double.TYPE);
 54  2
         wrapperToPrimitiveMap.put(Float.class, Float.TYPE);
 55  2
         wrapperToPrimitiveMap.put(Void.TYPE, Void.TYPE);
 56  2
     }
 57  
 
 58  
     public static boolean isConcrete(Class clazz)
 59  
     {
 60  8
         if (clazz == null)
 61  
         {
 62  2
             throw new IllegalArgumentException("clazz may not be null");
 63  
         }
 64  6
         return !(clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers()));
 65  
     }
 66  
 
 67  
     /**
 68  
      * Load a given resource. <p/> This method will try to load the resource using
 69  
      * the following methods (in order):
 70  
      * <ul>
 71  
      * <li>From
 72  
      * {@link Thread#getContextClassLoader() Thread.currentThread().getContextClassLoader()}
 73  
      * <li>From
 74  
      * {@link Class#getClassLoader() ClassUtils.class.getClassLoader()}
 75  
      * <li>From the {@link Class#getClassLoader() callingClass.getClassLoader() }
 76  
      * </ul>
 77  
      * 
 78  
      * @param resourceName The name of the resource to load
 79  
      * @param callingClass The Class object of the calling object
 80  
      */
 81  
     public static URL getResource(final String resourceName, final Class callingClass)
 82  
     {
 83  438
         URL url = (URL) AccessController.doPrivileged(new PrivilegedAction()
 84  
         {
 85  438
             public Object run()
 86  
             {
 87  438
                 final ClassLoader cl = Thread.currentThread().getContextClassLoader();
 88  438
                 return cl != null ? cl.getResource(resourceName) : null;
 89  
             }
 90  
         });
 91  
 
 92  438
         if (url == null)
 93  
         {
 94  6
             url = (URL) AccessController.doPrivileged(new PrivilegedAction()
 95  
             {
 96  6
                 public Object run()
 97  
                 {
 98  6
                     return ClassUtils.class.getClassLoader().getResource(resourceName);
 99  
                 }
 100  
             });
 101  
         }
 102  
 
 103  438
         if (url == null)
 104  
         {
 105  6
             url = (URL) AccessController.doPrivileged(new PrivilegedAction()
 106  
             {
 107  6
                 public Object run()
 108  
                 {
 109  6
                     return callingClass.getClassLoader().getResource(resourceName);
 110  
                 }
 111  
             });
 112  
         }
 113  
 
 114  438
         return url;
 115  
     }
 116  
 
 117  
     public static Enumeration getResources(final String resourceName, final Class callingClass)
 118  
     {
 119  4
         Enumeration enumeration = (Enumeration) AccessController.doPrivileged(new PrivilegedAction()
 120  
         {
 121  4
             public Object run()
 122  
             {
 123  
                 try
 124  
                 {
 125  4
                     final ClassLoader cl = Thread.currentThread().getContextClassLoader();
 126  4
                     return cl != null ? cl.getResources(resourceName) : null;
 127  
                 }
 128  0
                 catch (IOException e)
 129  
                 {
 130  0
                     return null;
 131  
                 }
 132  
             }
 133  
         });
 134  
 
 135  4
         if (enumeration == null)
 136  
         {
 137  0
             enumeration = (Enumeration) AccessController.doPrivileged(new PrivilegedAction()
 138  
             {
 139  0
                 public Object run()
 140  
                 {
 141  
                     try
 142  
                     {
 143  0
                         return ClassUtils.class.getClassLoader().getResources(resourceName);
 144  
                     }
 145  0
                     catch (IOException e)
 146  
                     {
 147  0
                         return null;
 148  
                     }
 149  
                 }
 150  
             });
 151  
         }
 152  
 
 153  4
         if (enumeration == null)
 154  
         {
 155  0
             enumeration = (Enumeration) AccessController.doPrivileged(new PrivilegedAction()
 156  
             {
 157  0
                 public Object run()
 158  
                 {
 159  
                     try
 160  
                     {
 161  0
                         return callingClass.getClassLoader().getResources(resourceName);
 162  
                     }
 163  0
                     catch (IOException e)
 164  
                     {
 165  0
                         return null;
 166  
                     }
 167  
                 }
 168  
             });
 169  
         }
 170  
 
 171  4
         return enumeration;
 172  
     }
 173  
 
 174  
     /**
 175  
      * Load a class with a given name. <p/> It will try to load the class in the
 176  
      * following order:
 177  
      * <ul>
 178  
      * <li>From
 179  
      * {@link Thread#getContextClassLoader() Thread.currentThread().getContextClassLoader()}
 180  
      * <li>Using the basic {@link Class#forName(java.lang.String) }
 181  
      * <li>From
 182  
      * {@link Class#getClassLoader() ClassLoaderUtil.class.getClassLoader()}
 183  
      * <li>From the {@link Class#getClassLoader() callingClass.getClassLoader() }
 184  
      * </ul>
 185  
      * 
 186  
      * @param className The name of the class to load
 187  
      * @param callingClass The Class object of the calling object
 188  
      * @throws ClassNotFoundException If the class cannot be found anywhere.
 189  
      */
 190  
     public static Class loadClass(final String className, final Class callingClass)
 191  
         throws ClassNotFoundException
 192  
     {
 193  2174
         Class clazz = (Class) AccessController.doPrivileged(new PrivilegedAction()
 194  
         {
 195  2174
             public Object run()
 196  
             {
 197  
                 try
 198  
                 {
 199  2174
                     final ClassLoader cl = Thread.currentThread().getContextClassLoader();
 200  2174
                     return cl != null ? cl.loadClass(className) : null;
 201  
 
 202  
                 }
 203  6
                 catch (ClassNotFoundException e)
 204  
                 {
 205  6
                     return null;
 206  
                 }
 207  
             }
 208  
         });
 209  
 
 210  2174
         if (clazz == null)
 211  
         {
 212  6
             clazz = (Class) AccessController.doPrivileged(new PrivilegedAction()
 213  
             {
 214  6
                 public Object run()
 215  
                 {
 216  
                     try
 217  
                     {
 218  6
                         return Class.forName(className);
 219  
                     }
 220  6
                     catch (ClassNotFoundException e)
 221  
                     {
 222  6
                         return null;
 223  
                     }
 224  
                 }
 225  
             });
 226  
         }
 227  
 
 228  2174
         if (clazz == null)
 229  
         {
 230  6
             clazz = (Class) AccessController.doPrivileged(new PrivilegedAction()
 231  
             {
 232  6
                 public Object run()
 233  
                 {
 234  
                     try
 235  
                     {
 236  6
                         return ClassUtils.class.getClassLoader().loadClass(className);
 237  
                     }
 238  6
                     catch (ClassNotFoundException e)
 239  
                     {
 240  6
                         return null;
 241  
                     }
 242  
                 }
 243  
             });
 244  
         }
 245  
 
 246  2174
         if (clazz == null)
 247  
         {
 248  6
             clazz = (Class) AccessController.doPrivileged(new PrivilegedAction()
 249  
             {
 250  6
                 public Object run()
 251  
                 {
 252  
                     try
 253  
                     {
 254  6
                         return callingClass.getClassLoader().loadClass(className);
 255  
                     }
 256  6
                     catch (ClassNotFoundException e)
 257  
                     {
 258  6
                         return null;
 259  
                     }
 260  
                 }
 261  
             });
 262  
         }
 263  
 
 264  2174
         if (clazz == null)
 265  
         {
 266  6
             throw new ClassNotFoundException(className);
 267  
         }
 268  
 
 269  2168
         return clazz;
 270  
     }
 271  
 
 272  
     /**
 273  
      * Prints the current classloader hierarchy - useful for debugging.
 274  
      */
 275  
     public static void printClassLoader()
 276  
     {
 277  0
         System.out.println("ClassLoaderUtils.printClassLoader");
 278  0
         printClassLoader(Thread.currentThread().getContextClassLoader());
 279  0
     }
 280  
 
 281  
     /**
 282  
      * Prints the classloader hierarchy from a given classloader - useful for
 283  
      * debugging.
 284  
      */
 285  
     public static void printClassLoader(ClassLoader cl)
 286  
     {
 287  0
         System.out.println("ClassLoaderUtils.printClassLoader(cl = " + cl + ")");
 288  
 
 289  0
         if (cl != null)
 290  
         {
 291  0
             printClassLoader(cl.getParent());
 292  
         }
 293  0
     }
 294  
 
 295  
     public static Object instanciateClass(Class clazz, Object[] constructorArgs)
 296  
         throws SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException,
 297  
         IllegalAccessException, InvocationTargetException
 298  
     {
 299  
         Class[] args;
 300  1316
         if (constructorArgs != null)
 301  
         {
 302  1302
             args = new Class[constructorArgs.length];
 303  1306
             for (int i = 0; i < constructorArgs.length; i++)
 304  
             {
 305  4
                 if (constructorArgs[i] == null)
 306  
                 {
 307  0
                     args[i] = null;
 308  
                 }
 309  
                 else
 310  
                 {
 311  4
                     args[i] = constructorArgs[i].getClass();
 312  
                 }
 313  
             }
 314  
         }
 315  
         else
 316  
         {
 317  14
             args = new Class[0];
 318  
         }
 319  
 
 320  
         // try the arguments as given
 321  1316
         Constructor ctor = getConstructor(clazz, args);
 322  
 
 323  1316
         if (ctor == null)
 324  
         {
 325  
             // try again but adapt value classes to primitives
 326  0
             ctor = getConstructor(clazz, wrappersToPrimitives(args));
 327  
         }
 328  
 
 329  1316
         if (ctor == null)
 330  
         {
 331  0
             StringBuffer argsString = new StringBuffer(100);
 332  0
             for (int i = 0; i < args.length; i++)
 333  
             {
 334  0
                 argsString.append(args[i].getName()).append(", ");
 335  
             }
 336  0
             throw new NoSuchMethodException("could not find constructor with matching arg params: "
 337  
                             + argsString);
 338  
         }
 339  
 
 340  1316
         return ctor.newInstance(constructorArgs);
 341  
     }
 342  
 
 343  
     public static Object instanciateClass(String name, Object[] constructorArgs)
 344  
         throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException,
 345  
         InstantiationException, IllegalAccessException, InvocationTargetException
 346  
     {
 347  880
         Class clazz = loadClass(name, ClassUtils.class);
 348  878
         return instanciateClass(clazz, constructorArgs);
 349  
 
 350  
     }
 351  
 
 352  
     public static Object instanciateClass(String name, Object[] constructorArgs, Class callingClass)
 353  
         throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException,
 354  
         InstantiationException, IllegalAccessException, InvocationTargetException
 355  
     {
 356  436
         Class clazz = loadClass(name, callingClass);
 357  436
         return instanciateClass(clazz, constructorArgs);
 358  
     }
 359  
 
 360  
     public static Class[] getParameterTypes(Object bean, String methodName)
 361  
     {
 362  4
         if (!methodName.startsWith("set"))
 363  
         {
 364  4
             methodName = "set" + methodName.substring(0, 1).toUpperCase() + methodName.substring(1);
 365  
         }
 366  
 
 367  4
         Method methods[] = bean.getClass().getMethods();
 368  
 
 369  52
         for (int i = 0; i < methods.length; i++)
 370  
         {
 371  50
             if (methods[i].getName().equals(methodName))
 372  
             {
 373  2
                 return methods[i].getParameterTypes();
 374  
             }
 375  
         }
 376  
 
 377  2
         return new Class[]{};
 378  
     }
 379  
 
 380  
     /**
 381  
      * Returns a matching method for the given name and parameters on the given class
 382  
      * If the parameterTypes arguments is null it will return the first matching
 383  
      * method on the class.
 384  
      * 
 385  
      * @param clazz the class to find the method on
 386  
      * @param name the method name to find
 387  
      * @param parameterTypes an array of argument types or null
 388  
      * @return the Method object or null if none was found
 389  
      */
 390  
     public static Method getMethod(Class clazz, String name, Class[] parameterTypes)
 391  
     {
 392  462
         Method[] methods = clazz.getMethods();
 393  22140
         for (int i = 0; i < methods.length; i++)
 394  
         {
 395  21684
             if (methods[i].getName().equals(name))
 396  
             {
 397  6
                 if (parameterTypes == null)
 398  
                 {
 399  6
                     return methods[i];
 400  
                 }
 401  0
                 else if (compare(methods[i].getParameterTypes(), parameterTypes, true))
 402  
                 {
 403  0
                     return methods[i];
 404  
                 }
 405  
             }
 406  
         }
 407  456
         return null;
 408  
     }
 409  
     
 410  
     public static Constructor getConstructor(Class clazz, Class[] paramTypes)
 411  
     {
 412  1316
         Constructor[] ctors = clazz.getConstructors();
 413  1320
         for (int i = 0; i < ctors.length; i++)
 414  
         {
 415  1320
             Class[] types = ctors[i].getParameterTypes();
 416  1320
             if (types.length == paramTypes.length)
 417  
             {
 418  1316
                 boolean match = true;
 419  1320
                 for (int x = 0; x < types.length; x++)
 420  
                 {
 421  4
                     if (paramTypes[x] == null)
 422  
                     {
 423  0
                         match = true;
 424  
                     }
 425  
                     else
 426  
                     {
 427  4
                         match = types[x].isAssignableFrom(paramTypes[x]);
 428  
                     }
 429  
                 }
 430  1316
                 if (match)
 431  
                 {
 432  1316
                     return ctors[i];
 433  
                 }
 434  
             }
 435  
         }
 436  0
         return null;
 437  
     }
 438  
 
 439  
     /**
 440  
      * A helper method that will find all matching methods on a class with the given
 441  
      * parameter type
 442  
      * 
 443  
      * @param implementation the class to build methods on
 444  
      * @param parameterTypes the argument param types to look for
 445  
      * @param voidOk whether void methods shouldbe included in the found list
 446  
      * @param matchOnObject determines whether parameters of Object type are matched
 447  
      *            when they are of Object.class type
 448  
      * @param ignoredMethodNames a Set of method names to ignore. Often 'equals' is
 449  
      *            not a desired match. This argument can be null.
 450  
      * @return a List of methods on the class that match the criteria. If there are
 451  
      *         none, an empty list is returned
 452  
      */
 453  
     public static List getSatisfiableMethods(Class implementation,
 454  
                                              Class[] parameterTypes,
 455  
                                              boolean voidOk,
 456  
                                              boolean matchOnObject,
 457  
                                              Set ignoredMethodNames)
 458  
     {
 459  34
         List result = new ArrayList();
 460  
 
 461  34
         if (ignoredMethodNames == null)
 462  
         {
 463  0
             ignoredMethodNames = Collections.EMPTY_SET;
 464  
         }
 465  
 
 466  34
         Method[] methods = implementation.getMethods();
 467  522
         for (int i = 0; i < methods.length; i++)
 468  
         {
 469  488
             Method method = methods[i];
 470  488
             Class[] methodParams = method.getParameterTypes();
 471  
 
 472  488
             if (compare(methodParams, parameterTypes, matchOnObject))
 473  
             {
 474  52
                 if (!ignoredMethodNames.contains(method.getName()))
 475  
                 {
 476  28
                     String returnType = method.getReturnType().getName();
 477  28
                     if ((returnType.equals("void") && voidOk) || !returnType.equals("void"))
 478  
                     {
 479  24
                         result.add(method);
 480  
                     }
 481  
                 }
 482  
             }
 483  
         }
 484  
 
 485  34
         return result;
 486  
     }
 487  
 
 488  
     public static List getSatisfiableMethodsWithReturnType(Class implementation,
 489  
                                              Class returnType,
 490  
                                              boolean matchOnObject,
 491  
                                              Set ignoredMethodNames)
 492  
     {
 493  0
         List result = new ArrayList();
 494  
 
 495  0
         if (ignoredMethodNames == null)
 496  
         {
 497  0
             ignoredMethodNames = Collections.EMPTY_SET;
 498  
         }
 499  
 
 500  0
         Method[] methods = implementation.getMethods();
 501  0
         for (int i = 0; i < methods.length; i++)
 502  
         {
 503  0
             Method method = methods[i];
 504  0
             Class returns = method.getReturnType();
 505  
 
 506  0
             if (compare(new Class[]{returns}, new Class[]{returnType}, matchOnObject))
 507  
             {
 508  0
                 if (!ignoredMethodNames.contains(method.getName()))
 509  
                 {
 510  0
                     result.add(method);
 511  
                 }
 512  
             }
 513  
         }
 514  
 
 515  0
         return result;
 516  
     }
 517  
 
 518  
     /**
 519  
      * Can be used by serice endpoints to select which service to use based on what's
 520  
      * loaded on the classpath
 521  
      * 
 522  
      * @param className The class name to look for
 523  
      * @param currentClass the calling class
 524  
      * @return true if the class is on the path
 525  
      */
 526  
     public static boolean isClassOnPath(String className, Class currentClass)
 527  
     {
 528  
         try
 529  
         {
 530  0
             return (loadClass(className, currentClass) != null);
 531  
         }
 532  0
         catch (ClassNotFoundException e)
 533  
         {
 534  0
             return false;
 535  
         }
 536  
     }
 537  
 
 538  
     /**
 539  
      * Used for creating an array of class types for an array or single object
 540  
      * 
 541  
      * @param object single object or array
 542  
      * @return an array of class types for the object
 543  
      */
 544  
     public static Class[] getClassTypes(Object object)
 545  
     {
 546  
         Class[] types;
 547  
 
 548  
         // TODO MULE-1088: instead of returning the classes of an array's elements we should
 549  
         // just return the array class - which makes the whole method pointless!?
 550  
 //        if (object.getClass().isArray())
 551  
 //        {
 552  
 //            types = new Class[]{object.getClass()};
 553  
 //        }
 554  
 
 555  24
         if (object instanceof Object[])
 556  
         {
 557  0
             Object[] objects = (Object[]) object;
 558  0
             types = new Class[objects.length];
 559  0
             for (int i = 0; i < objects.length; i++)
 560  
             {
 561  0
                 types[i] = objects[i].getClass();
 562  
             }
 563  0
         }
 564  
         else
 565  
         {
 566  24
             types = new Class[]{object.getClass()};
 567  
         }
 568  
 
 569  24
         return types;
 570  
     }
 571  
 
 572  
     public static String getClassName(Class clazz)
 573  
     {
 574  3520
         if (clazz == null)
 575  
         {
 576  0
             return null;
 577  
         }
 578  3520
         String name = clazz.getName();
 579  3520
         return name.substring(name.lastIndexOf(".") + 1);
 580  
     }
 581  
 
 582  
     public static boolean compare(Class[] c1, Class[] c2, boolean matchOnObject)
 583  
     {
 584  488
         if (c1.length != c2.length)
 585  
         {
 586  320
             return false;
 587  
         }
 588  220
         for (int i = 0; i < c1.length; i++)
 589  
         {
 590  168
             if (c1[i].equals(Object.class) && !matchOnObject)
 591  
             {
 592  14
                 return false;
 593  
             }
 594  154
             if (!c1[i].isAssignableFrom(c2[i]))
 595  
             {
 596  
 
 597  102
                 return false;
 598  
             }
 599  
         }
 600  52
         return true;
 601  
     }
 602  
 
 603  
     public static Class wrapperToPrimitive(Class wrapper)
 604  
     {
 605  0
         return (Class) MapUtils.getObject(wrapperToPrimitiveMap, wrapper, wrapper);
 606  
     }
 607  
 
 608  
     public static Class[] wrappersToPrimitives(Class[] wrappers)
 609  
     {
 610  0
         if (wrappers == null)
 611  
         {
 612  0
             return null;
 613  
         }
 614  
 
 615  0
         if (wrappers.length == 0)
 616  
         {
 617  0
             return wrappers;
 618  
         }
 619  
 
 620  0
         Class[] primitives = new Class[wrappers.length];
 621  
 
 622  0
         for (int i = 0; i < wrappers.length; i++)
 623  
         {
 624  0
             primitives[i] = (Class) MapUtils.getObject(wrapperToPrimitiveMap, wrappers[i], wrappers[i]);
 625  
         }
 626  
 
 627  0
         return primitives;
 628  
     }
 629  
 
 630  
     /**
 631  
      * Provide a simple-to-understand class name (with access to only Java 1.4 API).
 632  
      * @param clazz The class whose name we will generate
 633  
      * @return A readable name for the class
 634  
      */
 635  
     public static String getSimpleName(Class clazz)
 636  
     {
 637  766
         if (null == clazz)
 638  
         {
 639  2
             return "null";
 640  
         }
 641  
         else
 642  
         {
 643  764
             return classNameHelper(new BufferedReader(new CharArrayReader(clazz.getName().toCharArray())));
 644  
         }
 645  
     }
 646  
 
 647  
     private static String classNameHelper(Reader encodedName)
 648  
     {
 649  
         // I did consider separating this data from the code, but I could not find a
 650  
         // solution that was as clear to read, or clearly motivated (these data are not
 651  
         // used elsewhere).
 652  
 
 653  
         try
 654  
         {
 655  794
             encodedName.mark(1);
 656  794
             switch(encodedName.read())
 657  
             {
 658  0
                 case -1: return "null";
 659  0
                 case 'Z': return "boolean";
 660  22
                 case 'B': return "byte";
 661  0
                 case 'C': return "char";
 662  0
                 case 'D': return "double";
 663  0
                 case 'F': return "float";
 664  2
                 case 'I': return "int";
 665  0
                 case 'J': return "long";
 666  0
                 case 'S': return "short";
 667  30
                 case '[': return classNameHelper(encodedName) + "[]";
 668  4
                 case 'L': return shorten(new BufferedReader(encodedName).readLine());
 669  
                 default:
 670  736
                     encodedName.reset();
 671  736
                     return shorten(new BufferedReader(encodedName).readLine());
 672  
             }
 673  
         }
 674  0
         catch (IOException e)
 675  
         {
 676  0
             return "unknown type: " + e.getMessage();
 677  
         }
 678  
     }
 679  
 
 680  
     /**
 681  
      * @param clazz A class name (with possible package and trailing semicolon)
 682  
      * @return The short name for the class
 683  
      */
 684  
     private static String shorten(String clazz)
 685  
     {
 686  740
         if (null != clazz && clazz.endsWith(";"))
 687  
         {
 688  4
             clazz = clazz.substring(0, clazz.length() - 1);
 689  
         }
 690  740
         if (null != clazz && clazz.lastIndexOf(".") > -1)
 691  
         {
 692  740
             clazz = clazz.substring(clazz.lastIndexOf(".") + 1, clazz.length());
 693  
         }
 694  740
         return clazz;
 695  
     }
 696  
 }