Gen.java :  » 6.0-JDK-Modules-com.sun » tools » com » sun » tools » javah » Java Open Source

Java Open Source » 6.0 JDK Modules com.sun » tools 
tools » com » sun » tools » javah » Gen.java
/*
 * Copyright 2002-2005 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package com.sun.tools.javah;

import java.io.UnsupportedEncodingException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import com.sun.javadoc.*;
import java.io.*;
import java.util.Stack;
import java.util.Vector;
import java.util.Arrays;


/**
 * An abstraction for generating support files required by native methods.
 * Subclasses are for specific native interfaces. At the time of its
 * original writing, this interface is rich enough to support JNI and the
 * old 1.0-style native method interface.
 *
 * @author  Sucheta Dambalkar(Revised)
 */
 

public abstract class Gen {
    protected String lineSep = System.getProperty("line.separator");
    
    RootDoc root;
    /*
     * List of classes for which we must generate output.
     */
    protected ClassDoc[] classes;
    static private final boolean isWindows = 
  System.getProperty("os.name").startsWith("Windows");
    
    public Gen(RootDoc root){
  this.root = root;
    }
    
    /**
     * Override this abstract method, generating content for the named
     * class into the outputstream.
     */
    protected abstract void write(OutputStream o, ClassDoc clazz)
  throws ClassNotFoundException;
    
    /**
     * Override this method to provide a list of #include statements
     * required by the native interface.
     */
    protected abstract String getIncludes();
    
    /*
     * Output location.
     */
    protected String outDir;
    protected String outFile;
    
    public void setOutDir(String outDir) {
  /* Check important, otherwise concatenation of two null strings
   * produces the "nullnull" String.
   */
  if (outDir != null) {
      this.outDir = outDir + System.getProperty("file.separator");
      File d = new File(outDir);
      if (!d.exists())
    if (!d.mkdirs())
        Util.error("cant.create.dir", d.toString());
  }
    }
    
    public void setOutFile(String outFile) {
  this.outFile = outFile;
    }
    
    
    public void setClasses(ClassDoc[] classes) {
  this.classes = classes;
    }
    
    /*
     * Smartness with generated files.
     */
    protected boolean force = false;
    
    public void setForce(boolean state) {
  force = state;
    }
    
    /**
     * We explicitly need to write ASCII files because that is what C
     * compilers understand.
     */
    protected PrintWriter wrapWriter(OutputStream o) {
  try {
      return new
      PrintWriter(new OutputStreamWriter(o, "ISO8859_1"), true);
  } catch (UnsupportedEncodingException use) {
      Util.bug("encoding.iso8859_1.not.found");
      return null; /* dead code */
  }
    }
    
    /**
     * After initializing state of an instance, use this method to start
     * processing.
     *
     * Buffer size chosen as an approximation from a single sampling of:
     *         expr `du -sk` / `ls *.h | wc -l`
     */
    public void run() throws IOException, ClassNotFoundException {
  int i = 0;
  if (outFile != null) {
      /* Everything goes to one big file... */
      ByteArrayOutputStream bout = new ByteArrayOutputStream(8192);
      writeFileTop(bout); /* only once */
      
      for (i = 0; i < classes.length; i++) {
    write(bout, classes[i]);
      }
      
      writeIfChanged(bout.toByteArray(), outFile);
  } else {
      /* Each class goes to its own file... */
      for (i = 0; i < classes.length; i++) {
    ByteArrayOutputStream bout = new ByteArrayOutputStream(8192);
    writeFileTop(bout);
    ClassDoc clazz = classes[i];
    write(bout, clazz);
    writeIfChanged(bout.toByteArray(), getFileName(clazz.qualifiedName()));
      }
  }
    }
    
    /*
     * Write the contents of byte[] b to a file named file.  Writing
     * is done if either the file doesn't exist or if the contents are
     * different.
     */
    private void writeIfChanged(byte[] b, String file) throws IOException {
  File f = new File(file);
  boolean mustWrite = false;
  String event = "[No need to update file ";
  
  if (force) {
      mustWrite = true;
      event = "[Forcefully writing file ";
  } else {
      if (!f.exists()) {
    mustWrite = true;
    event = "[Creating file ";
      } else {
    int l = (int)f.length();
    if (b.length != l) {
        mustWrite = true;
        event = "[Overwriting file ";
    } else {
        /* Lengths are equal, so read it. */
        byte[] a = new byte[l];
        FileInputStream in = new FileInputStream(f);
        if (in.read(a) != l) {
      in.close();
      /* This can't happen, we already checked the length. */
      Util.error("not.enough.bytes", Integer.toString(l),
           f.toString());
        }
        in.close();
        while (--l >= 0) {
      if (a[l] != b[l]) {
          mustWrite = true;
          event = "[Overwriting file ";
      }
        }
    }
      }
  }
  if (Util.verbose)
      Util.log(event + file + "]");
  if (mustWrite) {
      OutputStream out = new FileOutputStream(file);
      out.write(b); /* No buffering, just one big write! */
      out.close();
  }
    }
    
    protected String defineForStatic(ClassDoc c, FieldDoc f){
  
  String cnamedoc = c.qualifiedName();
  String fnamedoc = f.name();

  String cname = Mangle.mangle(cnamedoc, Mangle.Type.CLASS);
  String fname = Mangle.mangle(fnamedoc, Mangle.Type.FIELDSTUB);
  
  if (!f.isStatic())
      Util.bug("tried.to.define.non.static");
  
  if (f.isFinal()) {  
      Object value = null;
      
      value = f.constantValue();
      
      if (value != null) { /* so it is a ConstantExpression */
    String constString = null;
    if ((value instanceof Integer) 
        || (value instanceof Byte) 
        || (value instanceof Character)
        || (value instanceof Short)
        || (value instanceof Boolean)) {
        /* covers byte, boolean, char, short, int */
        if(value instanceof Boolean)
      constString = (value.toString() == "true") ? "1L" : "0L";
        else
      constString = value.toString() + "L";
    } else if (value instanceof Long) {
        // Visual C++ supports the i64 suffix, not LL.
        if (isWindows)
      constString = value.toString() + "i64";
        else
      constString = value.toString() + "LL";
    } else if (value instanceof Float) {
        /* bug for bug */
        float fv = ((Float)value).floatValue();
        if (Float.isInfinite(fv))
      constString = ((fv < 0) ? "-" : "") + "Inff";
        else
      constString = value.toString() + "f";
    } else if (value instanceof Double) {
        /* bug for bug */
        double d = ((Double)value).doubleValue();
        if (Double.isInfinite(d))
      constString = ((d < 0) ? "-" : "") + "InfD";
        else
      constString = value.toString();
    }
    if (constString != null) {
        StringBuffer s = new StringBuffer("#undef ");
        s.append(cname); s.append("_"); s.append(fname); s.append(lineSep);
        s.append("#define "); s.append(cname); s.append("_");
        s.append(fname); s.append(" "); s.append(constString);
        return s.toString();
    }
    
      }
  }
  return null;
    }
    
    /*
     * Deal with the C pre-processor.
     */
    protected String cppGuardBegin() {
  return "#ifdef __cplusplus" + lineSep + "extern \"C\" {" + lineSep + "#endif";
    }
    
    protected String cppGuardEnd() {
  return "#ifdef __cplusplus" + lineSep + "}" + lineSep + "#endif";
    }
    
    protected String guardBegin(String cname) {
  return "/* Header for class " + cname + " */" + lineSep + lineSep + 
      "#ifndef _Included_" + cname + lineSep + 
      "#define _Included_" + cname;
    }
    
    protected String guardEnd(String cname) {
  return "#endif";
    }
    
    /*
     * File name and file preamble related operations.
     */
    protected void writeFileTop(OutputStream o) {
  PrintWriter pw = wrapWriter(o);
  pw.println("/* DO NOT EDIT THIS FILE - it is machine generated */" + lineSep +
       getIncludes());
    }
    
    protected String baseFileName(String clazz) {
  StringBuffer f = 
      new StringBuffer(Mangle.mangle(clazz,
             Mangle.Type.CLASS));
  if (outDir != null) {
      f.insert(0, outDir);
  }
  return f.toString();
    }
    
    protected String getFileName(String clazz) {
  return baseFileName(clazz) + getFileSuffix();
    }
    
    protected String getFileSuffix() {
  return ".h";
    }

    /**
     * Including super classes' fields.
     */

    FieldDoc[] getAllFields(ClassDoc subclazz) 
    throws ClassNotFoundException {
  Vector fields = new Vector();
  ClassDoc cd = null;
  Stack s = new Stack();
  
  cd = subclazz;
  while (true) {
      s.push(cd);
      ClassDoc c = cd.superclass();
      if (c == null)
    break;
      cd = c;
  }
  
  while (!s.empty()) {
      cd = (ClassDoc)s.pop();
      fields.addAll(Arrays.asList(cd.fields()));
  }

  return (FieldDoc[]) fields.toArray(new FieldDoc[fields.size()]);
    }
}

java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.