| /* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under |
| * the terms of the Common Public License v1.0 which accompanies this distribution, |
| * and is available at http://www.eclipse.org/legal/cpl-v10.html |
| * |
| * $Id: Descriptors.java,v 1.1.1.1 2004/05/09 16:57:52 vlad_r Exp $ |
| */ |
| package com.vladium.util; |
| |
| import com.vladium.jcd.cls.IClassDefConstants; |
| |
| // ---------------------------------------------------------------------------- |
| /** |
| * @author Vlad Roubtsov, (C) 2003 |
| */ |
| public |
| abstract class Descriptors |
| { |
| // public: ................................................................ |
| |
| // TODO: some overlap with Types in c.v.jcp.lib |
| |
| public static final char JAVA_NAME_SEPARATOR = '.'; |
| public static final char VM_NAME_SEPARATOR = '/'; |
| |
| public static String combine (final String packageName, final String name, final char separator) |
| { |
| if ((name == null) || (name.length () == 0)) |
| throw new IllegalArgumentException ("null or empty input: name"); |
| |
| if ((packageName == null) || (packageName.length () == 0)) |
| return name; |
| else |
| return new StringBuffer (packageName).append (separator).append (name).toString (); |
| } |
| |
| public static String combineJavaName (final String packageName, final String name) |
| { |
| return combine (packageName, name, JAVA_NAME_SEPARATOR); |
| } |
| |
| public static String combineVMName (final String packageName, final String name) |
| { |
| return combine (packageName, name, VM_NAME_SEPARATOR); |
| } |
| |
| /** |
| * Converts a Java package/class name to how it would be |
| * represented in the VM.<P> |
| * |
| * Example: |
| * <PRE><CODE> |
| * javaNameToVMName("java.lang.Object") = "java/lang/Object" |
| * </CODE></PRE> |
| * |
| * @see #vmNameToJavaName |
| */ |
| public static String javaNameToVMName (final String javaName) |
| { |
| if (javaName == null) return null; |
| |
| return javaName.replace ('.', '/'); |
| } |
| |
| /** |
| * Converts a JVM package/class name to how it would be |
| * represented in Java.<P> |
| * |
| * Example: |
| * <PRE><CODE> |
| * vmNameToJavaName("java/lang/Object") = "java.lang.Object" |
| * </CODE></PRE> |
| * |
| * @see #javaNameToVMName |
| */ |
| public static String vmNameToJavaName (final String vmName) |
| { |
| if (vmName == null) return null; |
| |
| return vmName.replace ('/', '.'); |
| } |
| |
| /** |
| * NOTE: With 'shortTypeNames'=true the output is potentially lossy (truncates |
| * package name) and can result in method signature collisions in very rare |
| * circumstances (e.g., java.awt.List = java.util.List).<P> |
| * |
| * Return type info is also lost. |
| * |
| * @return method name (signature), no package prefix, no return type |
| */ |
| public static String methodVMNameToJavaName (final String className, |
| final String methodVMName, |
| final String descriptor, |
| final boolean renameInits, |
| final boolean shortTypeNames, |
| final boolean appendReturnType) |
| { |
| final StringBuffer out = new StringBuffer (); |
| |
| if (renameInits) |
| { |
| if (IClassDefConstants.CLINIT_NAME.equals (methodVMName)) |
| return "<static initializer>"; |
| else if (IClassDefConstants.INIT_NAME.equals (methodVMName)) |
| out.append (className); |
| else |
| out.append (methodVMName); |
| } |
| else |
| { |
| if (IClassDefConstants.CLINIT_NAME.equals (methodVMName)) |
| return IClassDefConstants.CLINIT_NAME; |
| else |
| out.append (methodVMName); |
| } |
| |
| final char [] chars = descriptor.toCharArray (); |
| int end; |
| |
| out.append (" ("); |
| { |
| for (end = chars.length; chars [-- end] != ')'; ); |
| |
| for (int start = 1; start < end; ) |
| { |
| if (start > 1) out.append (", "); |
| start = typeDescriptorToJavaName (chars, start, shortTypeNames, out); |
| } |
| } |
| |
| if (appendReturnType) |
| { |
| out.append ("): "); |
| |
| typeDescriptorToJavaName (chars, end + 1, shortTypeNames, out); |
| } |
| else |
| { |
| out.append (')'); |
| } |
| |
| return out.toString (); |
| } |
| |
| |
| |
| // protected: ............................................................. |
| |
| // package: ............................................................... |
| |
| // private: ............................................................... |
| |
| // private static int typeSignatureToJavaName (final char [] signature, int start, |
| // final boolean shortTypeNames, |
| // final StringBuffer out) |
| // { |
| // |
| // } |
| |
| |
| private static int typeDescriptorToJavaName (final char [] descriptor, int start, |
| final boolean shortTypeNames, |
| final StringBuffer out) |
| { |
| int dims; |
| for (dims = 0; descriptor [start] == '['; ++ dims, ++ start); |
| |
| char c = descriptor [start ++]; |
| switch (c) |
| { |
| case 'L': |
| { |
| if (shortTypeNames) |
| { |
| int lastSlash = -1; |
| for (int s = start; descriptor [s] != ';'; ++ s) |
| { |
| if (descriptor [s] == '/') lastSlash = s; |
| } |
| |
| for (start = lastSlash > 0 ? lastSlash + 1 : start; descriptor [start] != ';'; ++ start) |
| { |
| c = descriptor [start]; |
| if (RENAME_INNER_CLASSES) |
| out.append (c != '$' ? c : '.'); |
| else |
| out.append (c); |
| } |
| } |
| else |
| { |
| for (; descriptor [start] != ';'; ++ start) |
| { |
| c = descriptor [start]; |
| out.append (c != '/' ? c : '.'); |
| } |
| } |
| |
| ++ start; |
| } |
| break; |
| |
| case 'B': out.append ("byte"); break; |
| case 'C': out.append ("char"); break; |
| case 'D': out.append ("double"); break; |
| case 'F': out.append ("float"); break; |
| case 'I': out.append ("int"); break; |
| case 'J': out.append ("long"); break; |
| case 'S': out.append ("short"); break; |
| case 'Z': out.append ("boolean"); break; |
| |
| case 'V': out.append ("void"); break; |
| |
| default: |
| throw new IllegalStateException ("unknown type descriptor element: " + c); |
| |
| } // end of switch |
| |
| if (dims > 0) |
| { |
| out.append (' '); |
| for (int d = 0; d < dims; ++ d) out.append ("[]"); |
| } |
| |
| return start; |
| } |
| |
| |
| private Descriptors () {} // prevent subclassing |
| |
| |
| // note: setting this to 'true' is not 100% reliable because it is legal |
| // to have $'s in regular class names as well: |
| private static final boolean RENAME_INNER_CLASSES = false; |
| |
| } // end of class |
| // ---------------------------------------------------------------------------- |