From d58f6c455b7988b159dcac9bc6c95ab0ed438451 Mon Sep 17 00:00:00 2001 From: benfry Date: Sat, 17 Jan 2004 18:33:04 +0000 Subject: [PATCH] more work on build/export --- processing/app/PdeCompiler.java | 104 --------- processing/app/PdeSketch.java | 377 +++++++++++++++++++++++++++++++- processing/build/macosx/make.sh | 22 +- processing/todo.txt | 2 + 4 files changed, 386 insertions(+), 119 deletions(-) diff --git a/processing/app/PdeCompiler.java b/processing/app/PdeCompiler.java index 084e0634b..024101850 100644 --- a/processing/app/PdeCompiler.java +++ b/processing/app/PdeCompiler.java @@ -366,108 +366,4 @@ public class PdeCompiler implements PdeMessageConsumer { } return importCount; } - - - /// - - - /** - * Slurps up .class files from a colon (or semicolon on windows) - * separated list of paths and adds them to a ZipOutputStream. - */ - static public void magicExports(String path, ZipOutputStream zos) - throws IOException { - String pieces[] = - BApplet.splitStrings(path, File.pathSeparatorChar); - - for (int i = 0; i < pieces.length; i++) { - if (pieces[i].length() == 0) continue; - //System.out.println("checking piece " + pieces[i]); - - // is it a jar file or directory? - if (pieces[i].toLowerCase().endsWith(".jar") || - pieces[i].toLowerCase().endsWith(".zip")) { - try { - ZipFile file = new ZipFile(pieces[i]); - Enumeration entries = file.entries(); - while (entries.hasMoreElements()) { - ZipEntry entry = (ZipEntry) entries.nextElement(); - if (entry.isDirectory()) { - // actually 'continue's for all dir entries - - } else { - String name = entry.getName(); - // ignore contents of the META-INF folders - if (name.indexOf("META-INF") == 0) continue; - ZipEntry entree = new ZipEntry(name); - - zos.putNextEntry(entree); - byte buffer[] = new byte[(int) entry.getSize()]; - InputStream is = file.getInputStream(entry); - - int offset = 0; - int remaining = buffer.length; - while (remaining > 0) { - int count = is.read(buffer, offset, remaining); - offset += count; - remaining -= count; - } - - zos.write(buffer); - zos.flush(); - zos.closeEntry(); - } - } - } catch (IOException e) { - System.err.println("Error in file " + pieces[i]); - e.printStackTrace(); - } - } else { // not a .jar or .zip, prolly a directory - File dir = new File(pieces[i]); - // but must be a dir, since it's one of several paths - // just need to check if it exists - if (dir.exists()) { - magicExportsRecursive(dir, null, zos); - } - } - } - } - - - /** - * Continue the process of magical exporting. This function - * can be called recursively to walk through folders looking - * for more goodies that will be added to the ZipOutputStream. - */ - static public void magicExportsRecursive(File dir, String sofar, - ZipOutputStream zos) - throws IOException { - - String files[] = dir.list(); - for (int i = 0; i < files.length; i++) { - //if (files[i].equals(".") || files[i].equals("..")) continue; - // ignore . .. and .DS_Store - if (files[i].charAt(0) == '.') continue; - - File sub = new File(dir, files[i]); - String nowfar = (sofar == null) ? - files[i] : (sofar + "/" + files[i]); - - if (sub.isDirectory()) { - magicExportsRecursive(sub, nowfar, zos); - - } else { - // don't add .jar and .zip files, since they only work - // inside the root, and they're unpacked - if (!files[i].toLowerCase().endsWith(".jar") && - !files[i].toLowerCase().endsWith(".zip") && - files[i].charAt(0) != '.') { - ZipEntry entry = new ZipEntry(nowfar); - zos.putNextEntry(entry); - zos.write(PdeBase.grabFile(sub)); - zos.closeEntry(); - } - } - } - } } diff --git a/processing/app/PdeSketch.java b/processing/app/PdeSketch.java index b14a96995..0e2949d63 100644 --- a/processing/app/PdeSketch.java +++ b/processing/app/PdeSketch.java @@ -29,7 +29,6 @@ Export to: [ Applet (for the web) + ] [ OK ] [ ] OK to overwrite HTML file <-- only visible if there is one there remembers previous setting as a pref - > Advanced Version: [ Java 1.1 + ] @@ -77,9 +76,14 @@ Export to: [ Library + ] [ OK ] */ public class PdeSketch { + // name of sketch, which is the name of main file + // (without .pde or .java extension) + String name; + + // String path; // path to 'main' file for this sketch - String name; + // the sketch folder File directory; static final int PDE = 0; @@ -102,6 +106,7 @@ public class PdeSketch { System.out.println("main file is " + mainFile); main = mainFile.getName(); + System.out.println("main file is " + main); /* if (main.endsWith(".pde")) { main = main.substring(0, main.length() - 4); @@ -121,7 +126,7 @@ public class PdeSketch { /** * Build the list of files. * - * Generally his is only done once, rather than + * Generally this is only done once, rather than * each time a change is made, because otherwise it gets to be * a nightmare to keep track of what files went where, because * not all the data will be saved to disk. @@ -210,7 +215,7 @@ public class PdeSketch { who = j; // this guy is earlier in the alphabet } } - if (who != i) { // swap with someone + if (who != i) { // swap with someone if changes made PdeCode temp = code[who]; code[who] = code[i]; code[i] = temp; @@ -220,7 +225,7 @@ public class PdeSketch { /** - * Change the file currently being edited. + * Change what file is currently being edited. * 1. store the String for the text of the current file. * 2. retrieve the String for the text of the new file. * 3. change the text that's visible in the text area @@ -244,6 +249,7 @@ public class PdeSketch { } + /** * This is not Runnable.run(), but a handler for the run() command. * @@ -387,10 +393,13 @@ public class PdeSketch { */ - // in an advanced program, the returned classname could be different, - // which is why the className is set based on the return value. - // @return null if compilation failed, className if not - // + /** + * Build all the code for this sketch. + * + * In an advanced program, the returned classname could be different, + * which is why the className is set based on the return value. + * @return null if compilation failed, className if not + */ protected String build(String buildPath, String suggestedClassName) throws PdeException, Exception { @@ -483,6 +492,356 @@ public class PdeSketch { } + public void exportApplet(boolean replaceHtml) { + //File appletDir, String exportSketchName, File dataDir) { + try { + String program = textarea.getText(); + + // create the project directory + // pass null for datapath because the files shouldn't be + // copied to the build dir.. that's only for the temp stuff + File appletDir = new File(directory, "applet"); + + boolean writeHtml = true; + if (appletDir.exists()) { + File htmlFile = new new File(appletDir, "index.html"); + if (htmlFile.exists() && !replaceHtml) { + writeHtml = false; + } + } else { + appletDir.mkdirs(); + } + + // build the sketch + String foundName = build(name, appletDir.getPath()); + + // (already reported) error during export, exit this function + if (foundName == null) { + buttons.clear(); + return; + } + + // if name != exportSketchName, then that's weirdness + // BUG unfortunately, that can also be a bug in the preproc :( + if (!name.equals(foundName)) { + PdeBase.showWarning("Error during export", + "Sketch name is " + name + " but the sketch\n" + + "name in the code was " + foundName); + return; + } + + if (writeHtml) { + int wide = BApplet.DEFAULT_WIDTH; + int high = BApplet.DEFAULT_HEIGHT; + + try { + PatternMatcher matcher = new Perl5Matcher(); + PatternCompiler compiler = new Perl5Compiler(); + + // this matches against any uses of the size() function, + // whether they contain numbers of variables or whatever. + // this way, no warning is shown if size() isn't actually + // used in the applet, which is the case especially for + // beginners that are cutting/pasting from the reference. + String sizing = + "[\\s\\;]size\\s*\\(\\s*(\\S+)\\s*,\\s*(\\S+)\\s*\\);"; + Pattern pattern = compiler.compile(sizing); + + // adds a space at the beginning, in case size() is the very + // first thing in the program (very common), since the regexp + // needs to check for things in front of it. + PatternMatcherInput input = new PatternMatcherInput(" " + program); + if (matcher.contains(input, pattern)) { + MatchResult result = matcher.getMatch(); + try { + wide = Integer.parseInt(result.group(1).toString()); + high = Integer.parseInt(result.group(2).toString()); + + } catch (NumberFormatException e) { + // found a reference to size, but it didn't + // seem to contain numbers + final String message = + "The size of this applet could not automatically be\n" + + "determined from your code. You'll have to edit the\n" + + "HTML file to set the size of the applet."; + + PdeBase.showWarning("Could not find applet size", message, null); + } + } // else no size() command found + + } catch (MalformedPatternException e) { + PdeBase.showWarning("Internal Problem", + "An internal error occurred while trying\n" + + "to export the sketch. Please report this.", e); + } + + StringBuffer sources = new StringBuffer(); + for (int i = 0; i < codeCount; i++) { + sources.append("" + + code[i].name + " "); + } + + File htmlOutputFile = new File(appletDir, "index.html"); + FileOutputStream fos = new FileOutputStream(htmlOutputFile); + PrintStream ps = new PrintStream(fos); + + // @@sketch@@, @@width@@, @@height@@, @@archive@@, @@source@@ + + InputStream is = PdeBase.getStream("applet.html"); + BufferedReader reader = new BufferedReader(new InputStreamReader(is)); + + String line = null; + while ((line = reader.readLine()) != null) { + if (line.indexOf("@@") != -1) { + StringBuffer sb = new StringBuffer(line); + int index = 0; + while ((index = sb.indexOf("@@sketch@@")) != -1) { + sb.replace(index, index + "@@sketch@@".length(), + name); + } + while ((index = sb.indexOf("@@source@@")) != -1) { + sb.replace(index, index + "@@source@@".length(), + sources.toString()); + } + while ((index = sb.indexOf("@@archive@@")) != -1) { + sb.replace(index, index + "@@archive@@".length(), + name + ".jar"); + } + while ((index = sb.indexOf("@@width@@")) != -1) { + sb.replace(index, index + "@@width@@".length(), + String.valueOf(wide)); + } + while ((index = sb.indexOf("@@height@@")) != -1) { + sb.replace(index, index + "@@height@@".length(), + String.valueOf(wide)); + } + line = sb.toString(); + } + ps.println(line); + } + + reader.close(); + + ps.flush(); + ps.close(); + } + + // copy the source files to the target, since we like + // to encourage people to share their code + for (int i = 0; i < codeCount; i++) { + PdeBase.copyFile(code[i].file, + new File(appletDir, code[i].file.getName())); + } + + // create new .jar file + FileOutputStream zipOutputFile = + new FileOutputStream(new File(appletDir, name + ".jar")); + ZipOutputStream zos = new ZipOutputStream(zipOutputFile); + ZipEntry entry; + + // add the contents of the code folder to the jar + // unpacks all jar files + File codeFolder = new File(sketchDir, "code"); + if (codeFolder.exists()) { + String includes = PdeCompiler.contentsToClassPath(codeFolder); + packClassPathIntoZipFile(includes, zos); + } + + // add the appropriate bagel to the classpath + String jdkVersionStr = PdePreferences.get("compiler.jdk_version"); + String bagelJar = "lib/export11.jar"; // default + if (jdkVersion.equals("1.3") || jdkVersion.equals("1.4")) { + bagelJar = "lib/export13.jar"; + } + //if (jdkVersionStr.equals("1.3")) { bagelJar = "export13.jar" }; + //if (jdkVersionStr.equals("1.4")) { bagelJar = "export14.jar" }; + packClassPathIntoZipFile(bagelJar); + + /* + // add the contents of lib/export to the jar file + // these are the jdk11-only bagel classes + String exportDir = ("lib" + File.separator + + "export" + File.separator); + String bagelClasses[] = new File(exportDir).list(); + + for (int i = 0; i < bagelClasses.length; i++) { + if (!bagelClasses[i].endsWith(".class")) continue; + entry = new ZipEntry(bagelClasses[i]); + zos.putNextEntry(entry); + zos.write(PdeBase.grabFile(new File(exportDir + bagelClasses[i]))); + zos.closeEntry(); + } + */ + + // files to include from data directory + if ((dataDir != null) && (dataDir.exists())) { + String datafiles[] = dataDir.list(); + for (int i = 0; i < datafiles.length; i++) { + // don't export hidden files, this handles, . .. .DS_Store + if (datafiles[i].charAt(0) == '.') continue; + //if (datafiles[i].equals(".") || datafiles[i].equals("..")) { + //continue; + //} + entry = new ZipEntry(datafiles[i]); + zos.putNextEntry(entry); + zos.write(PdeBase.grabFile(new File(dataDir, datafiles[i]))); + zos.closeEntry(); + } + } + + // add the project's .class to the jar + // actually, these should grab everything from the build directory + // since there may be some inner classes + // (add any .class files from the applet dir, then delete them) + String classfiles[] = appletDir.list(); + for (int i = 0; i < classfiles.length; i++) { + if (classfiles[i].endsWith(".class")) { + entry = new ZipEntry(classfiles[i]); + zos.putNextEntry(entry); + zos.write(PdeBase.grabFile(new File(appletDir, classfiles[i]))); + zos.closeEntry(); + } + } + + // remove the .class files from the applet folder. if they're not + // removed, the msjvm will complain about an illegal access error, + // since the classes are outside the jar file. + for (int i = 0; i < classfiles.length; i++) { + if (classfiles[i].endsWith(".class")) { + File deadguy = new File(appletDir, classfiles[i]); + if (!deadguy.delete()) { + System.err.println(classfiles[i] + + " could not be deleted from the applet folder."); + System.err.println("You'll need to remove it by hand."); + } + } + } + + // close up the jar file + zos.flush(); + zos.close(); + + // make a copy of the .pde file to post on the web + FileOutputStream sketchOutput = + new FileOutputStream(new File(appletDir, name + ".pde")); + PrintWriter sketchWriter = + new PrintWriter(new OutputStreamWriter(sketchOutput)); + sketchWriter.print(program); + sketchWriter.flush(); + sketchWriter.close(); + + message("Done exporting."); + PdeBase.openFolder(appletDir); + + } catch (Exception e) { + message("Error during export."); + e.printStackTrace(); + } + buttons.clear(); + } + + + /** + * Slurps up .class files from a colon (or semicolon on windows) + * separated list of paths and adds them to a ZipOutputStream. + */ + static public void packClassPathIntoZipFile(String path, ZipOutputStream zos) + throws IOException { + String pieces[] = + BApplet.splitStrings(path, File.pathSeparatorChar); + + for (int i = 0; i < pieces.length; i++) { + if (pieces[i].length() == 0) continue; + //System.out.println("checking piece " + pieces[i]); + + // is it a jar file or directory? + if (pieces[i].toLowerCase().endsWith(".jar") || + pieces[i].toLowerCase().endsWith(".zip")) { + try { + ZipFile file = new ZipFile(pieces[i]); + Enumeration entries = file.entries(); + while (entries.hasMoreElements()) { + ZipEntry entry = (ZipEntry) entries.nextElement(); + if (entry.isDirectory()) { + // actually 'continue's for all dir entries + + } else { + String name = entry.getName(); + // ignore contents of the META-INF folders + if (name.indexOf("META-INF") == 0) continue; + ZipEntry entree = new ZipEntry(name); + + zos.putNextEntry(entree); + byte buffer[] = new byte[(int) entry.getSize()]; + InputStream is = file.getInputStream(entry); + + int offset = 0; + int remaining = buffer.length; + while (remaining > 0) { + int count = is.read(buffer, offset, remaining); + offset += count; + remaining -= count; + } + + zos.write(buffer); + zos.flush(); + zos.closeEntry(); + } + } + } catch (IOException e) { + System.err.println("Error in file " + pieces[i]); + e.printStackTrace(); + } + } else { // not a .jar or .zip, prolly a directory + File dir = new File(pieces[i]); + // but must be a dir, since it's one of several paths + // just need to check if it exists + if (dir.exists()) { + packClassPathIntoZipFileRecursive(dir, null, zos); + } + } + } + } + + + /** + * Continue the process of magical exporting. This function + * can be called recursively to walk through folders looking + * for more goodies that will be added to the ZipOutputStream. + */ + static public void packClassPathIntoZipFileRecursive(File dir, String sofar, + ZipOutputStream zos) + throws IOException { + + String files[] = dir.list(); + for (int i = 0; i < files.length; i++) { + //if (files[i].equals(".") || files[i].equals("..")) continue; + // ignore . .. and .DS_Store + if (files[i].charAt(0) == '.') continue; + + File sub = new File(dir, files[i]); + String nowfar = (sofar == null) ? + files[i] : (sofar + "/" + files[i]); + + if (sub.isDirectory()) { + packClassPathIntoZipFileRecursive(sub, nowfar, zos); + + } else { + // don't add .jar and .zip files, since they only work + // inside the root, and they're unpacked + if (!files[i].toLowerCase().endsWith(".jar") && + !files[i].toLowerCase().endsWith(".zip") && + files[i].charAt(0) != '.') { + ZipEntry entry = new ZipEntry(nowfar); + zos.putNextEntry(entry); + zos.write(PdeBase.grabFile(sub)); + zos.closeEntry(); + } + } + } + } + + /** * Returns true if this is a read-only sketch. Used for the * examples directory, or when sketches are loaded from read-only diff --git a/processing/build/macosx/make.sh b/processing/build/macosx/make.sh index 5829fb32f..97cb1cb34 100755 --- a/processing/build/macosx/make.sh +++ b/processing/build/macosx/make.sh @@ -104,14 +104,24 @@ CLASSPATH=/System/Library/Frameworks/JavaVM.framework/Classes/classes.jar:/Syste export CLASSPATH ### --- make version with all the goodies for the application -echo Building bagel with serial, video, audio, and jdk13 support -perl make.pl JIKES=../build/macosx/work/jikes SERIAL RXTX VIDEO SONIC JDK13 -cp classes/*.class ../build/macosx/work/classes/ +#echo Building bagel with serial, video, audio, and jdk13 support +#perl make.pl JIKES=../build/macosx/work/jikes SERIAL RXTX VIDEO SONIC JDK13 +#cp classes/*.class ../build/macosx/work/classes/ ### --- make version without serial for applet exporting -echo Building bagel for export with audio -perl make.pl JIKES=../build/macosx/work/jikes SONIC -cp classes/*.class ../build/macosx/work/lib/export/ +#echo Building bagel for export with audio +#perl make.pl JIKES=../build/macosx/work/jikes SONIC +#cp classes/*.class ../build/macosx/work/lib/export/ + +echo Building export classes for 1.1 +rm -rf classes && mkdir classes +perl make.pl JIKES=../build/macosx/work/jikes +cd classes && zip -r0q ../build/macosx/work/lib/export11.jar && cd .. + +echo Building export classes for 1.3 +rm -rf classes && mkdir classes +perl make.pl JIKES=../build/macosx/work/jikes +cd classes && zip -r0q ../build/macosx/work/lib/export13.jar && cd .. cd .. cd app diff --git a/processing/todo.txt b/processing/todo.txt index b39daa1e2..b07731014 100644 --- a/processing/todo.txt +++ b/processing/todo.txt @@ -68,6 +68,8 @@ o http://proce55ing.net/discourse/yabb/YaBB.cgi?board=Proce55ing_Software;acti o try ariel's Thread.yield() suggestion o set default framerate of 24? 30? 2x that? +_ fix make.sh and dist.sh for all platforms to include new export setup + _ re-implement history (disabled for 68) _ sync files into lib/build rather than copying everything new