This is NOT part of any API supported by Sun Microsystems.
+ * 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.
+ *
* @author Sucheta Dambalkar(Revised)
*/
-
-
public abstract class Gen {
protected String lineSep = System.getProperty("line.separator");
- RootDoc root;
+ protected ProcessingEnvironment processingEnvironment;
+ protected Types types;
+ protected Elements elems;
+ protected Mangle mangler;
+ protected Util util;
+
+ protected Gen(Util util) {
+ this.util = util;
+ }
+
/*
* List of classes for which we must generate output.
*/
- protected ClassDoc[] classes;
+ protected Set 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;
+ protected abstract void write(OutputStream o, TypeElement clazz) throws Util.Exit;
/**
* Override this method to provide a list of #include statements
@@ -78,31 +103,29 @@
/*
* Output location.
*/
- protected String outDir;
- protected String outFile;
+ protected JavaFileManager fileManager;
+ protected JavaFileObject 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 setFileManager(JavaFileManager fm) {
+ fileManager = fm;
}
- public void setOutFile(String outFile) {
+ public void setOutFile(JavaFileObject outFile) {
this.outFile = outFile;
}
- public void setClasses(ClassDoc[] classes) {
+ public void setClasses(Set classes) {
this.classes = classes;
}
+ void setProcessingEnvironment(ProcessingEnvironment pEnv) {
+ processingEnvironment = pEnv;
+ elems = pEnv.getElementUtils();
+ types = pEnv.getTypeUtils();
+ mangler = new Mangle(elems, types);
+ }
+
/*
* Smartness with generated files.
*/
@@ -116,12 +139,11 @@
* We explicitly need to write ASCII files because that is what C
* compilers understand.
*/
- protected PrintWriter wrapWriter(OutputStream o) {
+ protected PrintWriter wrapWriter(OutputStream o) throws Util.Exit {
try {
- return new
- PrintWriter(new OutputStreamWriter(o, "ISO8859_1"), true);
+ return new PrintWriter(new OutputStreamWriter(o, "ISO8859_1"), true);
} catch (UnsupportedEncodingException use) {
- Util.bug("encoding.iso8859_1.not.found");
+ util.bug("encoding.iso8859_1.not.found");
return null; /* dead code */
}
}
@@ -133,26 +155,25 @@
* Buffer size chosen as an approximation from a single sampling of:
* expr `du -sk` / `ls *.h | wc -l`
*/
- public void run() throws IOException, ClassNotFoundException {
+ public void run() throws IOException, ClassNotFoundException, Util.Exit {
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]);
+ for (TypeElement t: classes) {
+ write(bout, t);
}
writeIfChanged(bout.toByteArray(), outFile);
} else {
/* Each class goes to its own file... */
- for (i = 0; i < classes.length; i++) {
+ for (TypeElement t: classes) {
ByteArrayOutputStream bout = new ByteArrayOutputStream(8192);
writeFileTop(bout);
- ClassDoc clazz = classes[i];
- write(bout, clazz);
- writeIfChanged(bout.toByteArray(), getFileName(clazz.qualifiedName()));
+ write(bout, t);
+ writeIfChanged(bout.toByteArray(), getFileObject(t.getQualifiedName()));
}
}
}
@@ -162,8 +183,7 @@
* 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);
+ private void writeIfChanged(byte[] b, FileObject file) throws IOException {
boolean mustWrite = false;
String event = "[No need to update file ";
@@ -171,71 +191,80 @@
mustWrite = true;
event = "[Forcefully writing file ";
} else {
- if (!f.exists()) {
+ InputStream in;
+ byte[] a;
+ try {
+ // regrettably, there's no API to get the length in bytes
+ // for a FileObject, so we can't short-circuit reading the
+ // file here
+ in = file.openInputStream();
+ a = readBytes(in);
+ if (!Arrays.equals(a, b)) {
+ mustWrite = true;
+ event = "[Overwriting file ";
+
+ }
+ } catch (FileNotFoundException e) {
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 (util.verbose)
+ util.log(event + file + "]");
+
if (mustWrite) {
- OutputStream out = new FileOutputStream(file);
+ OutputStream out = file.openOutputStream();
out.write(b); /* No buffering, just one big write! */
out.close();
}
}
- protected String defineForStatic(ClassDoc c, FieldDoc f){
+ protected byte[] readBytes(InputStream in) throws IOException {
+ try {
+ byte[] array = new byte[in.available() + 1];
+ int offset = 0;
+ int n;
+ while ((n = in.read(array, offset, array.length - offset)) != -1) {
+ offset += n;
+ if (offset == array.length)
+ array = Arrays.copyOf(array, array.length * 2);
+ }
- String cnamedoc = c.qualifiedName();
- String fnamedoc = f.name();
+ return Arrays.copyOf(array, offset);
+ } finally {
+ in.close();
+ }
+ }
- String cname = Mangle.mangle(cnamedoc, Mangle.Type.CLASS);
- String fname = Mangle.mangle(fnamedoc, Mangle.Type.FIELDSTUB);
+ protected String defineForStatic(TypeElement c, VariableElement f)
+ throws Util.Exit {
+ CharSequence cnamedoc = c.getQualifiedName();
+ CharSequence fnamedoc = f.getSimpleName();
- if (!f.isStatic())
- Util.bug("tried.to.define.non.static");
+ String cname = mangler.mangle(cnamedoc, Mangle.Type.CLASS);
+ String fname = mangler.mangle(fnamedoc, Mangle.Type.FIELDSTUB);
- if (f.isFinal()) {
+ if (!f.getModifiers().contains(Modifier.STATIC))
+ util.bug("tried.to.define.non.static");
+
+ if (f.getModifiers().contains(Modifier.FINAL)) {
Object value = null;
- value = f.constantValue();
+ value = f.getConstantValue();
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";
+ || (value instanceof Short)) {
+ /* covers byte, short, int */
+ constString = value.toString() + "L";
+ } else if (value instanceof Boolean) {
+ constString = ((Boolean) value) ? "1L" : "0L";
+ } else if (value instanceof Character) {
+ Character ch = (Character) value;
+ constString = String.valueOf(((int) ch) & 0xffff) + "L";
} else if (value instanceof Long) {
// Visual C++ supports the i64 suffix, not LL.
if (isWindows)
@@ -294,24 +323,19 @@
/*
* File name and file preamble related operations.
*/
- protected void writeFileTop(OutputStream o) {
+ protected void writeFileTop(OutputStream o) throws Util.Exit {
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 baseFileName(CharSequence className) {
+ return mangler.mangle(className, Mangle.Type.CLASS);
}
- protected String getFileName(String clazz) {
- return baseFileName(clazz) + getFileSuffix();
+ protected FileObject getFileObject(CharSequence className) throws IOException {
+ String name = baseFileName(className) + getFileSuffix();
+ return fileManager.getFileForOutput(StandardLocation.SOURCE_OUTPUT, "", name, null);
}
protected String getFileSuffix() {
@@ -322,26 +346,39 @@
* Including super classes' fields.
*/
- FieldDoc[] getAllFields(ClassDoc subclazz)
- throws ClassNotFoundException {
- Vector fields = new Vector();
- ClassDoc cd = null;
- Stack