Fri, 14 Jun 2013 16:25:09 +0100
8016569: javac, add new flag for polymorphic method signatures
Reviewed-by: jjg
Contributed-by: maurizio.cimadamore@oracle.com
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.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 }