alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (LLNI.java)

This example Java source code file (LLNI.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

boolean, byte, double, fielddefsres, float, list, long, short, string, typeelement, typemirror, typesignature, util, variableelement, void

The LLNI.java Java example source code

/*
 * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */


package com.sun.tools.javah;

import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

import java.util.Set;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.PrimitiveType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVisitor;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.SimpleTypeVisitor8;

/*
 * <p>This is NOT part of any supported API.
 * If you write code that depends on this, you do so at your own
 * risk.  This code and its internal interfaces are subject to change
 * or deletion without notice.</b>

* * @author Sucheta Dambalkar(Revised) */ public class LLNI extends Gen { protected final char innerDelim = '$'; /* For inner classes */ protected Set<String> doneHandleTypes; List<VariableElement> fields; List<ExecutableElement> methods; private boolean doubleAlign; private int padFieldNum = 0; LLNI(boolean doubleAlign, Util util) { super(util); this.doubleAlign = doubleAlign; } protected String getIncludes() { return ""; } protected void write(OutputStream o, TypeElement clazz) throws Util.Exit { try { String cname = mangleClassName(clazz.getQualifiedName().toString()); PrintWriter pw = wrapWriter(o); fields = ElementFilter.fieldsIn(clazz.getEnclosedElements()); methods = ElementFilter.methodsIn(clazz.getEnclosedElements()); generateDeclsForClass(pw, clazz, cname); // FIXME check if errors occurred on the PrintWriter and throw exception if so } catch (TypeSignature.SignatureException e) { util.error("llni.sigerror", e.getMessage()); } } protected void generateDeclsForClass(PrintWriter pw, TypeElement clazz, String cname) throws TypeSignature.SignatureException, Util.Exit { doneHandleTypes = new HashSet<String>(); /* The following handle types are predefined in "typedefs.h". Suppress inclusion in the output by generating them "into the blue" here. */ genHandleType(null, "java.lang.Class"); genHandleType(null, "java.lang.ClassLoader"); genHandleType(null, "java.lang.Object"); genHandleType(null, "java.lang.String"); genHandleType(null, "java.lang.Thread"); genHandleType(null, "java.lang.ThreadGroup"); genHandleType(null, "java.lang.Throwable"); pw.println("/* LLNI Header for class " + clazz.getQualifiedName() + " */" + lineSep); pw.println("#ifndef _Included_" + cname); pw.println("#define _Included_" + cname); pw.println("#include \"typedefs.h\""); pw.println("#include \"llni.h\""); pw.println("#include \"jni.h\"" + lineSep); forwardDecls(pw, clazz); structSectionForClass(pw, clazz, cname); methodSectionForClass(pw, clazz, cname); pw.println("#endif"); } protected void genHandleType(PrintWriter pw, String clazzname) { String cname = mangleClassName(clazzname); if (!doneHandleTypes.contains(cname)) { doneHandleTypes.add(cname); if (pw != null) { pw.println("#ifndef DEFINED_" + cname); pw.println(" #define DEFINED_" + cname); pw.println(" GEN_HANDLE_TYPES(" + cname + ");"); pw.println("#endif" + lineSep); } } } protected String mangleClassName(String s) { return s.replace('.', '_') .replace('/', '_') .replace(innerDelim, '_'); } protected void forwardDecls(PrintWriter pw, TypeElement clazz) throws TypeSignature.SignatureException { TypeElement object = elems.getTypeElement("java.lang.Object"); if (clazz.equals(object)) return; genHandleType(pw, clazz.getQualifiedName().toString()); TypeElement superClass = (TypeElement) (types.asElement(clazz.getSuperclass())); if (superClass != null) { String superClassName = superClass.getQualifiedName().toString(); forwardDecls(pw, superClass); } for (VariableElement field: fields) { if (!field.getModifiers().contains(Modifier.STATIC)) { TypeMirror t = types.erasure(field.asType()); TypeSignature newTypeSig = new TypeSignature(elems); String tname = newTypeSig.qualifiedTypeName(t); String sig = newTypeSig.getTypeSignature(tname); if (sig.charAt(0) != '[') forwardDeclsFromSig(pw, sig); } } for (ExecutableElement method: methods) { if (method.getModifiers().contains(Modifier.NATIVE)) { TypeMirror retType = types.erasure(method.getReturnType()); String typesig = signature(method); TypeSignature newTypeSig = new TypeSignature(elems); String sig = newTypeSig.getTypeSignature(typesig, retType); if (sig.charAt(0) != '[') forwardDeclsFromSig(pw, sig); } } } protected void forwardDeclsFromSig(PrintWriter pw, String sig) { int len = sig.length(); int i = sig.charAt(0) == '(' ? 1 : 0; /* Skip the initial "(". */ while (i < len) { if (sig.charAt(i) == 'L') { int j = i + 1; while (sig.charAt(j) != ';') j++; genHandleType(pw, sig.substring(i + 1, j)); i = j + 1; } else { i++; } } } protected void structSectionForClass(PrintWriter pw, TypeElement jclazz, String cname) { String jname = jclazz.getQualifiedName().toString(); if (cname.equals("java_lang_Object")) { pw.println("/* struct java_lang_Object is defined in typedefs.h. */"); pw.println(); return; } pw.println("#if !defined(__i386)"); pw.println("#pragma pack(4)"); pw.println("#endif"); pw.println(); pw.println("struct " + cname + " {"); pw.println(" ObjHeader h;"); pw.print(fieldDefs(jclazz, cname)); if (jname.equals("java.lang.Class")) pw.println(" Class *LLNI_mask(cClass);" + " /* Fake field; don't access (see oobj.h) */"); pw.println("};" + lineSep + lineSep + "#pragma pack()"); pw.println(); return; } private static class FieldDefsRes { public String className; /* Name of the current class. */ public FieldDefsRes parent; public String s; public int byteSize; public boolean bottomMost; public boolean printedOne = false; FieldDefsRes(TypeElement clazz, FieldDefsRes parent, boolean bottomMost) { this.className = clazz.getQualifiedName().toString(); this.parent = parent; this.bottomMost = bottomMost; int byteSize = 0; if (parent == null) this.s = ""; else this.s = parent.s; } } /* Returns "true" iff added a field. */ private boolean doField(FieldDefsRes res, VariableElement field, String cname, boolean padWord) { String fieldDef = addStructMember(field, cname, padWord); if (fieldDef != null) { if (!res.printedOne) { /* add separator */ if (res.bottomMost) { if (res.s.length() != 0) res.s = res.s + " /* local members: */" + lineSep; } else { res.s = res.s + " /* inherited members from " + res.className + ": */" + lineSep; } res.printedOne = true; } res.s = res.s + fieldDef; return true; } // Otherwise. return false; } private int doTwoWordFields(FieldDefsRes res, TypeElement clazz, int offset, String cname, boolean padWord) { boolean first = true; List<VariableElement> fields = ElementFilter.fieldsIn(clazz.getEnclosedElements()); for (VariableElement field: fields) { TypeKind tk = field.asType().getKind(); boolean twoWords = (tk == TypeKind.LONG || tk == TypeKind.DOUBLE); if (twoWords && doField(res, field, cname, first && padWord)) { offset += 8; first = false; } } return offset; } String fieldDefs(TypeElement clazz, String cname) { FieldDefsRes res = fieldDefs(clazz, cname, true); return res.s; } FieldDefsRes fieldDefs(TypeElement clazz, String cname, boolean bottomMost){ FieldDefsRes res; int offset; boolean didTwoWordFields = false; TypeElement superclazz = (TypeElement) types.asElement(clazz.getSuperclass()); if (superclazz != null) { String supername = superclazz.getQualifiedName().toString(); res = new FieldDefsRes(clazz, fieldDefs(superclazz, cname, false), bottomMost); offset = res.parent.byteSize; } else { res = new FieldDefsRes(clazz, null, bottomMost); offset = 0; } List<VariableElement> fields = ElementFilter.fieldsIn(clazz.getEnclosedElements()); for (VariableElement field: fields) { if (doubleAlign && !didTwoWordFields && (offset % 8) == 0) { offset = doTwoWordFields(res, clazz, offset, cname, false); didTwoWordFields = true; } TypeKind tk = field.asType().getKind(); boolean twoWords = (tk == TypeKind.LONG || tk == TypeKind.DOUBLE); if (!doubleAlign || !twoWords) { if (doField(res, field, cname, false)) offset += 4; } } if (doubleAlign && !didTwoWordFields) { if ((offset % 8) != 0) offset += 4; offset = doTwoWordFields(res, clazz, offset, cname, true); } res.byteSize = offset; return res; } /* OVERRIDE: This method handles instance fields */ protected String addStructMember(VariableElement member, String cname, boolean padWord) { String res = null; if (member.getModifiers().contains(Modifier.STATIC)) { res = addStaticStructMember(member, cname); // if (res == null) /* JNI didn't handle it, print comment. */ // res = " /* Inaccessible static: " + member + " */" + lineSep; } else { TypeMirror mt = types.erasure(member.asType()); if (padWord) res = " java_int padWord" + padFieldNum++ + ";" + lineSep; res = " " + llniType(mt, false, false) + " " + llniFieldName(member); if (isLongOrDouble(mt)) res = res + "[2]"; res = res + ";" + lineSep; } return res; } static private final boolean isWindows = System.getProperty("os.name").startsWith("Windows"); /* * This method only handles static final fields. */ protected String addStaticStructMember(VariableElement field, String cname) { String res = null; Object exp = null; if (!field.getModifiers().contains(Modifier.STATIC)) return res; if (!field.getModifiers().contains(Modifier.FINAL)) return res; exp = field.getConstantValue(); if (exp != null) { /* Constant. */ String cn = cname + "_" + field.getSimpleName(); String suffix = null; long val = 0; /* Can only handle int, long, float, and double fields. */ if (exp instanceof Byte || exp instanceof Short || exp instanceof Integer) { suffix = "L"; val = ((Number)exp).intValue(); } else if (exp instanceof Long) { // Visual C++ supports the i64 suffix, not LL suffix = isWindows ? "i64" : "LL"; val = ((Long)exp).longValue(); } else if (exp instanceof Float) suffix = "f"; else if (exp instanceof Double) suffix = ""; else if (exp instanceof Character) { suffix = "L"; Character ch = (Character) exp; val = ((int) ch) & 0xffff; } if (suffix != null) { // Some compilers will generate a spurious warning // for the integer constants for Integer.MIN_VALUE // and Long.MIN_VALUE so we handle them specially. if ((suffix.equals("L") && (val == Integer.MIN_VALUE)) || (suffix.equals("LL") && (val == Long.MIN_VALUE))) { res = " #undef " + cn + lineSep + " #define " + cn + " (" + (val + 1) + suffix + "-1)" + lineSep; } else if (suffix.equals("L") || suffix.endsWith("LL")) { res = " #undef " + cn + lineSep + " #define " + cn + " " + val + suffix + lineSep; } else { res = " #undef " + cn + lineSep + " #define " + cn + " " + exp + suffix + lineSep; } } } return res; } protected void methodSectionForClass(PrintWriter pw, TypeElement clazz, String cname) throws TypeSignature.SignatureException, Util.Exit { String methods = methodDecls(clazz, cname); if (methods.length() != 0) { pw.println("/* Native method declarations: */" + lineSep); pw.println("#ifdef __cplusplus"); pw.println("extern \"C\" {"); pw.println("#endif" + lineSep); pw.println(methods); pw.println("#ifdef __cplusplus"); pw.println("}"); pw.println("#endif"); } } protected String methodDecls(TypeElement clazz, String cname) throws TypeSignature.SignatureException, Util.Exit { String res = ""; for (ExecutableElement method: methods) { if (method.getModifiers().contains(Modifier.NATIVE)) res = res + methodDecl(method, clazz, cname); } return res; } protected String methodDecl(ExecutableElement method, TypeElement clazz, String cname) throws TypeSignature.SignatureException, Util.Exit { String res = null; TypeMirror retType = types.erasure(method.getReturnType()); String typesig = signature(method); TypeSignature newTypeSig = new TypeSignature(elems); String sig = newTypeSig.getTypeSignature(typesig, retType); boolean longName = needLongName(method, clazz); if (sig.charAt(0) != '(') util.error("invalid.method.signature", sig); res = "JNIEXPORT " + jniType(retType) + " JNICALL" + lineSep + jniMethodName(method, cname, longName) + "(JNIEnv *, " + cRcvrDecl(method, cname); List<? extends VariableElement> params = method.getParameters(); List<TypeMirror> argTypes = new ArrayList(); for (VariableElement p: params){ argTypes.add(types.erasure(p.asType())); } /* It would have been nice to include the argument names in the declaration, but there seems to be a bug in the "BinaryField" class, causing the getArguments() method to return "null" for most (non-constructor) methods. */ for (TypeMirror argType: argTypes) res = res + ", " + jniType(argType); res = res + ");" + lineSep; return res; } protected final boolean needLongName(ExecutableElement method, TypeElement clazz) { Name methodName = method.getSimpleName(); for (ExecutableElement memberMethod: methods) { if ((memberMethod != method) && memberMethod.getModifiers().contains(Modifier.NATIVE) && (methodName.equals(memberMethod.getSimpleName()))) return true; } return false; } protected final String jniMethodName(ExecutableElement method, String cname, boolean longName) throws TypeSignature.SignatureException { String res = "Java_" + cname + "_" + method.getSimpleName(); if (longName) { TypeMirror mType = types.erasure(method.getReturnType()); List<? extends VariableElement> params = method.getParameters(); List<TypeMirror> argTypes = new ArrayList(); for (VariableElement param: params) { argTypes.add(types.erasure(param.asType())); } res = res + "__"; for (TypeMirror t: argTypes) { String tname = t.toString(); TypeSignature newTypeSig = new TypeSignature(elems); String sig = newTypeSig.getTypeSignature(tname); res = res + nameToIdentifier(sig); } } return res; } // copied from JNI.java protected final String jniType(TypeMirror t) throws Util.Exit { TypeElement throwable = elems.getTypeElement("java.lang.Throwable"); TypeElement jClass = elems.getTypeElement("java.lang.Class"); TypeElement jString = elems.getTypeElement("java.lang.String"); Element tclassDoc = types.asElement(t); switch (t.getKind()) { case ARRAY: { TypeMirror ct = ((ArrayType) t).getComponentType(); switch (ct.getKind()) { case BOOLEAN: return "jbooleanArray"; case BYTE: return "jbyteArray"; case CHAR: return "jcharArray"; case SHORT: return "jshortArray"; case INT: return "jintArray"; case LONG: return "jlongArray"; case FLOAT: return "jfloatArray"; case DOUBLE: return "jdoubleArray"; case ARRAY: case DECLARED: return "jobjectArray"; default: throw new Error(ct.toString()); } } case VOID: return "void"; case BOOLEAN: return "jboolean"; case BYTE: return "jbyte"; case CHAR: return "jchar"; case SHORT: return "jshort"; case INT: return "jint"; case LONG: return "jlong"; case FLOAT: return "jfloat"; case DOUBLE: return "jdouble"; case DECLARED: { if (tclassDoc.equals(jString)) return "jstring"; else if (types.isAssignable(t, throwable.asType())) return "jthrowable"; else if (types.isAssignable(t, jClass.asType())) return "jclass"; else return "jobject"; } } util.bug("jni.unknown.type"); return null; /* dead code. */ } protected String llniType(TypeMirror t, boolean handleize, boolean longDoubleOK) { String res = null; switch (t.getKind()) { case ARRAY: { TypeMirror ct = ((ArrayType) t).getComponentType(); switch (ct.getKind()) { case BOOLEAN: res = "IArrayOfBoolean"; break; case BYTE: res = "IArrayOfByte"; break; case CHAR: res = "IArrayOfChar"; break; case SHORT: res = "IArrayOfShort"; break; case INT: res = "IArrayOfInt"; break; case LONG: res = "IArrayOfLong"; break; case FLOAT: res = "IArrayOfFloat"; break; case DOUBLE: res = "IArrayOfDouble"; break; case ARRAY: case DECLARED: res = "IArrayOfRef"; break; default: throw new Error(ct.getKind() + " " + ct); } if (!handleize) res = "DEREFERENCED_" + res; break; } case VOID: res = "void"; break; case BOOLEAN: case BYTE: case CHAR: case SHORT: case INT: res = "java_int" ; break; case LONG: res = longDoubleOK ? "java_long" : "val32 /* java_long */"; break; case FLOAT: res = "java_float"; break; case DOUBLE: res = longDoubleOK ? "java_double" : "val32 /* java_double */"; break; case DECLARED: TypeElement e = (TypeElement) types.asElement(t); res = "I" + mangleClassName(e.getQualifiedName().toString()); if (!handleize) res = "DEREFERENCED_" + res; break; default: throw new Error(t.getKind() + " " + t); // FIXME } return res; } protected final String cRcvrDecl(Element field, String cname) { return (field.getModifiers().contains(Modifier.STATIC) ? "jclass" : "jobject"); } protected String maskName(String s) { return "LLNI_mask(" + s + ")"; } protected String llniFieldName(VariableElement field) { return maskName(field.getSimpleName().toString()); } protected final boolean isLongOrDouble(TypeMirror t) { TypeVisitor<Boolean,Void> v = new SimpleTypeVisitor8() { public Boolean defaultAction(TypeMirror t, Void p){ return false; } public Boolean visitArray(ArrayType t, Void p) { return visit(t.getComponentType(), p); } public Boolean visitPrimitive(PrimitiveType t, Void p) { TypeKind tk = t.getKind(); return (tk == TypeKind.LONG || tk == TypeKind.DOUBLE); } }; return v.visit(t, null); } /* Do unicode to ansi C identifier conversion. %%% This may not be right, but should be called more often. */ protected final String nameToIdentifier(String name) { int len = name.length(); StringBuilder buf = new StringBuilder(len); for (int i = 0; i < len; i++) { char c = name.charAt(i); if (isASCIILetterOrDigit(c)) buf.append(c); else if (c == '/') buf.append('_'); else if (c == '.') buf.append('_'); else if (c == '_') buf.append("_1"); else if (c == ';') buf.append("_2"); else if (c == '[') buf.append("_3"); else buf.append("_0" + ((int)c)); } return new String(buf); } protected final boolean isASCIILetterOrDigit(char c) { if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')) || ((c >= '0') && (c <= '9'))) return true; else return false; } }

Other Java examples (source code examples)

Here is a short list of links related to this Java LLNI.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.