blob: de8b4aaa3d367dbf3c7fd74be455ffc0fcfab1cf [file] [log] [blame]
/* 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
// ----------------------------------------------------------------------------