/* * 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. * *

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.

* * @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 params = new ArrayList(); //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 v = new SimpleTypeVisitor8() { @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(); } }