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 */ 9package com.vladium.util; 10 11import com.vladium.jcd.cls.IClassDefConstants; 12 13// ---------------------------------------------------------------------------- 14/** 15 * @author Vlad Roubtsov, (C) 2003 16 */ 17public 18abstract 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// ----------------------------------------------------------------------------