import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Task; /** * Ant Task for copying the PImage and PGraphics methods into PApplet. */ public class PAppletMethods extends Task { private File baseDir; private boolean includeRecorder; public PAppletMethods() { } public void setDir(String dir) { baseDir = new File(dir); } public void setRecorder(boolean rec) { includeRecorder = rec; } public void execute() throws BuildException { // Do a bunch of checks... if (baseDir == null) { throw new BuildException("dir parameter must be set!"); } //System.out.println("using basedir " + baseDir); File graphicsFile = new File(baseDir, "PGraphics.java"); File appletFile = new File(baseDir, "PApplet.java"); File imageFile = new File(baseDir, "PImage.java"); if (!graphicsFile.exists() || !graphicsFile.canRead()) { throw new BuildException("PGraphics file not readable: " + graphicsFile.getAbsolutePath()); } if (!appletFile.exists() || !appletFile.canRead() || !appletFile.canWrite()) { throw new BuildException("PApplet file not read/writeable: " + appletFile.getAbsolutePath()); } if (!imageFile.exists() || !imageFile.canRead()) { throw new BuildException("PImage file not readable: " + imageFile.getAbsolutePath()); } // Looking good, let's do this! //ByteArrayOutputStream outBytes = new ByteArrayOutputStream(); //PrintStream out = new PrintStream(outBytes, "UTF-8"); StringBuilder out = new StringBuilder(); StringBuilder content = new StringBuilder(); try{ BufferedReader applet = createReader(appletFile); String line; while ((line = applet.readLine()) != null) { out.append(line); out.append('\n'); // to avoid Windows CRs content.append(line); content.append('\n'); // for efficiency if (line.indexOf("public functions for processing.core") >= 0) { break; } } // read the rest of the file and append it to the while ((line = applet.readLine()) != null) { content.append(line); content.append('\n'); } applet.close(); process(out, graphicsFile); process(out, imageFile); out.append('}'); out.append('\n'); //} catch (IOException e) { //e.printStackTrace(); } catch (Exception e) { //ex.printStackTrace(); throw new BuildException(e); } //out.flush(); String outString = out.toString(); if (content.toString().equals(outString)) { System.out.println("No changes to PApplet API."); } else { System.out.println("Updating PApplet with API changes " + "from PImage or PGraphics."); try { PrintStream temp = new PrintStream(appletFile, "UTF-8"); temp.print(outString); temp.flush(); temp.close(); } catch (IOException e) { //e.printStackTrace(); throw new BuildException(e); } } } private void process(StringBuilder out, File input) throws IOException { BufferedReader in = createReader(input); int comments = 0; String line = null; StringBuilder commentBuffer = new StringBuilder(); while ((line = in.readLine()) != null) { String decl = ""; // Keep track of comments //if (line.matches(Pattern.quote("/*"))) { if (line.indexOf("/*") != -1) { comments++; } //if (line.matches(Pattern.quote("*/"))) { if (line.indexOf("*/") != -1) { commentBuffer.append(line); commentBuffer.append('\n'); //System.out.println("comment is: " + commentBuffer.toString()); comments--; // otherwise gotSomething will be false, and nuke the comment continue; } // Ignore everything inside comments if (comments > 0) { commentBuffer.append(line); commentBuffer.append('\n'); continue; } boolean gotSomething = false; boolean gotStatic = false; Matcher result; if ((result = Pattern.compile("^\\s*public ([\\w\\[\\]]+) [a-zA-z_]+\\(.*$").matcher(line)).matches()) { gotSomething = true; } else if ((result = Pattern.compile("^\\s*abstract public ([\\w\\[\\]]+) [a-zA-z_]+\\(.*$").matcher(line)).matches()) { gotSomething = true; } else if ((result = Pattern.compile("^\\s*public final ([\\w\\[\\]]+) [a-zA-z_]+\\(.*$").matcher(line)).matches()) { gotSomething = true; } else if ((result = Pattern.compile("^\\s*static public ([\\w\\[\\]]+) [a-zA-z_]+\\(.*$").matcher(line)).matches()) { gotSomething = true; gotStatic = true; } // if function is marked "// ignore" then, uh, ignore it. if (gotSomething && line.indexOf("// ignore") >= 0) { gotSomething = false; } String returns = ""; if (gotSomething) { if (result.group(1).equals("void")) { returns = ""; } else { returns = "return "; } // remove the abstract modifier line = line.replaceFirst(Pattern.quote("abstract"), " "); // replace semicolons with a start def line = line.replaceAll(Pattern.quote(";"), " {\n"); //out.println("\n\n" + line); out.append('\n'); out.append('\n'); // end has its own newline //out.print(commentBuffer.toString()); // TODO disabled for now XXXX out.append(commentBuffer.toString()); // duplicates all comments commentBuffer.setLength(0); out.append(line); out.append('\n'); decl += line; while(line.indexOf(')') == -1) { line = in.readLine(); decl += line; line = line.replaceAll("\\;\\s*$", " {\n"); out.append(line); out.append('\n'); } result = Pattern.compile(".*?\\s(\\S+)\\(.*?").matcher(decl); // try to match. don't remove this or things will stop working! result.matches(); String declName = result.group(1); String gline = ""; String rline = ""; if (gotStatic) { gline = " " + returns + "PGraphics." + declName + "("; } else { rline = " if (recorder != null) recorder." + declName + "("; gline = " " + returns + "g." + declName + "("; } decl = decl.replaceAll("\\s+", " "); // smush onto a single line decl = decl.replaceFirst("^.*\\(", ""); decl = decl.replaceFirst("\\).*$", ""); int prev = 0; String parts[] = decl.split("\\, "); for (String part : parts) { if (!part.trim().equals("")) { String blargh[] = part.split(" "); String theArg = blargh[1].replaceAll("[\\[\\]]", ""); if (prev != 0) { gline += ", "; rline += ", "; } gline += theArg; rline += theArg; prev = 1; } } gline += ");"; rline += ");"; if (!gotStatic && returns.equals("") && includeRecorder) { out.append(rline); out.append('\n'); } out.append(gline); out.append('\n'); out.append(" }"); out.append('\n'); } else { commentBuffer.setLength(0); } } in.close(); } static BufferedReader createReader(File file) throws IOException { FileInputStream fis = new FileInputStream(file); return new BufferedReader(new InputStreamReader(fis, "UTF-8")); } }