src/share/classes/com/sun/tools/javac/jvm/JNIWriter.java

Fri, 03 May 2013 15:08:47 -0700

author
jjg
date
Fri, 03 May 2013 15:08:47 -0700
changeset 1723
a2889739cf21
parent 1521
71f35e4b93a5
child 1802
8fb68f73d4b1
permissions
-rw-r--r--

8000407: remove @GenerateNativeHeader
Reviewed-by: vromero, darcy

     1 /*
     2  * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package com.sun.tools.javac.jvm;
    28 import java.io.IOException;
    29 import java.io.Writer;
    30 import java.util.ArrayList;
    31 import java.util.List;
    32 import java.util.Stack;
    33 import java.util.StringTokenizer;
    35 import javax.lang.model.element.Element;
    36 import javax.lang.model.element.ExecutableElement;
    37 import javax.lang.model.element.Modifier;
    38 import javax.lang.model.element.Name;
    39 import javax.lang.model.element.TypeElement;
    40 import javax.lang.model.element.VariableElement;
    41 import javax.lang.model.type.ArrayType;
    42 import javax.lang.model.type.DeclaredType;
    43 import javax.lang.model.type.NoType;
    44 import javax.lang.model.type.PrimitiveType;
    45 import javax.lang.model.type.TypeKind;
    46 import javax.lang.model.type.TypeMirror;
    47 import javax.lang.model.type.TypeVariable;
    48 import javax.lang.model.type.TypeVisitor;
    49 import javax.lang.model.util.ElementFilter;
    50 import javax.lang.model.util.Elements;
    51 import javax.lang.model.util.SimpleTypeVisitor8;
    52 import javax.lang.model.util.Types;
    54 import javax.tools.FileObject;
    55 import javax.tools.JavaFileManager;
    56 import javax.tools.StandardLocation;
    58 import com.sun.tools.javac.code.Attribute;
    59 import com.sun.tools.javac.code.Flags;
    60 import com.sun.tools.javac.code.Kinds;
    61 import com.sun.tools.javac.code.Scope;
    62 import com.sun.tools.javac.code.Symbol.ClassSymbol;
    63 import com.sun.tools.javac.code.Symtab;
    64 import com.sun.tools.javac.model.JavacElements;
    65 import com.sun.tools.javac.model.JavacTypes;
    66 import com.sun.tools.javac.util.Assert;
    67 import com.sun.tools.javac.util.Context;
    68 import com.sun.tools.javac.util.Log;
    69 import com.sun.tools.javac.util.Options;
    71 import static com.sun.tools.javac.main.Option.*;
    73 /** This class provides operations to write native header files for classes.
    74  *
    75  *  <p><b>This is NOT part of any supported API.
    76  *  If you write code that depends on this, you do so at your own risk.
    77  *  This code and its internal interfaces are subject to change or
    78  *  deletion without notice.</b>
    79  */
    80 public class JNIWriter {
    81     protected static final Context.Key<JNIWriter> jniWriterKey =
    82         new Context.Key<JNIWriter>();
    84     /** Access to files. */
    85     private final JavaFileManager fileManager;
    87     JavacElements elements;
    88     JavacTypes types;
    90     /** The log to use for verbose output.
    91      */
    92     private final Log log;
    94     /** Switch: verbose output.
    95      */
    96     private boolean verbose;
    98     /** Switch: check all nested classes of top level class
    99      */
   100     private boolean checkAll;
   102     private Mangle mangler;
   104     private Context context;
   106     private Symtab syms;
   108     private String lineSep;
   110     private final boolean isWindows =
   111         System.getProperty("os.name").startsWith("Windows");
   113     /** Get the ClassWriter instance for this context. */
   114     public static JNIWriter instance(Context context) {
   115         JNIWriter instance = context.get(jniWriterKey);
   116         if (instance == null)
   117             instance = new JNIWriter(context);
   118         return instance;
   119     }
   121     /** Construct a class writer, given an options table.
   122      */
   123     private JNIWriter(Context context) {
   124         context.put(jniWriterKey, this);
   125         fileManager = context.get(JavaFileManager.class);
   126         log = Log.instance(context);
   128         Options options = Options.instance(context);
   129         verbose = options.isSet(VERBOSE);
   130         checkAll = options.isSet("javah:full");
   132         this.context = context; // for lazyInit()
   133         syms = Symtab.instance(context);
   135         lineSep = System.getProperty("line.separator");
   136     }
   138     private void lazyInit() {
   139         if (mangler == null) {
   140             elements = JavacElements.instance(context);
   141             types = JavacTypes.instance(context);
   142             mangler = new Mangle(elements, types);
   143         }
   144     }
   146     public boolean needsHeader(ClassSymbol c) {
   147         if (c.isLocal() || (c.flags() & Flags.SYNTHETIC) != 0)
   148             return false;
   150         if (checkAll)
   151             return needsHeader(c.outermostClass(), true);
   152         else
   153             return needsHeader(c, false);
   154     }
   156     private boolean needsHeader(ClassSymbol c, boolean checkNestedClasses) {
   157         if (c.isLocal() || (c.flags() & Flags.SYNTHETIC) != 0)
   158             return false;
   160         for (Scope.Entry i = c.members_field.elems; i != null; i = i.sibling) {
   161             if (i.sym.kind == Kinds.MTH && (i.sym.flags() & Flags.NATIVE) != 0)
   162                 return true;
   163             for (Attribute.Compound a: i.sym.annotations.getDeclarationAttributes()) {
   164                 if (a.type.tsym == syms.nativeHeaderType.tsym)
   165                     return true;
   166             }
   167         }
   168         if (checkNestedClasses) {
   169             for (Scope.Entry i = c.members_field.elems; i != null; i = i.sibling) {
   170                 if ((i.sym.kind == Kinds.TYP) && needsHeader(((ClassSymbol) i.sym), true))
   171                     return true;
   172             }
   173         }
   174         return false;
   175     }
   177     /** Emit a class file for a given class.
   178      *  @param c      The class from which a class file is generated.
   179      */
   180     public FileObject write(ClassSymbol c)
   181         throws IOException
   182     {
   183         String className = c.flatName().toString();
   184         FileObject outFile
   185             = fileManager.getFileForOutput(StandardLocation.NATIVE_HEADER_OUTPUT,
   186                 "", className.replaceAll("[.$]", "_") + ".h", null);
   187         Writer out = outFile.openWriter();
   188         try {
   189             write(out, c);
   190             if (verbose)
   191                 log.printVerbose("wrote.file", outFile);
   192             out.close();
   193             out = null;
   194         } finally {
   195             if (out != null) {
   196                 // if we are propogating an exception, delete the file
   197                 out.close();
   198                 outFile.delete();
   199                 outFile = null;
   200             }
   201         }
   202         return outFile; // may be null if write failed
   203     }
   205     public void write(Writer out, ClassSymbol sym)
   206             throws IOException {
   207         lazyInit();
   208         try {
   209             String cname = mangler.mangle(sym.fullname, Mangle.Type.CLASS);
   210             println(out, fileTop());
   211             println(out, includes());
   212             println(out, guardBegin(cname));
   213             println(out, cppGuardBegin());
   215             writeStatics(out, sym);
   216             writeMethods(out, sym, cname);
   218             println(out, cppGuardEnd());
   219             println(out, guardEnd(cname));
   220         } catch (TypeSignature.SignatureException e) {
   221             throw new IOException(e);
   222         }
   223     }
   225     protected void writeStatics(Writer out, ClassSymbol sym) throws IOException {
   226         List<VariableElement> classfields = getAllFields(sym);
   228         for (VariableElement v: classfields) {
   229             if (!v.getModifiers().contains(Modifier.STATIC))
   230                 continue;
   231             String s = null;
   232             s = defineForStatic(sym, v);
   233             if (s != null) {
   234                 println(out, s);
   235             }
   236         }
   237     }
   239     /**
   240      * Including super class fields.
   241      */
   242     List<VariableElement> getAllFields(TypeElement subclazz) {
   243         List<VariableElement> fields = new ArrayList<VariableElement>();
   244         TypeElement cd = null;
   245         Stack<TypeElement> s = new Stack<TypeElement>();
   247         cd = subclazz;
   248         while (true) {
   249             s.push(cd);
   250             TypeElement c = (TypeElement) (types.asElement(cd.getSuperclass()));
   251             if (c == null)
   252                 break;
   253             cd = c;
   254         }
   256         while (!s.empty()) {
   257             cd = s.pop();
   258             fields.addAll(ElementFilter.fieldsIn(cd.getEnclosedElements()));
   259         }
   261         return fields;
   262     }
   264     protected String defineForStatic(TypeElement c, VariableElement f) {
   265         CharSequence cnamedoc = c.getQualifiedName();
   266         CharSequence fnamedoc = f.getSimpleName();
   268         String cname = mangler.mangle(cnamedoc, Mangle.Type.CLASS);
   269         String fname = mangler.mangle(fnamedoc, Mangle.Type.FIELDSTUB);
   271         Assert.check(f.getModifiers().contains(Modifier.STATIC));
   273         if (f.getModifiers().contains(Modifier.FINAL)) {
   274             Object value = null;
   276             value = f.getConstantValue();
   278             if (value != null) { /* so it is a ConstantExpression */
   279                 String constString = null;
   280                 if ((value instanceof Integer)
   281                     || (value instanceof Byte)
   282                     || (value instanceof Short)) {
   283                     /* covers byte, short, int */
   284                     constString = value.toString() + "L";
   285                 } else if (value instanceof Boolean) {
   286                     constString = ((Boolean) value) ? "1L" : "0L";
   287                 } else if (value instanceof Character) {
   288                     Character ch = (Character) value;
   289                     constString = String.valueOf(((int) ch) & 0xffff) + "L";
   290                 } else if (value instanceof Long) {
   291                     // Visual C++ supports the i64 suffix, not LL.
   292                     if (isWindows)
   293                         constString = value.toString() + "i64";
   294                     else
   295                         constString = value.toString() + "LL";
   296                 } else if (value instanceof Float) {
   297                     /* bug for bug */
   298                     float fv = ((Float)value).floatValue();
   299                     if (Float.isInfinite(fv))
   300                         constString = ((fv < 0) ? "-" : "") + "Inff";
   301                     else
   302                         constString = value.toString() + "f";
   303                 } else if (value instanceof Double) {
   304                     /* bug for bug */
   305                     double d = ((Double)value).doubleValue();
   306                     if (Double.isInfinite(d))
   307                         constString = ((d < 0) ? "-" : "") + "InfD";
   308                     else
   309                         constString = value.toString();
   310                 }
   312                 if (constString != null) {
   313                     StringBuilder s = new StringBuilder("#undef ");
   314                     s.append(cname); s.append("_"); s.append(fname); s.append(lineSep);
   315                     s.append("#define "); s.append(cname); s.append("_");
   316                     s.append(fname); s.append(" "); s.append(constString);
   317                     return s.toString();
   318                 }
   320             }
   321         }
   323         return null;
   324     }
   327     protected void writeMethods(Writer out, ClassSymbol sym, String cname)
   328             throws IOException, TypeSignature.SignatureException {
   329         List<ExecutableElement> classmethods = ElementFilter.methodsIn(sym.getEnclosedElements());
   330         for (ExecutableElement md: classmethods) {
   331             if(md.getModifiers().contains(Modifier.NATIVE)){
   332                 TypeMirror mtr = types.erasure(md.getReturnType());
   333                 String sig = signature(md);
   334                 TypeSignature newtypesig = new TypeSignature(elements);
   335                 CharSequence methodName = md.getSimpleName();
   336                 boolean longName = false;
   337                 for (ExecutableElement md2: classmethods) {
   338                     if ((md2 != md)
   339                         && (methodName.equals(md2.getSimpleName()))
   340                         && (md2.getModifiers().contains(Modifier.NATIVE)))
   341                         longName = true;
   343                 }
   344                 println(out, "/*");
   345                 println(out, " * Class:     " + cname);
   346                 println(out, " * Method:    " +
   347                            mangler.mangle(methodName, Mangle.Type.FIELDSTUB));
   348                 println(out, " * Signature: " + newtypesig.getTypeSignature(sig, mtr));
   349                 println(out, " */");
   350                 println(out, "JNIEXPORT " + jniType(mtr) +
   351                            " JNICALL " +
   352                            mangler.mangleMethod(md, sym,
   353                                                (longName) ?
   354                                                Mangle.Type.METHOD_JNI_LONG :
   355                                                Mangle.Type.METHOD_JNI_SHORT));
   356                 print(out, "  (JNIEnv *, ");
   357                 List<? extends VariableElement> paramargs = md.getParameters();
   358                 List<TypeMirror> args = new ArrayList<TypeMirror>();
   359                 for (VariableElement p: paramargs) {
   360                     args.add(types.erasure(p.asType()));
   361                 }
   362                 if (md.getModifiers().contains(Modifier.STATIC))
   363                     print(out, "jclass");
   364                 else
   365                     print(out, "jobject");
   367                 for (TypeMirror arg: args) {
   368                     print(out, ", ");
   369                     print(out, jniType(arg));
   370                 }
   371                 println(out, ");"
   372                         + lineSep);
   373             }
   374         }
   375     }
   377     // c.f. MethodDoc.signature
   378     String signature(ExecutableElement e) {
   379         StringBuilder sb = new StringBuilder("(");
   380         String sep = "";
   381         for (VariableElement p: e.getParameters()) {
   382             sb.append(sep);
   383             sb.append(types.erasure(p.asType()).toString());
   384             sep = ",";
   385         }
   386         sb.append(")");
   387         return sb.toString();
   388     }
   390     protected final String jniType(TypeMirror t) {
   391         TypeElement throwable = elements.getTypeElement("java.lang.Throwable");
   392         TypeElement jClass = elements.getTypeElement("java.lang.Class");
   393         TypeElement jString = elements.getTypeElement("java.lang.String");
   394         Element tclassDoc = types.asElement(t);
   397         switch (t.getKind()) {
   398             case ARRAY: {
   399                 TypeMirror ct = ((ArrayType) t).getComponentType();
   400                 switch (ct.getKind()) {
   401                     case BOOLEAN:  return "jbooleanArray";
   402                     case BYTE:     return "jbyteArray";
   403                     case CHAR:     return "jcharArray";
   404                     case SHORT:    return "jshortArray";
   405                     case INT:      return "jintArray";
   406                     case LONG:     return "jlongArray";
   407                     case FLOAT:    return "jfloatArray";
   408                     case DOUBLE:   return "jdoubleArray";
   409                     case ARRAY:
   410                     case DECLARED: return "jobjectArray";
   411                     default: throw new Error(ct.toString());
   412                 }
   413             }
   415             case VOID:     return "void";
   416             case BOOLEAN:  return "jboolean";
   417             case BYTE:     return "jbyte";
   418             case CHAR:     return "jchar";
   419             case SHORT:    return "jshort";
   420             case INT:      return "jint";
   421             case LONG:     return "jlong";
   422             case FLOAT:    return "jfloat";
   423             case DOUBLE:   return "jdouble";
   425             case DECLARED: {
   426                 if (tclassDoc.equals(jString))
   427                     return "jstring";
   428                 else if (types.isAssignable(t, throwable.asType()))
   429                     return "jthrowable";
   430                 else if (types.isAssignable(t, jClass.asType()))
   431                     return "jclass";
   432                 else
   433                     return "jobject";
   434             }
   435         }
   437         Assert.check(false, "jni unknown type");
   438         return null; /* dead code. */
   439     }
   441     protected String fileTop() {
   442         return "/* DO NOT EDIT THIS FILE - it is machine generated */";
   443     }
   445     protected String includes() {
   446         return "#include <jni.h>";
   447     }
   449     /*
   450      * Deal with the C pre-processor.
   451      */
   452     protected String cppGuardBegin() {
   453         return "#ifdef __cplusplus" + lineSep
   454                 + "extern \"C\" {" + lineSep
   455                 + "#endif";
   456     }
   458     protected String cppGuardEnd() {
   459         return "#ifdef __cplusplus" + lineSep
   460                 + "}" + lineSep
   461                 + "#endif";
   462     }
   464     protected String guardBegin(String cname) {
   465         return "/* Header for class " + cname + " */" + lineSep
   466                 + lineSep
   467                 + "#ifndef _Included_" + cname + lineSep
   468                 + "#define _Included_" + cname;
   469     }
   471     protected String guardEnd(String cname) {
   472         return "#endif";
   473     }
   475     protected void print(Writer out, String text) throws IOException {
   476         out.write(text);
   477     }
   479     protected void println(Writer out, String text) throws IOException {
   480         out.write(text);
   481         out.write(lineSep);
   482     }
   485     private static class Mangle {
   487         public static class Type {
   488             public static final int CLASS            = 1;
   489             public static final int FIELDSTUB        = 2;
   490             public static final int FIELD            = 3;
   491             public static final int JNI              = 4;
   492             public static final int SIGNATURE        = 5;
   493             public static final int METHOD_JDK_1     = 6;
   494             public static final int METHOD_JNI_SHORT = 7;
   495             public static final int METHOD_JNI_LONG  = 8;
   496         };
   498         private Elements elems;
   499         private Types types;
   501         Mangle(Elements elems, Types types) {
   502             this.elems = elems;
   503             this.types = types;
   504         }
   506         public final String mangle(CharSequence name, int mtype) {
   507             StringBuilder result = new StringBuilder(100);
   508             int length = name.length();
   510             for (int i = 0; i < length; i++) {
   511                 char ch = name.charAt(i);
   512                 if (isalnum(ch)) {
   513                     result.append(ch);
   514                 } else if ((ch == '.') &&
   515                            mtype == Mangle.Type.CLASS) {
   516                     result.append('_');
   517                 } else if (( ch == '$') &&
   518                            mtype == Mangle.Type.CLASS) {
   519                     result.append('_');
   520                     result.append('_');
   521                 } else if (ch == '_' && mtype == Mangle.Type.FIELDSTUB) {
   522                     result.append('_');
   523                 } else if (ch == '_' && mtype == Mangle.Type.CLASS) {
   524                     result.append('_');
   525                 } else if (mtype == Mangle.Type.JNI) {
   526                     String esc = null;
   527                     if (ch == '_')
   528                         esc = "_1";
   529                     else if (ch == '.')
   530                         esc = "_";
   531                     else if (ch == ';')
   532                         esc = "_2";
   533                     else if (ch == '[')
   534                         esc = "_3";
   535                     if (esc != null) {
   536                         result.append(esc);
   537                     } else {
   538                         result.append(mangleChar(ch));
   539                     }
   540                 } else if (mtype == Mangle.Type.SIGNATURE) {
   541                     if (isprint(ch)) {
   542                         result.append(ch);
   543                     } else {
   544                         result.append(mangleChar(ch));
   545                     }
   546                 } else {
   547                     result.append(mangleChar(ch));
   548                 }
   549             }
   551             return result.toString();
   552         }
   554         public String mangleMethod(ExecutableElement method, TypeElement clazz,
   555                                           int mtype) throws TypeSignature.SignatureException {
   556             StringBuilder result = new StringBuilder(100);
   557             result.append("Java_");
   559             if (mtype == Mangle.Type.METHOD_JDK_1) {
   560                 result.append(mangle(clazz.getQualifiedName(), Mangle.Type.CLASS));
   561                 result.append('_');
   562                 result.append(mangle(method.getSimpleName(),
   563                                      Mangle.Type.FIELD));
   564                 result.append("_stub");
   565                 return result.toString();
   566             }
   568             /* JNI */
   569             result.append(mangle(getInnerQualifiedName(clazz), Mangle.Type.JNI));
   570             result.append('_');
   571             result.append(mangle(method.getSimpleName(),
   572                                  Mangle.Type.JNI));
   573             if (mtype == Mangle.Type.METHOD_JNI_LONG) {
   574                 result.append("__");
   575                 String typesig = signature(method);
   576                 TypeSignature newTypeSig = new TypeSignature(elems);
   577                 String sig = newTypeSig.getTypeSignature(typesig,  method.getReturnType());
   578                 sig = sig.substring(1);
   579                 sig = sig.substring(0, sig.lastIndexOf(')'));
   580                 sig = sig.replace('/', '.');
   581                 result.append(mangle(sig, Mangle.Type.JNI));
   582             }
   584             return result.toString();
   585         }
   586         //where
   587             private String getInnerQualifiedName(TypeElement clazz) {
   588                 return elems.getBinaryName(clazz).toString();
   589             }
   591         public final String mangleChar(char ch) {
   592             String s = Integer.toHexString(ch);
   593             int nzeros = 5 - s.length();
   594             char[] result = new char[6];
   595             result[0] = '_';
   596             for (int i = 1; i <= nzeros; i++)
   597                 result[i] = '0';
   598             for (int i = nzeros+1, j = 0; i < 6; i++, j++)
   599                 result[i] = s.charAt(j);
   600             return new String(result);
   601         }
   603         // Warning: duplicated in Gen
   604         private String signature(ExecutableElement e) {
   605             StringBuilder sb = new StringBuilder();
   606             String sep = "(";
   607             for (VariableElement p: e.getParameters()) {
   608                 sb.append(sep);
   609                 sb.append(types.erasure(p.asType()).toString());
   610                 sep = ",";
   611             }
   612             sb.append(")");
   613             return sb.toString();
   614         }
   616         /* Warning: Intentional ASCII operation. */
   617         private static boolean isalnum(char ch) {
   618             return ch <= 0x7f && /* quick test */
   619                 ((ch >= 'A' && ch <= 'Z') ||
   620                  (ch >= 'a' && ch <= 'z') ||
   621                  (ch >= '0' && ch <= '9'));
   622         }
   624         /* Warning: Intentional ASCII operation. */
   625         private static boolean isprint(char ch) {
   626             return ch >= 32 && ch <= 126;
   627         }
   628     }
   630     private static class TypeSignature {
   631         static class SignatureException extends Exception {
   632             private static final long serialVersionUID = 1L;
   633             SignatureException(String reason) {
   634                 super(reason);
   635             }
   636         }
   638         Elements elems;
   640         /* Signature Characters */
   642         private static final String SIG_VOID                   = "V";
   643         private static final String SIG_BOOLEAN                = "Z";
   644         private static final String SIG_BYTE                   = "B";
   645         private static final String SIG_CHAR                   = "C";
   646         private static final String SIG_SHORT                  = "S";
   647         private static final String SIG_INT                    = "I";
   648         private static final String SIG_LONG                   = "J";
   649         private static final String SIG_FLOAT                  = "F";
   650         private static final String SIG_DOUBLE                 = "D";
   651         private static final String SIG_ARRAY                  = "[";
   652         private static final String SIG_CLASS                  = "L";
   656         public TypeSignature(Elements elems){
   657             this.elems = elems;
   658         }
   660         /*
   661          * Returns the type signature of a field according to JVM specs
   662          */
   663         public String getTypeSignature(String javasignature) throws SignatureException {
   664             return getParamJVMSignature(javasignature);
   665         }
   667         /*
   668          * Returns the type signature of a method according to JVM specs
   669          */
   670         public String getTypeSignature(String javasignature, TypeMirror returnType)
   671                 throws SignatureException {
   672             String signature = null; //Java type signature.
   673             String typeSignature = null; //Internal type signature.
   674             List<String> params = new ArrayList<String>(); //List of parameters.
   675             String paramsig = null; //Java parameter signature.
   676             String paramJVMSig = null; //Internal parameter signature.
   677             String returnSig = null; //Java return type signature.
   678             String returnJVMType = null; //Internal return type signature.
   679             int dimensions = 0; //Array dimension.
   681             int startIndex = -1;
   682             int endIndex = -1;
   683             StringTokenizer st = null;
   684             int i = 0;
   686             // Gets the actual java signature without parentheses.
   687             if (javasignature != null) {
   688                 startIndex = javasignature.indexOf("(");
   689                 endIndex = javasignature.indexOf(")");
   690             }
   692             if (((startIndex != -1) && (endIndex != -1))
   693                 &&(startIndex+1 < javasignature.length())
   694                 &&(endIndex < javasignature.length())) {
   695                 signature = javasignature.substring(startIndex+1, endIndex);
   696             }
   698             // Separates parameters.
   699             if (signature != null) {
   700                 if (signature.indexOf(",") != -1) {
   701                     st = new StringTokenizer(signature, ",");
   702                     if (st != null) {
   703                         while (st.hasMoreTokens()) {
   704                             params.add(st.nextToken());
   705                         }
   706                     }
   707                 } else {
   708                     params.add(signature);
   709                 }
   710             }
   712             /* JVM type signature. */
   713             typeSignature = "(";
   715             // Gets indivisual internal parameter signature.
   716             while (params.isEmpty() != true) {
   717                 paramsig = params.remove(i).trim();
   718                 paramJVMSig  = getParamJVMSignature(paramsig);
   719                 if (paramJVMSig != null) {
   720                     typeSignature += paramJVMSig;
   721                 }
   722             }
   724             typeSignature += ")";
   726             // Get internal return type signature.
   728             returnJVMType = "";
   729             if (returnType != null) {
   730                 dimensions = dimensions(returnType);
   731             }
   733             //Gets array dimension of return type.
   734             while (dimensions-- > 0) {
   735                 returnJVMType += "[";
   736             }
   737             if (returnType != null) {
   738                 returnSig = qualifiedTypeName(returnType);
   739                 returnJVMType += getComponentType(returnSig);
   740             } else {
   741                 System.out.println("Invalid return type.");
   742             }
   744             typeSignature += returnJVMType;
   746             return typeSignature;
   747         }
   749         /*
   750          * Returns internal signature of a parameter.
   751          */
   752         private String getParamJVMSignature(String paramsig) throws SignatureException {
   753             String paramJVMSig = "";
   754             String componentType ="";
   756             if(paramsig != null){
   758                 if(paramsig.indexOf("[]") != -1) {
   759                     // Gets array dimension.
   760                     int endindex = paramsig.indexOf("[]");
   761                     componentType = paramsig.substring(0, endindex);
   762                     String dimensionString =  paramsig.substring(endindex);
   763                     if(dimensionString != null){
   764                         while(dimensionString.indexOf("[]") != -1){
   765                             paramJVMSig += "[";
   766                             int beginindex = dimensionString.indexOf("]") + 1;
   767                             if(beginindex < dimensionString.length()){
   768                                 dimensionString = dimensionString.substring(beginindex);
   769                             }else
   770                                 dimensionString = "";
   771                         }
   772                     }
   773                 } else componentType = paramsig;
   775                 paramJVMSig += getComponentType(componentType);
   776             }
   777             return paramJVMSig;
   778         }
   780         /*
   781          * Returns internal signature of a component.
   782          */
   783         private String getComponentType(String componentType) throws SignatureException {
   785             String JVMSig = "";
   787             if(componentType != null){
   788                 if(componentType.equals("void")) JVMSig += SIG_VOID ;
   789                 else if(componentType.equals("boolean"))  JVMSig += SIG_BOOLEAN ;
   790                 else if(componentType.equals("byte")) JVMSig += SIG_BYTE ;
   791                 else if(componentType.equals("char"))  JVMSig += SIG_CHAR ;
   792                 else if(componentType.equals("short"))  JVMSig += SIG_SHORT ;
   793                 else if(componentType.equals("int"))  JVMSig += SIG_INT ;
   794                 else if(componentType.equals("long"))  JVMSig += SIG_LONG ;
   795                 else if(componentType.equals("float")) JVMSig += SIG_FLOAT ;
   796                 else if(componentType.equals("double"))  JVMSig += SIG_DOUBLE ;
   797                 else {
   798                     if(!componentType.equals("")){
   799                         TypeElement classNameDoc = elems.getTypeElement(componentType);
   801                         if(classNameDoc == null){
   802                             throw new SignatureException(componentType);
   803                         }else {
   804                             String classname = classNameDoc.getQualifiedName().toString();
   805                             String newclassname = classname.replace('.', '/');
   806                             JVMSig += "L";
   807                             JVMSig += newclassname;
   808                             JVMSig += ";";
   809                         }
   810                     }
   811                 }
   812             }
   813             return JVMSig;
   814         }
   816         int dimensions(TypeMirror t) {
   817             if (t.getKind() != TypeKind.ARRAY)
   818                 return 0;
   819             return 1 + dimensions(((ArrayType) t).getComponentType());
   820         }
   823         String qualifiedTypeName(TypeMirror type) {
   824             TypeVisitor<Name, Void> v = new SimpleTypeVisitor8<Name, Void>() {
   825                 @Override
   826                 public Name visitArray(ArrayType t, Void p) {
   827                     return t.getComponentType().accept(this, p);
   828                 }
   830                 @Override
   831                 public Name visitDeclared(DeclaredType t, Void p) {
   832                     return ((TypeElement) t.asElement()).getQualifiedName();
   833                 }
   835                 @Override
   836                 public Name visitPrimitive(PrimitiveType t, Void p) {
   837                     return elems.getName(t.toString());
   838                 }
   840                 @Override
   841                 public Name visitNoType(NoType t, Void p) {
   842                     if (t.getKind() == TypeKind.VOID)
   843                         return elems.getName("void");
   844                     return defaultAction(t, p);
   845                 }
   847                 @Override
   848                 public Name visitTypeVariable(TypeVariable t, Void p) {
   849                     return t.getUpperBound().accept(this, p);
   850                 }
   851             };
   852             return v.visit(type).toString();
   853         }
   854     }
   856 }

mercurial