duke@1: /* jjg@416: * Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved. duke@1: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@1: * duke@1: * This code is free software; you can redistribute it and/or modify it duke@1: * under the terms of the GNU General Public License version 2 only, as duke@1: * published by the Free Software Foundation. Sun designates this duke@1: * particular file as subject to the "Classpath" exception as provided duke@1: * by Sun in the LICENSE file that accompanied this code. duke@1: * duke@1: * This code is distributed in the hope that it will be useful, but WITHOUT duke@1: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@1: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@1: * version 2 for more details (a copy is included in the LICENSE file that duke@1: * accompanied this code). duke@1: * duke@1: * You should have received a copy of the GNU General Public License version duke@1: * 2 along with this work; if not, write to the Free Software Foundation, duke@1: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@1: * duke@1: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, duke@1: * CA 95054 USA or visit www.sun.com if you need additional information or duke@1: * have any questions. duke@1: */ duke@1: duke@1: duke@1: package com.sun.tools.javah; duke@1: duke@1: import java.util.*; jjg@416: import javax.lang.model.element.Name; jjg@416: import javax.lang.model.element.TypeElement; jjg@416: import javax.lang.model.type.ArrayType; jjg@416: import javax.lang.model.type.DeclaredType; jjg@416: import javax.lang.model.type.NoType; jjg@416: import javax.lang.model.type.PrimitiveType; jjg@416: import javax.lang.model.type.TypeKind; jjg@416: import javax.lang.model.type.TypeMirror; jjg@416: import javax.lang.model.type.TypeVariable; jjg@416: import javax.lang.model.type.TypeVisitor; jjg@416: import javax.lang.model.util.Elements; jjg@416: import javax.lang.model.util.SimpleTypeVisitor6; duke@1: duke@1: /** duke@1: * Returns internal type signature. duke@1: * jjg@416: *

This is NOT part of any API supported by Sun Microsystems. jjg@416: * If you write code that depends on this, you do so at your own jjg@416: * risk. This code and its internal interfaces are subject to change jjg@416: * or deletion without notice.

jjg@416: * duke@1: * @author Sucheta Dambalkar duke@1: */ duke@1: duke@1: public class TypeSignature{ duke@1: jjg@416: Elements elems; duke@1: duke@1: /* Signature Characters */ duke@1: duke@1: private static final String SIG_VOID = "V"; duke@1: private static final String SIG_BOOLEAN = "Z"; duke@1: private static final String SIG_BYTE = "B"; duke@1: private static final String SIG_CHAR = "C"; duke@1: private static final String SIG_SHORT = "S"; duke@1: private static final String SIG_INT = "I"; duke@1: private static final String SIG_LONG = "J"; duke@1: private static final String SIG_FLOAT = "F"; duke@1: private static final String SIG_DOUBLE = "D"; duke@1: private static final String SIG_ARRAY = "["; duke@1: private static final String SIG_CLASS = "L"; duke@1: duke@1: duke@1: jjg@416: public TypeSignature(Elements elems){ jjg@416: this.elems = elems; duke@1: } duke@1: duke@1: /* duke@1: * Returns the type signature of a field according to JVM specs duke@1: */ duke@1: public String getTypeSignature(String javasignature){ duke@1: return getParamJVMSignature(javasignature); duke@1: } duke@1: duke@1: /* duke@1: * Returns the type signature of a method according to JVM specs duke@1: */ jjg@416: public String getTypeSignature(String javasignature, TypeMirror returnType){ duke@1: String signature = null; //Java type signature. duke@1: String typeSignature = null; //Internal type signature. jjg@416: List params = new ArrayList(); //List of parameters. duke@1: String paramsig = null; //Java parameter signature. duke@1: String paramJVMSig = null; //Internal parameter signature. duke@1: String returnSig = null; //Java return type signature. duke@1: String returnJVMType = null; //Internal return type signature. jjg@416: int dimensions = 0; //Array dimension. duke@1: duke@1: int startIndex = -1; duke@1: int endIndex = -1; duke@1: StringTokenizer st = null; duke@1: int i = 0; duke@1: duke@1: // Gets the actual java signature without parentheses. jjg@416: if (javasignature != null) { duke@1: startIndex = javasignature.indexOf("("); duke@1: endIndex = javasignature.indexOf(")"); duke@1: } duke@1: jjg@416: if (((startIndex != -1) && (endIndex != -1)) jjg@416: &&(startIndex+1 < javasignature.length()) jjg@416: &&(endIndex < javasignature.length())) { duke@1: signature = javasignature.substring(startIndex+1, endIndex); duke@1: } duke@1: duke@1: // Separates parameters. jjg@416: if (signature != null) { jjg@416: if (signature.indexOf(",") != -1) { duke@1: st = new StringTokenizer(signature, ","); jjg@416: if (st != null) { duke@1: while (st.hasMoreTokens()) { duke@1: params.add(st.nextToken()); duke@1: } duke@1: } jjg@416: } else { duke@1: params.add(signature); duke@1: } duke@1: } duke@1: duke@1: /* JVM type signature. */ duke@1: typeSignature = "("; duke@1: duke@1: // Gets indivisual internal parameter signature. jjg@416: while (params.isEmpty() != true) { jjg@416: paramsig = params.remove(i).trim(); duke@1: paramJVMSig = getParamJVMSignature(paramsig); jjg@416: if (paramJVMSig != null) { duke@1: typeSignature += paramJVMSig; duke@1: } duke@1: } duke@1: duke@1: typeSignature += ")"; duke@1: duke@1: // Get internal return type signature. duke@1: duke@1: returnJVMType = ""; jjg@416: if (returnType != null) { jjg@416: dimensions = dimensions(returnType); duke@1: } duke@1: jjg@416: //Gets array dimension of return type. jjg@416: while (dimensions-- > 0) { jjg@416: returnJVMType += "["; duke@1: } jjg@416: if (returnType != null) { jjg@416: returnSig = qualifiedTypeName(returnType); duke@1: returnJVMType += getComponentType(returnSig); jjg@416: } else { duke@1: System.out.println("Invalid return type."); duke@1: } duke@1: duke@1: typeSignature += returnJVMType; jjg@416: duke@1: return typeSignature; duke@1: } duke@1: duke@1: /* duke@1: * Returns internal signature of a parameter. duke@1: */ jjg@416: private String getParamJVMSignature(String paramsig) { duke@1: String paramJVMSig = ""; duke@1: String componentType =""; duke@1: duke@1: if(paramsig != null){ duke@1: duke@1: if(paramsig.indexOf("[]") != -1) { duke@1: // Gets array dimension. duke@1: int endindex = paramsig.indexOf("[]"); duke@1: componentType = paramsig.substring(0, endindex); duke@1: String dimensionString = paramsig.substring(endindex); duke@1: if(dimensionString != null){ duke@1: while(dimensionString.indexOf("[]") != -1){ duke@1: paramJVMSig += "["; duke@1: int beginindex = dimensionString.indexOf("]") + 1; duke@1: if(beginindex < dimensionString.length()){ duke@1: dimensionString = dimensionString.substring(beginindex); duke@1: }else duke@1: dimensionString = ""; duke@1: } duke@1: } duke@1: } else componentType = paramsig; duke@1: duke@1: paramJVMSig += getComponentType(componentType); duke@1: } duke@1: return paramJVMSig; duke@1: } duke@1: duke@1: /* duke@1: * Returns internal signature of a component. duke@1: */ duke@1: private String getComponentType(String componentType){ duke@1: duke@1: String JVMSig = ""; duke@1: duke@1: if(componentType != null){ duke@1: if(componentType.equals("void")) JVMSig += SIG_VOID ; duke@1: else if(componentType.equals("boolean")) JVMSig += SIG_BOOLEAN ; duke@1: else if(componentType.equals("byte")) JVMSig += SIG_BYTE ; duke@1: else if(componentType.equals("char")) JVMSig += SIG_CHAR ; duke@1: else if(componentType.equals("short")) JVMSig += SIG_SHORT ; duke@1: else if(componentType.equals("int")) JVMSig += SIG_INT ; duke@1: else if(componentType.equals("long")) JVMSig += SIG_LONG ; duke@1: else if(componentType.equals("float")) JVMSig += SIG_FLOAT ; duke@1: else if(componentType.equals("double")) JVMSig += SIG_DOUBLE ; duke@1: else { duke@1: if(!componentType.equals("")){ jjg@416: TypeElement classNameDoc = elems.getTypeElement(componentType); duke@1: duke@1: if(classNameDoc == null){ jjg@416: System.out.println("Invalid class type for " + componentType); jjg@416: new Exception().printStackTrace(); duke@1: }else { jjg@416: String classname = classNameDoc.getQualifiedName().toString(); duke@1: String newclassname = classname.replace('.', '/'); duke@1: JVMSig += "L"; duke@1: JVMSig += newclassname; duke@1: JVMSig += ";"; duke@1: } duke@1: } duke@1: } duke@1: } duke@1: return JVMSig; duke@1: } jjg@416: jjg@416: int dimensions(TypeMirror t) { jjg@416: if (t.getKind() != TypeKind.ARRAY) jjg@416: return 0; jjg@416: return 1 + dimensions(((ArrayType) t).getComponentType()); jjg@416: } jjg@416: jjg@416: jjg@416: String qualifiedTypeName(TypeMirror type) { jjg@416: TypeVisitor v = new SimpleTypeVisitor6() { jjg@416: @Override jjg@416: public Name visitArray(ArrayType t, Void p) { jjg@416: return t.getComponentType().accept(this, p); jjg@416: } jjg@416: jjg@416: @Override jjg@416: public Name visitDeclared(DeclaredType t, Void p) { jjg@416: return ((TypeElement) t.asElement()).getQualifiedName(); jjg@416: } jjg@416: jjg@416: @Override jjg@416: public Name visitPrimitive(PrimitiveType t, Void p) { jjg@416: return elems.getName(t.toString()); jjg@416: } jjg@416: jjg@416: @Override jjg@416: public Name visitNoType(NoType t, Void p) { jjg@416: if (t.getKind() == TypeKind.VOID) jjg@416: return elems.getName("void"); jjg@416: return defaultAction(t, p); jjg@416: } jjg@416: jjg@416: @Override jjg@416: public Name visitTypeVariable(TypeVariable t, Void p) { jjg@416: return t.getUpperBound().accept(this, p); jjg@416: } jjg@416: }; jjg@416: return v.visit(type).toString(); jjg@416: } duke@1: }