com.hazelcast.org.codehaus.janino.Descriptor Maven / Gradle / Ivy
/*
* Janino - An embedded Java[TM] compiler
*
* Copyright (c) 2001-2010 Arno Unkrig. All rights reserved.
* Copyright (c) 2015-2016 TIBCO Software Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
* following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.hazelcast.org.codehaus.janino;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import com.hazelcast.org.codehaus.commons.nullanalysis.Nullable;
/**
* Helper class that defines useful methods for handling "field descriptors"
* (JVMS 4.3.2) and "method descriptors" (JVMS 4.3.3).
*
* Typical descriptors are:
*
*
* - {@code I} Integer
*
- {@code [I} Array of integer
*
- {@code Lpkg1/pkg2/Clazz;} Class
*
- {@code Lpkg1/pkg2/Outer$Inner;} Member class
*
*/
public final
class Descriptor {
private Descriptor() {}
/**
* @return Whether this {@link Descriptor} describes a reference (i.e. non-primitive) type
*/
public static boolean
isReference(String d) { return d.length() > 1; }
/**
* @return Whether this {@link Descriptor} describes a class or an interface (and not an array or a primitive type)
*/
public static boolean
isClassOrInterfaceReference(String d) { return d.charAt(0) == 'L'; }
/**
* @return Whether this {@link Descriptor} describes an array type
*/
public static boolean
isArrayReference(String d) { return d.charAt(0) == '['; }
/**
* @return The descriptor of the component of the array type d
* @throws InternalCompilerException d does not describe an array type
*/
public static String
getComponentDescriptor(String d) {
if (d.charAt(0) != '[') {
throw new InternalCompilerException(
"Cannot determine component descriptor from non-array descriptor \""
+ d
+ "\""
);
}
return d.substring(1);
}
/**
* @return The number of slots (1 or two) that a value of the type described by d occupies on the
* operand stack or in the local variable array, or 0 iff d describes the type VOID
*/
public static short
size(String d) {
if (d.equals(Descriptor.VOID)) return 0;
if (Descriptor.hasSize1(d)) return 1;
if (Descriptor.hasSize2(d)) return 2;
throw new InternalCompilerException("No size defined for type \"" + Descriptor.toString(d) + "\"");
}
/**
* @return {@code true} iff d describes a primitive type except LONG and DOUBLE, or a reference type
*/
public static boolean
hasSize1(String d) {
if (d.length() == 1) return "BCFISZ".indexOf(d) != -1;
return Descriptor.isReference(d);
}
/**
* @return {@code true} iff d LONG or DOUBLE
*/
public static boolean
hasSize2(String d) {
return d.equals(Descriptor.LONG) || d.equals(Descriptor.DOUBLE);
}
/**
* Pretty-prints the given descriptor.
*
* @param d A valid field or method descriptor
*/
public static String
toString(String d) {
int idx = 0;
StringBuilder sb = new StringBuilder();
if (d.charAt(0) == '(') {
++idx;
sb.append("(");
while (idx < d.length() && d.charAt(idx) != ')') {
if (idx != 1) sb.append(", ");
idx = Descriptor.toString(d, idx, sb);
}
if (idx >= d.length()) throw new InternalCompilerException("Invalid descriptor \"" + d + "\"");
sb.append(") => ");
++idx;
}
Descriptor.toString(d, idx, sb);
return sb.toString();
}
private static int
toString(String d, int idx, StringBuilder sb) {
int dimensions = 0;
while (idx < d.length() && d.charAt(idx) == '[') {
++dimensions;
++idx;
}
if (idx >= d.length()) throw new InternalCompilerException("Invalid descriptor \"" + d + "\"");
switch (d.charAt(idx)) {
case 'L':
{
int idx2 = d.indexOf(';', idx);
if (idx2 == -1) throw new InternalCompilerException("Invalid descriptor \"" + d + "\"");
sb.append(d.substring(idx + 1, idx2).replace('/', '.'));
idx = idx2;
}
break;
case 'V':
sb.append("void");
break;
case 'B':
sb.append("byte");
break;
case 'C':
sb.append("char");
break;
case 'D':
sb.append("double");
break;
case 'F':
sb.append("float");
break;
case 'I':
sb.append("int");
break;
case 'J':
sb.append("long");
break;
case 'S':
sb.append("short");
break;
case 'Z':
sb.append("boolean");
break;
default:
throw new InternalCompilerException("Invalid descriptor \"" + d + "\"");
}
for (; dimensions > 0; --dimensions) sb.append("[]");
return idx + 1;
}
/**
* Converts a class name as defined by "Class.getName()" into a descriptor.
*/
public static String
fromClassName(String className) {
String res = (String) Descriptor.CLASS_NAME_TO_DESCRIPTOR.get(className);
if (res != null) { return res; }
if (className.startsWith("[")) return className.replace('.', '/');
return 'L' + className.replace('.', '/') + ';';
}
/**
* Converts a class name in the "internal form" as described in JVMS 4.2 into a descriptor.
*
* Also implements the encoding of array types as described in JVMS 4.4.1.
*
*/
public static String
fromInternalForm(String internalForm) {
if (internalForm.charAt(0) == '[') return internalForm;
return 'L' + internalForm + ';';
}
/**
* Converts a field descriptor into a class name as defined by {@link Class#getName()}.
*/
public static String
toClassName(String d) {
String res = (String) Descriptor.DESCRIPTOR_TO_CLASSNAME.get(d);
if (res != null) { return res; }
char firstChar = d.charAt(0);
if (firstChar == 'L' && d.endsWith(";")) {
// Class or interface -- convert "Ljava/lang/String;" to "java.lang.String".
return d.substring(1, d.length() - 1).replace('/', '.');
}
if (firstChar == '[') {
// Array type -- convert "[Ljava/lang/String;" to "[Ljava.lang.String;".
return d.replace('/', '.');
}
throw new InternalCompilerException("(Invalid field descriptor \"" + d + "\")");
}
/**
* Converts a descriptor into the "internal form" as defined by JVMS 4.2.
*/
public static String
toInternalForm(String d) {
if (d.charAt(0) != 'L') {
throw new InternalCompilerException(
"Attempt to convert non-class descriptor \""
+ d
+ "\" into internal form"
);
}
return d.substring(1, d.length() - 1);
}
/**
* @return Whether d describes a primitive type or VOID
*/
public static boolean
isPrimitive(String d) { return d.length() == 1 && "VBCDFIJSZ".indexOf(d.charAt(0)) != -1; }
/**
* @return Whether d describes a primitive type except {@code boolean} and {@code void}
*/
public static boolean
isPrimitiveNumeric(String d) { return d.length() == 1 && "BDFIJSC".indexOf(d.charAt(0)) != -1; }
/**
* Returns the package name of a class or interface reference descriptor, or {@code null} iff the class or
* interface is declared in the default package.
*/
@Nullable public static String
getPackageName(String d) {
if (d.charAt(0) != 'L') {
throw new InternalCompilerException("Attempt to get package name of non-class descriptor \"" + d + "\"");
}
int idx = d.lastIndexOf('/');
return idx == -1 ? null : d.substring(1, idx).replace('/', '.');
}
/**
* Checks whether two reference types are declared in the same package.
*/
public static boolean
areInSamePackage(String d1, String d2) {
String packageName1 = Descriptor.getPackageName(d1);
String packageName2 = Descriptor.getPackageName(d2);
return packageName1 == null ? packageName2 == null : packageName1.equals(packageName2);
}
/**
* The field descriptor for the type {@code void}.
*/
public static final String VOID = "V";
// Primitive types.
/**
* The field descriptor for the primitive type BYTE.
*/
public static final String BYTE = "B";
/**
* The field descriptor for the primitive type CHAR.
*/
public static final String CHAR = "C";
/**
* The field descriptor for the primitive type DOUBLE.
*/
public static final String DOUBLE = "D";
/**
* The field descriptor for the primitive type FLOAT.
*/
public static final String FLOAT = "F";
/**
* The field descriptor for the primitive type INT.
*/
public static final String INT = "I";
/**
* The field descriptor for the primitive type LONG.
*/
public static final String LONG = "J";
/**
* The field descriptor for the primitive type SHORT.
*/
public static final String SHORT = "S";
/**
* The field descriptor for the primitive type BOOLEAN.
*/
public static final String BOOLEAN = "Z";
// Annotations.
/**
* The field descriptor for the annotation {@link java.lang.annotation.Retention}.
*/
public static final String JAVA_LANG_ANNOTATION_RETENTION = "Ljava/lang/annotation/Retention;";
/**
* The field descriptor for the annotation {@link java.lang.Override}.
*/
public static final String JAVA_LANG_OVERRIDE = "Ljava/lang/Override;";
// Classes.
/**
* The field descriptor for the class {@link java.lang.AssertionError}.
*/
public static final String JAVA_LANG_ASSERTIONERROR = "Ljava/lang/AssertionError;";
/**
* The field descriptor for the class {@link java.lang.Boolean}.
*/
public static final String JAVA_LANG_BOOLEAN = "Ljava/lang/Boolean;";
/**
* The field descriptor for the class {@link java.lang.Byte}.
*/
public static final String JAVA_LANG_BYTE = "Ljava/lang/Byte;";
/**
* The field descriptor for the class {@link java.lang.Character}.
*/
public static final String JAVA_LANG_CHARACTER = "Ljava/lang/Character;";
/**
* The field descriptor for the class {@link java.lang.Class}.
*/
public static final String JAVA_LANG_CLASS = "Ljava/lang/Class;";
/**
* The field descriptor for the class {@link java.lang.Double}.
*/
public static final String JAVA_LANG_DOUBLE = "Ljava/lang/Double;";
/**
* The field descriptor for the class {@link java.lang.Enum}.
*/
public static final String JAVA_LANG_ENUM = "Ljava/lang/Enum;";
/**
* The field descriptor for the class {@link java.lang.Error}.
*/
public static final String JAVA_LANG_ERROR = "Ljava/lang/Error;";
/**
* The field descriptor for the class {@link java.lang.Exception}.
*/
public static final String JAVA_LANG_EXCEPTION = "Ljava/lang/Exception;";
/**
* The field descriptor for the class {@link java.lang.Float}.
*/
public static final String JAVA_LANG_FLOAT = "Ljava/lang/Float;";
/**
* The field descriptor for the class {@link java.lang.Integer}.
*/
public static final String JAVA_LANG_INTEGER = "Ljava/lang/Integer;";
/**
* The field descriptor for the class {@link java.lang.Long}.
*/
public static final String JAVA_LANG_LONG = "Ljava/lang/Long;";
/**
* The field descriptor for the class {@link java.lang.Object}.
*/
public static final String JAVA_LANG_OBJECT = "Ljava/lang/Object;";
/**
* The field descriptor for the class {@link java.lang.RuntimeException}.
*/
public static final String JAVA_LANG_RUNTIMEEXCEPTION = "Ljava/lang/RuntimeException;";
/**
* The field descriptor for the class {@link java.lang.Short}.
*/
public static final String JAVA_LANG_SHORT = "Ljava/lang/Short;";
/**
* The field descriptor for the class {@link java.lang.String}.
*/
public static final String JAVA_LANG_STRING = "Ljava/lang/String;";
/**
* The field descriptor for the class {@link java.lang.StringBuilder}.
*/
public static final String JAVA_LANG_STRINGBUILDER = "Ljava/lang/StringBuilder;"; // Since 1.5!
/**
* The field descriptor for the class {@link java.lang.System}.
*/
public static final String JAVA_LANG_SYSTEM = "Ljava/lang/System;";
/**
* The field descriptor for the class {@link java.lang.Throwable}.
*/
public static final String JAVA_LANG_THROWABLE = "Ljava/lang/Throwable;";
// Interfaces.
/**
* The field descriptor for the interface {@link java.io.Serializable}.
*/
public static final String JAVA_IO_SERIALIZABLE = "Ljava/io/Serializable;";
/**
* The field descriptor for the interface {@link java.lang.Cloneable}.
*/
public static final String JAVA_LANG_CLONEABLE = "Ljava/lang/Cloneable;";
/**
* The field descriptor for the interface {@link java.lang.Iterable}.
*/
public static final String JAVA_LANG_ITERABLE = "Ljava/lang/Iterable;";
/**
* The field descriptor for the interface {@link java.util.Iterator}.
*/
public static final String JAVA_UTIL_ITERATOR = "Ljava/util/Iterator;";
private static final Map DESCRIPTOR_TO_CLASSNAME;
static {
Map m = new HashMap();
m.put(Descriptor.VOID, "void");
// Primitive types.
m.put(Descriptor.BYTE, "byte");
m.put(Descriptor.CHAR, "char");
m.put(Descriptor.DOUBLE, "double");
m.put(Descriptor.FLOAT, "float");
m.put(Descriptor.INT, "int");
m.put(Descriptor.LONG, "long");
m.put(Descriptor.SHORT, "short");
m.put(Descriptor.BOOLEAN, "boolean");
// Annotations.
m.put(Descriptor.JAVA_LANG_OVERRIDE, "java.lang.Override");
// Classes.
m.put(Descriptor.JAVA_LANG_ASSERTIONERROR, "java.lang.AssertionError");
m.put(Descriptor.JAVA_LANG_BOOLEAN, "java.lang.Boolean");
m.put(Descriptor.JAVA_LANG_BYTE, "java.lang.Byte");
m.put(Descriptor.JAVA_LANG_CHARACTER, "java.lang.Character");
m.put(Descriptor.JAVA_LANG_CLASS, "java.lang.Class");
m.put(Descriptor.JAVA_LANG_DOUBLE, "java.lang.Double");
m.put(Descriptor.JAVA_LANG_EXCEPTION, "java.lang.Exception");
m.put(Descriptor.JAVA_LANG_ERROR, "java.lang.Error");
m.put(Descriptor.JAVA_LANG_FLOAT, "java.lang.Float");
m.put(Descriptor.JAVA_LANG_INTEGER, "java.lang.Integer");
m.put(Descriptor.JAVA_LANG_LONG, "java.lang.Long");
m.put(Descriptor.JAVA_LANG_OBJECT, "java.lang.Object");
m.put(Descriptor.JAVA_LANG_RUNTIMEEXCEPTION, "java.lang.RuntimeException");
m.put(Descriptor.JAVA_LANG_SHORT, "java.lang.Short");
m.put(Descriptor.JAVA_LANG_STRING, "java.lang.String");
m.put(Descriptor.JAVA_LANG_STRINGBUILDER, "java.lang.StringBuilder");
m.put(Descriptor.JAVA_LANG_THROWABLE, "java.lang.Throwable");
// Interfaces.
m.put(Descriptor.JAVA_IO_SERIALIZABLE, "java.io.Serializable");
m.put(Descriptor.JAVA_LANG_CLONEABLE, "java.lang.Cloneable");
m.put(Descriptor.JAVA_LANG_ITERABLE, "java.lang.Iterable");
m.put(Descriptor.JAVA_UTIL_ITERATOR, "java.util.Iterator");
DESCRIPTOR_TO_CLASSNAME = Collections.unmodifiableMap(m);
}
private static final Map CLASS_NAME_TO_DESCRIPTOR;
static {
Map m = new HashMap();
for (Map.Entry e : Descriptor.DESCRIPTOR_TO_CLASSNAME.entrySet()) {
m.put(e.getValue(), e.getKey());
}
CLASS_NAME_TO_DESCRIPTOR = Collections.unmodifiableMap(m);
}
}