duke@1: /*
ohair@798: * Copyright (c) 2002, 2010, 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: package com.sun.tools.javah;
duke@1:
duke@1: import java.io.OutputStream;
duke@1: import java.io.PrintWriter;
jjg@416: import java.util.ArrayList;
jjg@416: import java.util.List;
jjg@416: import javax.lang.model.element.Element;
jjg@416: import javax.lang.model.element.ExecutableElement;
jjg@416: import javax.lang.model.element.Modifier;
jjg@416: import javax.lang.model.element.TypeElement;
jjg@416: import javax.lang.model.element.VariableElement;
jjg@416: import javax.lang.model.type.ArrayType;
jjg@416: import javax.lang.model.type.TypeMirror;
jjg@416: import javax.lang.model.util.ElementFilter;
duke@1:
duke@1:
duke@1: /**
duke@1: * Header file generator for JNI.
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(Revised)
duke@1: */
duke@1: public class JNI extends Gen {
jjg@416: JNI(Util util) {
jjg@416: super(util);
duke@1: }
duke@1:
duke@1: public String getIncludes() {
duke@1: return "#include ";
duke@1: }
duke@1:
jjg@416: public void write(OutputStream o, TypeElement clazz) throws Util.Exit {
jjg@712: try {
jjg@712: String cname = mangler.mangle(clazz.getQualifiedName(), Mangle.Type.CLASS);
jjg@712: PrintWriter pw = wrapWriter(o);
jjg@712: pw.println(guardBegin(cname));
jjg@712: pw.println(cppGuardBegin());
duke@1:
jjg@712: /* Write statics. */
jjg@712: List classfields = getAllFields(clazz);
duke@1:
jjg@712: for (VariableElement v: classfields) {
jjg@712: if (!v.getModifiers().contains(Modifier.STATIC))
jjg@712: continue;
jjg@712: String s = null;
jjg@712: s = defineForStatic(clazz, v);
jjg@712: if (s != null) {
jjg@712: pw.println(s);
jjg@712: }
duke@1: }
jjg@712:
jjg@712: /* Write methods. */
jjg@712: List classmethods = ElementFilter.methodsIn(clazz.getEnclosedElements());
jjg@712: for (ExecutableElement md: classmethods) {
jjg@712: if(md.getModifiers().contains(Modifier.NATIVE)){
jjg@712: TypeMirror mtr = types.erasure(md.getReturnType());
jjg@712: String sig = signature(md);
jjg@712: TypeSignature newtypesig = new TypeSignature(elems);
jjg@712: CharSequence methodName = md.getSimpleName();
jjg@712: boolean longName = false;
jjg@712: for (ExecutableElement md2: classmethods) {
jjg@712: if ((md2 != md)
jjg@712: && (methodName.equals(md2.getSimpleName()))
jjg@712: && (md2.getModifiers().contains(Modifier.NATIVE)))
jjg@712: longName = true;
jjg@712:
jjg@712: }
jjg@712: pw.println("/*");
jjg@712: pw.println(" * Class: " + cname);
jjg@712: pw.println(" * Method: " +
jjg@712: mangler.mangle(methodName, Mangle.Type.FIELDSTUB));
jjg@712: pw.println(" * Signature: " + newtypesig.getTypeSignature(sig, mtr));
jjg@712: pw.println(" */");
jjg@712: pw.println("JNIEXPORT " + jniType(mtr) +
jjg@712: " JNICALL " +
jjg@712: mangler.mangleMethod(md, clazz,
jjg@712: (longName) ?
jjg@712: Mangle.Type.METHOD_JNI_LONG :
jjg@712: Mangle.Type.METHOD_JNI_SHORT));
jjg@712: pw.print(" (JNIEnv *, ");
jjg@712: List extends VariableElement> paramargs = md.getParameters();
jjg@712: List args = new ArrayList();
jjg@712: for (VariableElement p: paramargs) {
jjg@712: args.add(types.erasure(p.asType()));
jjg@712: }
jjg@712: if (md.getModifiers().contains(Modifier.STATIC))
jjg@712: pw.print("jclass");
jjg@712: else
jjg@712: pw.print("jobject");
jjg@712:
jjg@712: for (TypeMirror arg: args) {
jjg@712: pw.print(", ");
jjg@712: pw.print(jniType(arg));
jjg@712: }
jjg@712: pw.println(");" + lineSep);
jjg@712: }
jjg@712: }
jjg@712: pw.println(cppGuardEnd());
jjg@712: pw.println(guardEnd(cname));
jjg@712: } catch (TypeSignature.SignatureException e) {
jjg@712: util.error("jni.sigerror", e.getMessage());
duke@1: }
duke@1: }
duke@1:
duke@1:
jjg@416: protected final String jniType(TypeMirror t) throws Util.Exit {
jjg@416: TypeElement throwable = elems.getTypeElement("java.lang.Throwable");
jjg@416: TypeElement jClass = elems.getTypeElement("java.lang.Class");
jjg@416: TypeElement jString = elems.getTypeElement("java.lang.String");
jjg@416: Element tclassDoc = types.asElement(t);
duke@1:
duke@1:
jjg@416: switch (t.getKind()) {
jjg@416: case ARRAY: {
jjg@416: TypeMirror ct = ((ArrayType) t).getComponentType();
jjg@416: switch (ct.getKind()) {
jjg@416: case BOOLEAN: return "jbooleanArray";
jjg@416: case BYTE: return "jbyteArray";
jjg@416: case CHAR: return "jcharArray";
jjg@416: case SHORT: return "jshortArray";
jjg@416: case INT: return "jintArray";
jjg@416: case LONG: return "jlongArray";
jjg@416: case FLOAT: return "jfloatArray";
jjg@416: case DOUBLE: return "jdoubleArray";
jjg@416: case ARRAY:
jjg@416: case DECLARED: return "jobjectArray";
jjg@416: default: throw new Error(ct.toString());
jjg@416: }
jjg@416: }
jjg@416:
jjg@416: case VOID: return "void";
jjg@416: case BOOLEAN: return "jboolean";
jjg@416: case BYTE: return "jbyte";
jjg@416: case CHAR: return "jchar";
jjg@416: case SHORT: return "jshort";
jjg@416: case INT: return "jint";
jjg@416: case LONG: return "jlong";
jjg@416: case FLOAT: return "jfloat";
jjg@416: case DOUBLE: return "jdouble";
jjg@416:
jjg@416: case DECLARED: {
jjg@416: if (tclassDoc.equals(jString))
jjg@416: return "jstring";
jjg@416: else if (types.isAssignable(t, throwable.asType()))
jjg@416: return "jthrowable";
jjg@416: else if (types.isAssignable(t, jClass.asType()))
jjg@416: return "jclass";
jjg@416: else
jjg@416: return "jobject";
duke@1: }
duke@1: }
jjg@416:
jjg@416: util.bug("jni.unknown.type");
duke@1: return null; /* dead code. */
duke@1: }
duke@1: }