001    /*
002     * Copyright 2002-2005 Sun Microsystems, Inc.  All Rights Reserved.
003     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004     *
005     * This code is free software; you can redistribute it and/or modify it
006     * under the terms of the GNU General Public License version 2 only, as
007     * published by the Free Software Foundation.  Sun designates this
008     * particular file as subject to the "Classpath" exception as provided
009     * by Sun in the LICENSE file that accompanied this code.
010     *
011     * This code is distributed in the hope that it will be useful, but WITHOUT
012     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014     * version 2 for more details (a copy is included in the LICENSE file that
015     * accompanied this code).
016     *
017     * You should have received a copy of the GNU General Public License version
018     * 2 along with this work; if not, write to the Free Software Foundation,
019     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020     *
021     * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022     * CA 95054 USA or visit www.sun.com if you need additional information or
023     * have any questions.
024     */
025    
026    package com.sun.tools.javah;
027    
028    import java.io.OutputStream;
029    import java.io.PrintWriter;
030    import java.util.Vector;
031    import java.util.Enumeration;
032    import com.sun.javadoc.*;
033    
034    
035    /**
036     * Header file generator for JNI.
037     *
038     * @author  Sucheta Dambalkar(Revised)
039     */
040    
041    public class JNI extends Gen {
042    
043        public JNI(RootDoc root){
044            super(root);
045        }
046    
047        public String getIncludes() {
048            return "#include <jni.h>";
049        }
050    
051        public void write(OutputStream o, ClassDoc clazz)
052            throws ClassNotFoundException {
053    
054            String cname = Mangle.mangle(clazz.qualifiedName(), Mangle.Type.CLASS);
055            PrintWriter pw = wrapWriter(o);
056            pw.println(guardBegin(cname));
057            pw.println(cppGuardBegin());
058    
059            /* Write statics. */
060            FieldDoc[] classfields = getAllFields(clazz);
061    
062            for (int i = 0; i < classfields.length; i++) {
063                if (!classfields[i].isStatic())
064                    continue;
065                String s = null;
066                s = defineForStatic(clazz, classfields[i]);
067                if (s != null) {
068                    pw.println(s);
069                }
070            }
071    
072            /* Write methods. */
073            MethodDoc[] classmethods = clazz.methods();
074            for (int i = 0; i < classmethods.length; i++) {
075                if(classmethods[i].isNative()){
076                    MethodDoc md = classmethods[i];
077                    Type mtr = classmethods[i].returnType();
078                    String sig = md.signature();
079                    TypeSignature newtypesig = new TypeSignature(root);
080                    String methodName = md.name();
081                    boolean longName = false;
082                    for (int j = 0; j < classmethods.length; j++) {
083                        if ((classmethods[j] != md)
084                            && (methodName.equals(classmethods[j].name()))
085                            && (classmethods[j].isNative()))
086                            longName = true;
087    
088                    }
089                    pw.println("/*");
090                    pw.println(" * Class:     " + cname);
091                    pw.println(" * Method:    " +
092                               Mangle.mangle(methodName, Mangle.Type.FIELDSTUB));
093                    pw.println(" * Signature: " + newtypesig.getTypeSignature(sig, mtr));
094                    pw.println(" */");
095                    pw.println("JNIEXPORT " + jniType(mtr) +
096                               " JNICALL " +
097                               Mangle.mangleMethod(md, root,clazz,
098                                                   (longName) ?
099                                                   Mangle.Type.METHOD_JNI_LONG :
100                                                   Mangle.Type.METHOD_JNI_SHORT));
101                    pw.print("  (JNIEnv *, ");
102                    Parameter[] paramargs = md.parameters();
103                    Type []args =new Type[ paramargs.length];
104                    for(int p = 0; p < paramargs.length; p++){
105                        args[p] = paramargs[p].type();
106                    }
107                    if (md.isStatic())
108                        pw.print("jclass");
109                    else
110                        pw.print("jobject");
111                    if (args.length > 0)
112                        pw.print(", ");
113    
114                    for (int j = 0; j < args.length; j++) {
115                        pw.print(jniType(args[j]));
116                        if (j != (args.length - 1)) {
117                            pw.print(", ");
118                        }
119                    }
120                    pw.println(");" + lineSep);
121                }
122            }
123            pw.println(cppGuardEnd());
124            pw.println(guardEnd(cname));
125        }
126    
127    
128        protected final String jniType(Type t){
129    
130            String elmT = t.typeName();
131            ClassDoc throwable = root.classNamed("java.lang.Throwable");
132            ClassDoc jClass = root.classNamed("java.lang.Class");
133            ClassDoc tclassDoc = t.asClassDoc();
134    
135            if((t.dimension()).indexOf("[]") != -1){
136                if((t.dimension().indexOf("[][]") != -1)
137                   || (tclassDoc != null))  return "jobjectArray";
138                else if(elmT.equals("boolean"))return  "jbooleanArray";
139                else if(elmT.equals("byte"))return  "jbyteArray";
140                else if(elmT.equals("char"))return  "jcharArray";
141                else if(elmT.equals("short"))return  "jshortArray";
142                else if(elmT.equals("int"))return  "jintArray";
143                else if(elmT.equals("long"))return  "jlongArray";
144                else if(elmT.equals("float"))return  "jfloatArray";
145                else if(elmT.equals("double"))return  "jdoubleArray";
146            }else{
147                if(elmT.equals("void"))return  "void";
148                else if(elmT.equals("String"))return  "jstring";
149                else if(elmT.equals("boolean"))return  "jboolean";
150                else if(elmT.equals("byte"))return  "jbyte";
151                else if(elmT.equals("char"))return  "jchar";
152                else if(elmT.equals("short"))return  "jshort";
153                else if(elmT.equals("int"))return  "jint";
154                else if(elmT.equals("long"))return  "jlong";
155                else if(elmT.equals("float"))return  "jfloat";
156                else if(elmT.equals("double"))return  "jdouble";
157                else  if(tclassDoc  != null){
158                    if(tclassDoc.subclassOf(throwable)) return "jthrowable";
159                    else if(tclassDoc.subclassOf(jClass)) return "jclass";
160                    else return "jobject";
161                }
162            }
163            Util.bug("jni.unknown.type");
164            return null; /* dead code. */
165        }
166    }