blob: ecd06365bb8b523d7b8c0a9c141729bc7ab4695f [file] [log] [blame]
/*
* Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.javah;
import java.util.*;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.NoType;
import javax.lang.model.type.PrimitiveType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVariable;
import javax.lang.model.type.TypeVisitor;
import javax.lang.model.util.Elements;
import javax.lang.model.util.SimpleTypeVisitor8;
/**
* Returns internal type signature.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own
* risk. This code and its internal interfaces are subject to change
* or deletion without notice.</b></p>
*
* @author Sucheta Dambalkar
*/
public class TypeSignature {
static class SignatureException extends Exception {
private static final long serialVersionUID = 1L;
SignatureException(String reason) {
super(reason);
}
}
Elements elems;
/* Signature Characters */
private static final String SIG_VOID = "V";
private static final String SIG_BOOLEAN = "Z";
private static final String SIG_BYTE = "B";
private static final String SIG_CHAR = "C";
private static final String SIG_SHORT = "S";
private static final String SIG_INT = "I";
private static final String SIG_LONG = "J";
private static final String SIG_FLOAT = "F";
private static final String SIG_DOUBLE = "D";
private static final String SIG_ARRAY = "[";
private static final String SIG_CLASS = "L";
public TypeSignature(Elements elems){
this.elems = elems;
}
/*
* Returns the type signature of a field according to JVM specs
*/
public String getTypeSignature(String javasignature) throws SignatureException {
return getParamJVMSignature(javasignature);
}
/*
* Returns the type signature of a method according to JVM specs
*/
public String getTypeSignature(String javasignature, TypeMirror returnType)
throws SignatureException {
String signature = null; //Java type signature.
String typeSignature = null; //Internal type signature.
List<String> params = new ArrayList<String>(); //List of parameters.
String paramsig = null; //Java parameter signature.
String paramJVMSig = null; //Internal parameter signature.
String returnSig = null; //Java return type signature.
String returnJVMType = null; //Internal return type signature.
int dimensions = 0; //Array dimension.
int startIndex = -1;
int endIndex = -1;
StringTokenizer st = null;
int i = 0;
// Gets the actual java signature without parentheses.
if (javasignature != null) {
startIndex = javasignature.indexOf("(");
endIndex = javasignature.indexOf(")");
}
if (((startIndex != -1) && (endIndex != -1))
&&(startIndex+1 < javasignature.length())
&&(endIndex < javasignature.length())) {
signature = javasignature.substring(startIndex+1, endIndex);
}
// Separates parameters.
if (signature != null) {
if (signature.indexOf(",") != -1) {
st = new StringTokenizer(signature, ",");
if (st != null) {
while (st.hasMoreTokens()) {
params.add(st.nextToken());
}
}
} else {
params.add(signature);
}
}
/* JVM type signature. */
typeSignature = "(";
// Gets indivisual internal parameter signature.
while (params.isEmpty() != true) {
paramsig = params.remove(i).trim();
paramJVMSig = getParamJVMSignature(paramsig);
if (paramJVMSig != null) {
typeSignature += paramJVMSig;
}
}
typeSignature += ")";
// Get internal return type signature.
returnJVMType = "";
if (returnType != null) {
dimensions = dimensions(returnType);
}
//Gets array dimension of return type.
while (dimensions-- > 0) {
returnJVMType += "[";
}
if (returnType != null) {
returnSig = qualifiedTypeName(returnType);
returnJVMType += getComponentType(returnSig);
} else {
System.out.println("Invalid return type.");
}
typeSignature += returnJVMType;
return typeSignature;
}
/*
* Returns internal signature of a parameter.
*/
private String getParamJVMSignature(String paramsig) throws SignatureException {
String paramJVMSig = "";
String componentType ="";
if(paramsig != null){
if(paramsig.indexOf("[]") != -1) {
// Gets array dimension.
int endindex = paramsig.indexOf("[]");
componentType = paramsig.substring(0, endindex);
String dimensionString = paramsig.substring(endindex);
if(dimensionString != null){
while(dimensionString.indexOf("[]") != -1){
paramJVMSig += "[";
int beginindex = dimensionString.indexOf("]") + 1;
if(beginindex < dimensionString.length()){
dimensionString = dimensionString.substring(beginindex);
}else
dimensionString = "";
}
}
} else componentType = paramsig;
paramJVMSig += getComponentType(componentType);
}
return paramJVMSig;
}
/*
* Returns internal signature of a component.
*/
private String getComponentType(String componentType) throws SignatureException {
String JVMSig = "";
if(componentType != null){
if(componentType.equals("void")) JVMSig += SIG_VOID ;
else if(componentType.equals("boolean")) JVMSig += SIG_BOOLEAN ;
else if(componentType.equals("byte")) JVMSig += SIG_BYTE ;
else if(componentType.equals("char")) JVMSig += SIG_CHAR ;
else if(componentType.equals("short")) JVMSig += SIG_SHORT ;
else if(componentType.equals("int")) JVMSig += SIG_INT ;
else if(componentType.equals("long")) JVMSig += SIG_LONG ;
else if(componentType.equals("float")) JVMSig += SIG_FLOAT ;
else if(componentType.equals("double")) JVMSig += SIG_DOUBLE ;
else {
if(!componentType.equals("")){
TypeElement classNameDoc = elems.getTypeElement(componentType);
if(classNameDoc == null){
throw new SignatureException(componentType);
}else {
String classname = classNameDoc.getQualifiedName().toString();
String newclassname = classname.replace('.', '/');
JVMSig += "L";
JVMSig += newclassname;
JVMSig += ";";
}
}
}
}
return JVMSig;
}
int dimensions(TypeMirror t) {
if (t.getKind() != TypeKind.ARRAY)
return 0;
return 1 + dimensions(((ArrayType) t).getComponentType());
}
String qualifiedTypeName(TypeMirror type) {
TypeVisitor<Name, Void> v = new SimpleTypeVisitor8<Name, Void>() {
@Override
public Name visitArray(ArrayType t, Void p) {
return t.getComponentType().accept(this, p);
}
@Override
public Name visitDeclared(DeclaredType t, Void p) {
return ((TypeElement) t.asElement()).getQualifiedName();
}
@Override
public Name visitPrimitive(PrimitiveType t, Void p) {
return elems.getName(t.toString());
}
@Override
public Name visitNoType(NoType t, Void p) {
if (t.getKind() == TypeKind.VOID)
return elems.getName("void");
return defaultAction(t, p);
}
@Override
public Name visitTypeVariable(TypeVariable t, Void p) {
return t.getUpperBound().accept(this, p);
}
};
return v.visit(type).toString();
}
}