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 combine(final String packageName, final String name, final char separator)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 combineJavaName(final String packageName, final String name)38 public static String combineJavaName (final String packageName, final String name) 39 { 40 return combine (packageName, name, JAVA_NAME_SEPARATOR); 41 } 42 combineVMName(final String packageName, final String name)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 */ javaNameToVMName(final String javaName)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 */ vmNameToJavaName(final String vmName)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 */ methodVMNameToJavaName(final String className, final String methodVMName, final String descriptor, final boolean renameInits, final boolean shortTypeNames, final boolean appendReturnType)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 typeDescriptorToJavaName(final char [] descriptor, int start, final boolean shortTypeNames, final StringBuffer out)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 Descriptors()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 // ----------------------------------------------------------------------------