duke@1: /*
darcy@1054: * Copyright (c) 2002, 2011, Oracle and/or its affiliates. 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
ohair@554: * published by the Free Software Foundation. Oracle designates this
duke@1: * particular file as subject to the "Classpath" exception as provided
ohair@554: * by Oracle 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: *
ohair@554: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@554: * or visit www.oracle.com if you need additional information or have any
ohair@554: * 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;
darcy@1054: import javax.lang.model.util.SimpleTypeVisitor8;
duke@1:
duke@1: /**
duke@1: * Returns internal type signature.
duke@1: *
jjg@581: *
This is NOT part of any supported API.
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:
jjg@712: public class TypeSignature {
jjg@712: static class SignatureException extends Exception {
jjg@712: private static final long serialVersionUID = 1L;
jjg@712: SignatureException(String reason) {
jjg@712: super(reason);
jjg@712: }
jjg@712: }
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: */
jjg@712: public String getTypeSignature(String javasignature) throws SignatureException {
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@712: public String getTypeSignature(String javasignature, TypeMirror returnType)
jjg@712: throws SignatureException {
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@712: private String getParamJVMSignature(String paramsig) throws SignatureException {
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: */
jjg@712: private String getComponentType(String componentType) throws SignatureException {
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@712: throw new SignatureException(componentType);
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) {
darcy@1054: TypeVisitor v = new SimpleTypeVisitor8() {
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: }