Home | History | Annotate | Download | only in util
      1 /* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved.
      2  *
      3  * This program and the accompanying materials are made available under
      4  * the terms of the Common Public License v1.0 which accompanies this distribution,
      5  * and is available at http://www.eclipse.org/legal/cpl-v10.html
      6  *
      7  * $Id: Descriptors.java,v 1.1.1.1 2004/05/09 16:57:52 vlad_r Exp $
      8  */
      9 package com.vladium.util;
     10 
     11 import com.vladium.jcd.cls.IClassDefConstants;
     12 
     13 // ----------------------------------------------------------------------------
     14 /**
     15  * @author Vlad Roubtsov, (C) 2003
     16  */
     17 public
     18 abstract class Descriptors
     19 {
     20     // public: ................................................................
     21 
     22     // TODO: some overlap with Types in c.v.jcp.lib
     23 
     24     public static final char JAVA_NAME_SEPARATOR = '.';
     25     public static final char VM_NAME_SEPARATOR = '/';
     26 
     27     public static String combine (final String packageName, final String name, final char separator)
     28     {
     29         if ((name == null) || (name.length () == 0))
     30             throw new IllegalArgumentException ("null or empty input: name");
     31 
     32         if ((packageName == null) || (packageName.length () == 0))
     33             return name;
     34         else
     35             return new StringBuffer (packageName).append (separator).append (name).toString ();
     36     }
     37 
     38     public static String combineJavaName (final String packageName, final String name)
     39     {
     40         return combine (packageName, name, JAVA_NAME_SEPARATOR);
     41     }
     42 
     43     public static String combineVMName (final String packageName, final String name)
     44     {
     45         return combine (packageName, name, VM_NAME_SEPARATOR);
     46     }
     47 
     48     /**
     49      * Converts a Java package/class name to how it would be
     50      * represented in the VM.<P>
     51      *
     52      * Example:
     53      * <PRE><CODE>
     54      * javaNameToVMName("java.lang.Object") = "java/lang/Object"
     55      * </CODE></PRE>
     56      *
     57      * @see #vmNameToJavaName
     58      */
     59     public static String javaNameToVMName (final String javaName)
     60     {
     61         if (javaName == null) return null;
     62 
     63         return javaName.replace ('.', '/');
     64     }
     65 
     66     /**
     67      * Converts a JVM package/class name to how it would be
     68      * represented in Java.<P>
     69      *
     70      * Example:
     71      * <PRE><CODE>
     72      * vmNameToJavaName("java/lang/Object") = "java.lang.Object"
     73      * </CODE></PRE>
     74      *
     75      * @see #javaNameToVMName
     76      */
     77     public static String vmNameToJavaName (final String vmName)
     78     {
     79         if (vmName == null) return null;
     80 
     81         return vmName.replace ('/', '.');
     82     }
     83 
     84     /**
     85      * NOTE: With 'shortTypeNames'=true the output is potentially lossy (truncates
     86      * package name) and can result in method signature collisions in very rare
     87      * circumstances (e.g., java.awt.List = java.util.List).<P>
     88      *
     89      * Return type info is also lost.
     90      *
     91      * @return method name (signature), no package prefix, no return type
     92      */
     93     public static String methodVMNameToJavaName (final String className,
     94                                                  final String methodVMName,
     95                                                  final String descriptor,
     96                                                  final boolean renameInits,
     97                                                  final boolean shortTypeNames,
     98                                                  final boolean appendReturnType)
     99     {
    100         final StringBuffer out = new StringBuffer ();
    101 
    102         if (renameInits)
    103         {
    104             if (IClassDefConstants.CLINIT_NAME.equals (methodVMName))
    105                 return "<static initializer>";
    106             else if (IClassDefConstants.INIT_NAME.equals (methodVMName))
    107                 out.append (className);
    108             else
    109                 out.append (methodVMName);
    110         }
    111         else
    112         {
    113             if (IClassDefConstants.CLINIT_NAME.equals (methodVMName))
    114                 return IClassDefConstants.CLINIT_NAME;
    115             else
    116                 out.append (methodVMName);
    117         }
    118 
    119         final char [] chars = descriptor.toCharArray ();
    120         int end;
    121 
    122         out.append (" (");
    123         {
    124             for (end = chars.length; chars [-- end] != ')'; );
    125 
    126             for (int start = 1; start < end; )
    127             {
    128                 if (start > 1) out.append (", ");
    129                 start = typeDescriptorToJavaName (chars, start, shortTypeNames, out);
    130             }
    131         }
    132 
    133         if (appendReturnType)
    134         {
    135             out.append ("): ");
    136 
    137             typeDescriptorToJavaName (chars, end + 1, shortTypeNames, out);
    138         }
    139         else
    140         {
    141             out.append (')');
    142         }
    143 
    144         return out.toString ();
    145     }
    146 
    147 
    148 
    149     // protected: .............................................................
    150 
    151     // package: ...............................................................
    152 
    153     // private: ...............................................................
    154 
    155 //    private static int typeSignatureToJavaName (final char [] signature, int start,
    156 //                                                final boolean shortTypeNames,
    157 //                                                final StringBuffer out)
    158 //    {
    159 //
    160 //    }
    161 
    162 
    163     private static int typeDescriptorToJavaName (final char [] descriptor, int start,
    164                                                  final boolean shortTypeNames,
    165                                                  final StringBuffer out)
    166     {
    167         int dims;
    168         for (dims = 0; descriptor [start] == '['; ++ dims, ++ start);
    169 
    170         char c = descriptor [start ++];
    171         switch (c)
    172         {
    173             case 'L':
    174             {
    175                 if (shortTypeNames)
    176                 {
    177                     int lastSlash = -1;
    178                     for (int s = start; descriptor [s] != ';'; ++ s)
    179                     {
    180                         if (descriptor [s] == '/') lastSlash = s;
    181                     }
    182 
    183                     for (start = lastSlash > 0 ? lastSlash + 1 : start; descriptor [start] != ';'; ++ start)
    184                     {
    185                         c = descriptor [start];
    186                         if (RENAME_INNER_CLASSES)
    187                             out.append (c != '$' ? c : '.');
    188                         else
    189                             out.append (c);
    190                     }
    191                 }
    192                 else
    193                 {
    194                     for (; descriptor [start] != ';'; ++ start)
    195                     {
    196                         c = descriptor [start];
    197                         out.append (c != '/' ? c : '.');
    198                     }
    199                 }
    200 
    201                 ++ start;
    202             }
    203             break;
    204 
    205             case 'B': out.append ("byte"); break;
    206             case 'C': out.append ("char"); break;
    207             case 'D': out.append ("double"); break;
    208             case 'F': out.append ("float"); break;
    209             case 'I': out.append ("int"); break;
    210             case 'J': out.append ("long"); break;
    211             case 'S': out.append ("short"); break;
    212             case 'Z': out.append ("boolean"); break;
    213 
    214             case 'V': out.append ("void"); break;
    215 
    216             default:
    217                 throw new IllegalStateException ("unknown type descriptor element: " + c);
    218 
    219         } // end of switch
    220 
    221         if (dims > 0)
    222         {
    223             out.append (' ');
    224             for (int d = 0; d < dims; ++ d) out.append ("[]");
    225         }
    226 
    227         return start;
    228     }
    229 
    230 
    231     private Descriptors () {} // prevent subclassing
    232 
    233 
    234     // note: setting this to 'true' is not 100% reliable because it is legal
    235     // to have $'s in regular class names as well:
    236     private static final boolean RENAME_INNER_CLASSES = false;
    237 
    238 } // end of class
    239 // ----------------------------------------------------------------------------