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

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

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