Path: blob/aarch64-shenandoah-jdk8u272-b10/langtools/src/share/classes/com/sun/tools/javah/Gen.java
38899 views
/*1* Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package com.sun.tools.javah;2627import java.io.UnsupportedEncodingException;28import java.io.ByteArrayOutputStream;29import java.io.FileNotFoundException;30import java.io.IOException;31import java.io.InputStream;32import java.io.OutputStream;33import java.io.OutputStreamWriter;34import java.io.PrintWriter;35import java.util.ArrayList;36import java.util.Arrays;37import java.util.List;38import java.util.Set;39import java.util.Stack;4041import javax.annotation.processing.ProcessingEnvironment;4243import javax.lang.model.element.ExecutableElement;44import javax.lang.model.element.Modifier;45import javax.lang.model.element.TypeElement;46import javax.lang.model.element.VariableElement;47import javax.lang.model.util.ElementFilter;48import javax.lang.model.util.Elements;49import javax.lang.model.util.Types;5051import javax.tools.FileObject;52import javax.tools.JavaFileManager;53import javax.tools.JavaFileObject;54import javax.tools.StandardLocation;5556/**57* An abstraction for generating support files required by native methods.58* Subclasses are for specific native interfaces. At the time of its59* original writing, this interface is rich enough to support JNI and the60* old 1.0-style native method interface.61*62* <p><b>This is NOT part of any supported API.63* If you write code that depends on this, you do so at your own64* risk. This code and its internal interfaces are subject to change65* or deletion without notice.</b></p>66*67* @author Sucheta Dambalkar(Revised)68*/69public abstract class Gen {70protected String lineSep = System.getProperty("line.separator");7172protected ProcessingEnvironment processingEnvironment;73protected Types types;74protected Elements elems;75protected Mangle mangler;76protected Util util;7778protected Gen(Util util) {79this.util = util;80}8182/*83* List of classes for which we must generate output.84*/85protected Set<TypeElement> classes;86static private final boolean isWindows =87System.getProperty("os.name").startsWith("Windows");888990/**91* Override this abstract method, generating content for the named92* class into the outputstream.93*/94protected abstract void write(OutputStream o, TypeElement clazz) throws Util.Exit;9596/**97* Override this method to provide a list of #include statements98* required by the native interface.99*/100protected abstract String getIncludes();101102/*103* Output location.104*/105protected JavaFileManager fileManager;106protected JavaFileObject outFile;107108public void setFileManager(JavaFileManager fm) {109fileManager = fm;110}111112public void setOutFile(JavaFileObject outFile) {113this.outFile = outFile;114}115116117public void setClasses(Set<TypeElement> classes) {118this.classes = classes;119}120121void setProcessingEnvironment(ProcessingEnvironment pEnv) {122processingEnvironment = pEnv;123elems = pEnv.getElementUtils();124types = pEnv.getTypeUtils();125mangler = new Mangle(elems, types);126}127128/*129* Smartness with generated files.130*/131protected boolean force = false;132133public void setForce(boolean state) {134force = state;135}136137/**138* We explicitly need to write ASCII files because that is what C139* compilers understand.140*/141protected PrintWriter wrapWriter(OutputStream o) throws Util.Exit {142try {143return new PrintWriter(new OutputStreamWriter(o, "ISO8859_1"), true);144} catch (UnsupportedEncodingException use) {145util.bug("encoding.iso8859_1.not.found");146return null; /* dead code */147}148}149150/**151* After initializing state of an instance, use this method to start152* processing.153*154* Buffer size chosen as an approximation from a single sampling of:155* expr `du -sk` / `ls *.h | wc -l`156*/157public void run() throws IOException, ClassNotFoundException, Util.Exit {158int i = 0;159if (outFile != null) {160/* Everything goes to one big file... */161ByteArrayOutputStream bout = new ByteArrayOutputStream(8192);162writeFileTop(bout); /* only once */163164for (TypeElement t: classes) {165write(bout, t);166}167168writeIfChanged(bout.toByteArray(), outFile);169} else {170/* Each class goes to its own file... */171for (TypeElement t: classes) {172ByteArrayOutputStream bout = new ByteArrayOutputStream(8192);173writeFileTop(bout);174write(bout, t);175writeIfChanged(bout.toByteArray(), getFileObject(t.getQualifiedName()));176}177}178}179180/*181* Write the contents of byte[] b to a file named file. Writing182* is done if either the file doesn't exist or if the contents are183* different.184*/185private void writeIfChanged(byte[] b, FileObject file) throws IOException {186boolean mustWrite = false;187String event = "[No need to update file ";188189if (force) {190mustWrite = true;191event = "[Forcefully writing file ";192} else {193InputStream in;194byte[] a;195try {196// regrettably, there's no API to get the length in bytes197// for a FileObject, so we can't short-circuit reading the198// file here199in = file.openInputStream();200a = readBytes(in);201if (!Arrays.equals(a, b)) {202mustWrite = true;203event = "[Overwriting file ";204205}206} catch (FileNotFoundException e) {207mustWrite = true;208event = "[Creating file ";209}210}211212if (util.verbose)213util.log(event + file + "]");214215if (mustWrite) {216OutputStream out = file.openOutputStream();217out.write(b); /* No buffering, just one big write! */218out.close();219}220}221222protected byte[] readBytes(InputStream in) throws IOException {223try {224byte[] array = new byte[in.available() + 1];225int offset = 0;226int n;227while ((n = in.read(array, offset, array.length - offset)) != -1) {228offset += n;229if (offset == array.length)230array = Arrays.copyOf(array, array.length * 2);231}232233return Arrays.copyOf(array, offset);234} finally {235in.close();236}237}238239protected String defineForStatic(TypeElement c, VariableElement f)240throws Util.Exit {241CharSequence cnamedoc = c.getQualifiedName();242CharSequence fnamedoc = f.getSimpleName();243244String cname = mangler.mangle(cnamedoc, Mangle.Type.CLASS);245String fname = mangler.mangle(fnamedoc, Mangle.Type.FIELDSTUB);246247if (!f.getModifiers().contains(Modifier.STATIC))248util.bug("tried.to.define.non.static");249250if (f.getModifiers().contains(Modifier.FINAL)) {251Object value = null;252253value = f.getConstantValue();254255if (value != null) { /* so it is a ConstantExpression */256String constString = null;257if ((value instanceof Integer)258|| (value instanceof Byte)259|| (value instanceof Short)) {260/* covers byte, short, int */261constString = value.toString() + "L";262} else if (value instanceof Boolean) {263constString = ((Boolean) value) ? "1L" : "0L";264} else if (value instanceof Character) {265Character ch = (Character) value;266constString = String.valueOf(((int) ch) & 0xffff) + "L";267} else if (value instanceof Long) {268// Visual C++ supports the i64 suffix, not LL.269if (isWindows)270constString = value.toString() + "i64";271else272constString = value.toString() + "LL";273} else if (value instanceof Float) {274/* bug for bug */275float fv = ((Float)value).floatValue();276if (Float.isInfinite(fv))277constString = ((fv < 0) ? "-" : "") + "Inff";278else279constString = value.toString() + "f";280} else if (value instanceof Double) {281/* bug for bug */282double d = ((Double)value).doubleValue();283if (Double.isInfinite(d))284constString = ((d < 0) ? "-" : "") + "InfD";285else286constString = value.toString();287}288if (constString != null) {289StringBuilder s = new StringBuilder("#undef ");290s.append(cname); s.append("_"); s.append(fname); s.append(lineSep);291s.append("#define "); s.append(cname); s.append("_");292s.append(fname); s.append(" "); s.append(constString);293return s.toString();294}295296}297}298return null;299}300301/*302* Deal with the C pre-processor.303*/304protected String cppGuardBegin() {305return "#ifdef __cplusplus" + lineSep + "extern \"C\" {" + lineSep + "#endif";306}307308protected String cppGuardEnd() {309return "#ifdef __cplusplus" + lineSep + "}" + lineSep + "#endif";310}311312protected String guardBegin(String cname) {313return "/* Header for class " + cname + " */" + lineSep + lineSep +314"#ifndef _Included_" + cname + lineSep +315"#define _Included_" + cname;316}317318protected String guardEnd(String cname) {319return "#endif";320}321322/*323* File name and file preamble related operations.324*/325protected void writeFileTop(OutputStream o) throws Util.Exit {326PrintWriter pw = wrapWriter(o);327pw.println("/* DO NOT EDIT THIS FILE - it is machine generated */" + lineSep +328getIncludes());329}330331protected String baseFileName(CharSequence className) {332return mangler.mangle(className, Mangle.Type.CLASS);333}334335protected FileObject getFileObject(CharSequence className) throws IOException {336String name = baseFileName(className) + getFileSuffix();337return fileManager.getFileForOutput(StandardLocation.SOURCE_OUTPUT, "", name, null);338}339340protected String getFileSuffix() {341return ".h";342}343344/**345* Including super classes' fields.346*/347348List<VariableElement> getAllFields(TypeElement subclazz) {349List<VariableElement> fields = new ArrayList<VariableElement>();350TypeElement cd = null;351Stack<TypeElement> s = new Stack<TypeElement>();352353cd = subclazz;354while (true) {355s.push(cd);356TypeElement c = (TypeElement) (types.asElement(cd.getSuperclass()));357if (c == null)358break;359cd = c;360}361362while (!s.empty()) {363cd = s.pop();364fields.addAll(ElementFilter.fieldsIn(cd.getEnclosedElements()));365}366367return fields;368}369370// c.f. MethodDoc.signature371String signature(ExecutableElement e) {372StringBuilder sb = new StringBuilder("(");373String sep = "";374for (VariableElement p: e.getParameters()) {375sb.append(sep);376sb.append(types.erasure(p.asType()).toString());377sep = ",";378}379sb.append(")");380return sb.toString();381}382}383384385386