From 49c3435b36b6cde2b9209d0e47e3b39b0eb930a6 Mon Sep 17 00:00:00 2001 From: Kyle Feuz Date: Thu, 20 Nov 2014 12:57:04 -0700 Subject: [PATCH 1/2] Normalize line endings. Auto-detect textfiles. Force .java and .pde files to be treated as text. --- .gitattributes | 3 + .../processing/app/contrib/Contribution.java | 462 +++--- .../app/contrib/ContributionManager.java | 1102 +++++++------- .../app/contrib/LocalContribution.java | 1354 ++++++++--------- .../app/contrib/ModeContribution.java | 352 ++--- .../app/contrib/ToolContribution.java | 348 ++--- app/src/processing/mode/java/preproc/pde.g | 788 +++++----- app/test/resources/bug1064.expected | 58 +- app/test/resources/bug136.expected | 82 +- app/test/resources/bug1362.expected | 58 +- app/test/resources/bug1442.expected | 56 +- app/test/resources/bug1511.expected | 74 +- app/test/resources/bug1512.expected | 58 +- app/test/resources/bug1514a.expected | 70 +- app/test/resources/bug1514b.expected | 70 +- app/test/resources/bug1515.expected | 64 +- app/test/resources/bug1516.expected | 104 +- app/test/resources/bug1517.expected | 104 +- app/test/resources/bug1518a.expected | 90 +- app/test/resources/bug1518b.expected | 86 +- app/test/resources/bug281.expected | 64 +- app/test/resources/bug481.expected | 64 +- app/test/resources/bug598.expected | 140 +- app/test/resources/bug5a.expected | 60 +- app/test/resources/bug5b.expected | 60 +- build/macosx/jAppleMenuBar.url | 4 +- build/shared/lib/fonts/LICENSE.txt | 186 +-- build/windows/processing.bat | 4 +- .../dxf/.settings/org.eclipse.jdt.core.prefs | 24 +- .../.settings/org.eclipse.jdt.core.prefs | 24 +- 30 files changed, 3008 insertions(+), 3005 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..f4fc69cb2 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +* text=auto +*.java text +*.pde text diff --git a/app/src/processing/app/contrib/Contribution.java b/app/src/processing/app/contrib/Contribution.java index 3bb1ed4ee..183d7ffd2 100644 --- a/app/src/processing/app/contrib/Contribution.java +++ b/app/src/processing/app/contrib/Contribution.java @@ -1,231 +1,231 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2013 The Processing Foundation - Copyright (c) 2011-12 Ben Fry and Casey Reas - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. - - This program 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 for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -package processing.app.contrib; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import processing.core.PApplet; - - -abstract public class Contribution { - static final String SPECIAL_CATEGORY_NAME = "Starred"; - static final List validCategories = - Arrays.asList("3D", "Animation", "Data", "Geometry", "GUI", "Hardware", - "I/O", "Math", "Simulation", "Sound", SPECIAL_CATEGORY_NAME, "Typography", - "Utilities", "Video & Vision", "Other"); - - //protected String category; // "Sound" - protected List categories; // "Sound", "Typography" - protected String name; // "pdf" or "PDF Export" - protected String authorList; // Ben Fry - protected String url; // http://processing.org - protected String sentence; // Write graphics to PDF files. - protected String paragraph; // - protected int version; // 102 - protected String prettyVersion; // "1.0.2" - protected long lastUpdated; // 1402805757 - protected int minRevision; // 0 - protected int maxRevision; // 227 - - - // "Sound" -// public String getCategory() { -// return category; -// } - - - // "Sound", "Utilities"... see valid list in ContributionListing - protected List getCategories() { - return categories; - } - - - protected String getCategoryStr() { - StringBuilder sb = new StringBuilder(); - for (String category : categories) { - sb.append(category); - sb.append(','); - } - sb.deleteCharAt(sb.length()-1); // delete last comma - return sb.toString(); - } - - - protected boolean hasCategory(String category) { - if (category != null) { - for (String c : categories) { - if (category.equalsIgnoreCase(c)) { - return true; - } - } - } - return false; - } - - - // "pdf" or "PDF Export" - public String getName() { - return name; - } - - - // "[Ben Fry](http://benfry.com/)" - public String getAuthorList() { - return authorList; - } - - - // "http://processing.org" - public String getUrl() { - return url; - } - - - // "Write graphics to PDF files." - public String getSentence() { - return sentence; - } - - - // - public String getParagraph() { - return paragraph; - } - - - // 102 - public int getVersion() { - return version; - } - - - // "1.0.2" - public String getPrettyVersion() { - return prettyVersion; - } - - // 1402805757 - public long getLastUpdated() { - return lastUpdated; - } - - // 0 - public int getMinRevision() { - return minRevision; - } - - // 227 - public int getMaxRevision() { - return maxRevision; - } - - - public boolean isCompatible(int versionNum) { - return ((maxRevision == 0 || versionNum < maxRevision) && versionNum > minRevision); - } - - - abstract public ContributionType getType(); - - - public String getTypeName() { - return getType().toString(); - } - - - abstract public boolean isInstalled(); - - -// /** -// * Returns true if the type of contribution requires the PDE to restart -// * when being added or removed. -// */ -// public boolean requiresRestart() { -// return getType() == ContributionType.TOOL || getType() == ContributionType.MODE; -// } - - - boolean isRestartFlagged() { - return false; - } - - - /** Overridden by LocalContribution. */ - boolean isDeletionFlagged() { - return false; - } - - - boolean isUpdateFlagged() { - return false; - } - - - /** - * Returns true if the contribution is a starred/recommended contribution, or - * is by the Processing Foundation. - * - * @return - */ - boolean isSpecial() { - try { - return (authorList.indexOf("The Processing Foundation") != -1 || - categories.contains(SPECIAL_CATEGORY_NAME)); - } catch (NullPointerException npe) { - return false; - } - } - - - /** - * @return a single element list with "Unknown" as the category. - */ - static List defaultCategory() { - List outgoing = new ArrayList(); - outgoing.add("Unknown"); - return outgoing; - } - - - /** - * @return the list of categories that this contribution is part of - * (e.g. "Typography / Geometry"). "Unknown" if the category null. - */ - static List parseCategories(String categoryStr) { - List outgoing = new ArrayList(); - - if (categoryStr != null) { - String[] listing = PApplet.trim(PApplet.split(categoryStr, ',')); - for (String category : listing) { - if (validCategories.contains(category)) { - outgoing.add(category); - } - } - } - if (outgoing.size() == 0) { - return defaultCategory(); - } - return outgoing; - } -} +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2013 The Processing Foundation + Copyright (c) 2011-12 Ben Fry and Casey Reas + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 + as published by the Free Software Foundation. + + This program 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 for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +package processing.app.contrib; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import processing.core.PApplet; + + +abstract public class Contribution { + static final String SPECIAL_CATEGORY_NAME = "Starred"; + static final List validCategories = + Arrays.asList("3D", "Animation", "Data", "Geometry", "GUI", "Hardware", + "I/O", "Math", "Simulation", "Sound", SPECIAL_CATEGORY_NAME, "Typography", + "Utilities", "Video & Vision", "Other"); + + //protected String category; // "Sound" + protected List categories; // "Sound", "Typography" + protected String name; // "pdf" or "PDF Export" + protected String authorList; // Ben Fry + protected String url; // http://processing.org + protected String sentence; // Write graphics to PDF files. + protected String paragraph; // + protected int version; // 102 + protected String prettyVersion; // "1.0.2" + protected long lastUpdated; // 1402805757 + protected int minRevision; // 0 + protected int maxRevision; // 227 + + + // "Sound" +// public String getCategory() { +// return category; +// } + + + // "Sound", "Utilities"... see valid list in ContributionListing + protected List getCategories() { + return categories; + } + + + protected String getCategoryStr() { + StringBuilder sb = new StringBuilder(); + for (String category : categories) { + sb.append(category); + sb.append(','); + } + sb.deleteCharAt(sb.length()-1); // delete last comma + return sb.toString(); + } + + + protected boolean hasCategory(String category) { + if (category != null) { + for (String c : categories) { + if (category.equalsIgnoreCase(c)) { + return true; + } + } + } + return false; + } + + + // "pdf" or "PDF Export" + public String getName() { + return name; + } + + + // "[Ben Fry](http://benfry.com/)" + public String getAuthorList() { + return authorList; + } + + + // "http://processing.org" + public String getUrl() { + return url; + } + + + // "Write graphics to PDF files." + public String getSentence() { + return sentence; + } + + + // + public String getParagraph() { + return paragraph; + } + + + // 102 + public int getVersion() { + return version; + } + + + // "1.0.2" + public String getPrettyVersion() { + return prettyVersion; + } + + // 1402805757 + public long getLastUpdated() { + return lastUpdated; + } + + // 0 + public int getMinRevision() { + return minRevision; + } + + // 227 + public int getMaxRevision() { + return maxRevision; + } + + + public boolean isCompatible(int versionNum) { + return ((maxRevision == 0 || versionNum < maxRevision) && versionNum > minRevision); + } + + + abstract public ContributionType getType(); + + + public String getTypeName() { + return getType().toString(); + } + + + abstract public boolean isInstalled(); + + +// /** +// * Returns true if the type of contribution requires the PDE to restart +// * when being added or removed. +// */ +// public boolean requiresRestart() { +// return getType() == ContributionType.TOOL || getType() == ContributionType.MODE; +// } + + + boolean isRestartFlagged() { + return false; + } + + + /** Overridden by LocalContribution. */ + boolean isDeletionFlagged() { + return false; + } + + + boolean isUpdateFlagged() { + return false; + } + + + /** + * Returns true if the contribution is a starred/recommended contribution, or + * is by the Processing Foundation. + * + * @return + */ + boolean isSpecial() { + try { + return (authorList.indexOf("The Processing Foundation") != -1 || + categories.contains(SPECIAL_CATEGORY_NAME)); + } catch (NullPointerException npe) { + return false; + } + } + + + /** + * @return a single element list with "Unknown" as the category. + */ + static List defaultCategory() { + List outgoing = new ArrayList(); + outgoing.add("Unknown"); + return outgoing; + } + + + /** + * @return the list of categories that this contribution is part of + * (e.g. "Typography / Geometry"). "Unknown" if the category null. + */ + static List parseCategories(String categoryStr) { + List outgoing = new ArrayList(); + + if (categoryStr != null) { + String[] listing = PApplet.trim(PApplet.split(categoryStr, ',')); + for (String category : listing) { + if (validCategories.contains(category)) { + outgoing.add(category); + } + } + } + if (outgoing.size() == 0) { + return defaultCategory(); + } + return outgoing; + } +} diff --git a/app/src/processing/app/contrib/ContributionManager.java b/app/src/processing/app/contrib/ContributionManager.java index eba5d13a8..c46de9c91 100644 --- a/app/src/processing/app/contrib/ContributionManager.java +++ b/app/src/processing/app/contrib/ContributionManager.java @@ -1,551 +1,551 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2013 The Processing Foundation - Copyright (c) 2011-12 Ben Fry and Casey Reas - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. - - This program 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 for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -package processing.app.contrib; - -import java.io.*; -import java.net.*; -import java.util.*; - -import javax.swing.SwingWorker; - -import processing.app.Base; -import processing.app.Editor; -import processing.app.Language; - - -public class ContributionManager { - static public final ContributionListing contribListing; - - static { - contribListing = ContributionListing.getInstance(); - } - - - /** - * Blocks until the file is downloaded or an error occurs. Returns true if the - * file was successfully downloaded, false otherwise. - * - * @param source - * the URL of the file to download - * @param dest - * the file on the local system where the file will be written. This - * must be a file (not a directory), and must already exist. - * @param progress - * null if progress is irrelevant, such as when downloading for an - * install during startup, when the ProgressMonitor is useless since - * UI isn't setup yet. - * @throws FileNotFoundException - * if an error occurred downloading the file - */ - static boolean download(URL source, File dest, ProgressMonitor progress) { - boolean success = false; - try { -// System.out.println("downloading file " + source); -// URLConnection conn = source.openConnection(); - HttpURLConnection conn = (HttpURLConnection) source.openConnection(); - HttpURLConnection.setFollowRedirects(true); - conn.setConnectTimeout(15 * 1000); - conn.setReadTimeout(60 * 1000); - conn.setRequestMethod("GET"); - conn.connect(); - - if (progress != null) { - // TODO this is often -1, may need to set progress to indeterminate - int fileSize = conn.getContentLength(); -// System.out.println("file size is " + fileSize); - progress.startTask(Language.text("contrib.progress.downloading"), fileSize); - } - - InputStream in = conn.getInputStream(); - FileOutputStream out = new FileOutputStream(dest); - - byte[] b = new byte[8192]; - int amount; - if (progress != null) { - int total = 0; - while (!progress.isCanceled() && (amount = in.read(b)) != -1) { - out.write(b, 0, amount); - total += amount; - progress.setProgress(total); - } - } else { - while ((amount = in.read(b)) != -1) { - out.write(b, 0, amount); - } - } - out.flush(); - out.close(); - success = true; - - } catch (SocketTimeoutException ste) { - if (progress != null) { - progress.error(ste); - progress.cancel(); - } - } catch (IOException ioe) { - if (progress != null) { - progress.error(ioe); - progress.cancel(); - } - // Hiding stack trace. An error has been shown where needed. -// ioe.printStackTrace(); - } - if (progress != null) - progress.finished(); - return success; - } - - - /** - * Non-blocking call to download and install a contribution in a new thread. - * - * @param url - * Direct link to the contribution. - * @param toBeReplaced - * The Contribution that will be replaced by this library being - * installed (e.g. an advertised version of a contribution, or the - * old version of a contribution that is being updated). Must not be - * null. - */ - static void downloadAndInstall(final Editor editor, - final URL url, - final AvailableContribution ad, - final JProgressMonitor downloadProgress, - final JProgressMonitor installProgress, - final StatusPanel status) { - - new Thread(new Runnable() { - public void run() { - String filename = url.getFile(); - filename = filename.substring(filename.lastIndexOf('/') + 1); - try { - File contribZip = File.createTempFile("download", filename); - contribZip.setWritable(true); // necessary? - - try { - download(url, contribZip, downloadProgress); - - if (!downloadProgress.isCanceled() && !downloadProgress.isError()) { - installProgress.startTask(Language.text("contrib.progress.installing"), ProgressMonitor.UNKNOWN); - LocalContribution contribution = - ad.install(editor.getBase(), contribZip, false, status); - - if (contribution != null) { - contribListing.replaceContribution(ad, contribution); - if (contribution.getType() == ContributionType.MODE) { - ArrayList contribModes = editor.getBase().getModeContribs(); - if (!contribModes.contains(contribution)) - contribModes.add((ModeContribution) contribution); - } - refreshInstalled(editor); - } - installProgress.finished(); - } - else { - if (downloadProgress.exception instanceof SocketTimeoutException) { - status.setErrorMessage(Language - .interpolate("contrib.errors.contrib_download.timeout", - ad.getName())); - } else { - status.setErrorMessage(Language - .interpolate("contrib.errors.download_and_install", - ad.getName())); - } - } - contribZip.delete(); - - } catch (Exception e) { - // Hiding stack trace. The error message ought to suffice. -// e.printStackTrace(); - status - .setErrorMessage(Language - .interpolate("contrib.errors.download_and_install", - ad.getName())); - downloadProgress.cancel(); - installProgress.cancel(); - } - } catch (IOException e) { - status.setErrorMessage(Language.text("contrib.errors.temporary_directory")); - downloadProgress.cancel(); - installProgress.cancel(); - } - } - }, "Contribution Installer").start(); - } - - - - /** - * Non-blocking call to download and install a contribution in a new thread. - * - * @param url - * Direct link to the contribution. - * @param ad - * The AvailableContribution to be downloaded and installed. - */ - static void downloadAndInstallOnStartup(final Base base, final URL url, - final AvailableContribution ad) { - - new Thread(new Runnable() { - public void run() { - String filename = url.getFile(); - filename = filename.substring(filename.lastIndexOf('/') + 1); - try { - File contribZip = File.createTempFile("download", filename); - contribZip.setWritable(true); // necessary? - - try { - download(url, contribZip, null); - - LocalContribution contribution = ad.install(base, contribZip, - false, null); - - if (contribution != null) { - contribListing.replaceContribution(ad, contribution); - if (contribution.getType() == ContributionType.MODE) { - ArrayList contribModes = base - .getModeContribs(); - if (contribModes != null && !contribModes.contains(contribution)) { - contribModes.add((ModeContribution) contribution); - } - } - if (base.getActiveEditor() != null) - refreshInstalled(base.getActiveEditor()); - } - - contribZip.delete(); - - handleUpdateFailedMarkers(ad, filename.substring(0, filename.lastIndexOf('.'))); - - } catch (Exception e) { -// Chuck the stack trace. The user might have no idea why it is appearing, or what (s)he did wrong... -// e.printStackTrace(); - System.out.println("Error during download and install of " - + ad.getName()); - } - } catch (IOException e) { - System.err - .println("Could not write to temporary directory during download and install of " - + ad.getName()); - } - } - }, "Contribution Installer").start(); - } - - -/** - * After install, this function checks whether everything went properly or not. - * If not, it adds a marker file so that the next time Processing is started, installPreviouslyFailed() - * can install the contribution. - * @param ac - * The contribution just installed. - * @param filename - * The name of the folder in which the contribution is supposed to be stored. - */ - static private void handleUpdateFailedMarkers(final AvailableContribution ac, String filename) { - - File contribLocn = ac.getType().getSketchbookFolder(); - - for (File contribDir : contribLocn.listFiles()) - if (contribDir.isDirectory()) { - File[] contents = contribDir.listFiles(new FilenameFilter() { - - @Override - public boolean accept(File dir, String file) { - return file.equals(ac.getType() + ".properties"); - } - }); - if (contents.length > 0 && Base.readSettings(contents[0]).get("name").equals(ac.getName())) { - return; - } - } - - try { - new File(contribLocn, ac.getName()).createNewFile(); - } catch (IOException e) { -// Again, forget about the stack trace. The user ain't done wrong -// e.printStackTrace(); - System.err.println("The unupdated contribution marker seems to not like " - + ac.getName() + ". You may have to install it manually to update..."); - } - - } - - - static public void refreshInstalled(Editor e) { - - Iterator iter = e.getBase().getEditors().iterator(); - while (iter.hasNext()) { - Editor ed = iter.next(); - ed.getMode().rebuildImportMenu(); - ed.getMode().resetExamples(); - ed.rebuildToolMenu(); - ed.rebuildModeMenu(); - } - } - - - /** - * Returns a file in the parent folder that does not exist yet. If - * parent/fileName already exists, this will look for parent/fileName(2) - * then parent/fileName(3) and so forth. - * - * @return a file that does not exist yet - */ - public static File getUniqueName(File parentFolder, String fileName) { - File backupFolderForLib; - int i = 1; - do { - String folderName = fileName; - if (i >= 2) { - folderName += "(" + i + ")"; - } - i++; - - backupFolderForLib = new File(parentFolder, folderName); - } while (backupFolderForLib.exists()); - - return backupFolderForLib; - } - - - /** - * Returns the name of a file without its path or extension. - * - * For example, - * "/path/to/helpfullib.zip" returns "helpfullib" - * "helpfullib-0.1.1.plb" returns "helpfullib-0.1.1" - */ - static public String getFileName(File libFile) { - String path = libFile.getPath(); - int lastSeparator = path.lastIndexOf(File.separatorChar); - - String fileName; - if (lastSeparator != -1) { - fileName = path.substring(lastSeparator + 1); - } else { - fileName = path; - } - - int lastDot = fileName.lastIndexOf('.'); - if (lastDot != -1) { - return fileName.substring(0, lastDot); - } - - return fileName; - } - - - /** - * Called by Base to clean up entries previously marked for deletion - * and remove any "requires restart" flags. - * Also updates all entries previously marked for update. - */ - static public void cleanup(final Base base) throws Exception { - - deleteTemp(Base.getSketchbookModesFolder()); - deleteTemp(Base.getSketchbookToolsFolder()); - - deleteFlagged(Base.getSketchbookLibrariesFolder()); - deleteFlagged(Base.getSketchbookModesFolder()); - deleteFlagged(Base.getSketchbookToolsFolder()); - - installPreviouslyFailed(base, Base.getSketchbookModesFolder()); - updateFlagged(base, Base.getSketchbookModesFolder()); - - updateFlagged(base, Base.getSketchbookToolsFolder()); - - SwingWorker s = new SwingWorker() { - - @Override - protected Void doInBackground() throws Exception { - try { - Thread.sleep(1 * 1000); - installPreviouslyFailed(base, Base.getSketchbookToolsFolder()); - } catch (InterruptedException e) { - e.printStackTrace(); - } - return null; - } - }; - s.execute(); - - - - clearRestartFlags(Base.getSketchbookModesFolder()); - clearRestartFlags(Base.getSketchbookToolsFolder()); - } - - - /** - * Deletes the icky tmp folders that were left over from installs and updates - * in the previous run of Processing. Needed to be called only on the tools - * and modes sketchbook folders. - * - * @param root - */ - static private void deleteTemp(File root) { - - LinkedList deleteList = new LinkedList(); - - for (File f : root.listFiles()) - if (f.getName().matches(root.getName().substring(0, 4) + "\\d*" + "tmp")) - deleteList.add(f); - - Iterator folderIter = deleteList.iterator(); - - while (folderIter.hasNext()) { - Base.removeDir(folderIter.next()); - } - } - - - /** - * Deletes all the modes/tools/libs that are flagged for removal. - * - * @param root - * @throws Exception - */ - static private void deleteFlagged(File root) throws Exception { - File[] markedForDeletion = root.listFiles(new FileFilter() { - public boolean accept(File folder) { - return (folder.isDirectory() && LocalContribution - .isDeletionFlagged(folder)); - } - }); - for (File folder : markedForDeletion) { - Base.removeDir(folder); - } - } - - - /** - * Installs all the modes/tools whose installation failed during an - * auto-update the previous time Processing was started up. - * - * @param base - * @param root - * @throws Exception - */ - static private void installPreviouslyFailed(Base base, File root) throws Exception { - File[] installList = root.listFiles(new FileFilter() { - public boolean accept(File folder) { - return (folder.isFile()); - } - }); - - for (File file : installList) { - Iterator iter = contribListing.advertisedContributions.iterator(); - while (iter.hasNext()) { - AvailableContribution availableContrib = iter.next(); - if (file.getName().equals(availableContrib.getName())) { - file.delete(); - installOnStartUp(base, availableContrib); - contribListing - .replaceContribution(availableContrib, availableContrib); - } - } - } - } - - - /** - * Updates all the flagged modes/tools. - * - * @param base - * @param root - * @throws Exception - */ - static private void updateFlagged(Base base, File root) throws Exception { - File[] markedForUpdate = root.listFiles(new FileFilter() { - public boolean accept(File folder) { - return (folder.isDirectory() && LocalContribution - .isUpdateFlagged(folder)); - } - }); - - ArrayList updateContribsNames = new ArrayList(); - LinkedList updateContribsList = new LinkedList(); - - String type = root.getName().substring(root.getName().lastIndexOf('/') + 1); - String propFileName = null; - - if (type.equalsIgnoreCase("tools")) - propFileName = "tool.properties"; - else if (type.equalsIgnoreCase("modes")) - propFileName = "mode.properties"; - else if (type.equalsIgnoreCase("libraries")) //putting this here, just in case - propFileName = "libraries.properties"; - - for (File folder : markedForUpdate) { - HashMap properties = Base - .readSettings(new File(folder, propFileName)); - updateContribsNames.add(properties.get("name")); - Base.removeDir(folder); - } - - Iterator iter = contribListing.advertisedContributions.iterator(); - while (iter.hasNext()) { - AvailableContribution availableContribs = iter.next(); - if (updateContribsNames.contains(availableContribs.getName())) { - updateContribsList.add(availableContribs); - } - } - - Iterator iter2 = updateContribsList.iterator(); - while (iter2.hasNext()) { - AvailableContribution contribToUpdate = iter2.next(); - installOnStartUp(base, contribToUpdate); - contribListing.replaceContribution(contribToUpdate, contribToUpdate); - } - } - - - static private void installOnStartUp(final Base base, final AvailableContribution availableContrib) { - if (availableContrib.link == null) { - Base.showWarning(Language.interpolate("contrib.errors.update_on_restart_failed", availableContrib.getName()), - Language.text("contrib.unsupported_operating_system")); - return; - } - try { - URL downloadUrl = new URL(availableContrib.link); - - ContributionManager.downloadAndInstallOnStartup(base, downloadUrl, availableContrib); - - } catch (MalformedURLException e) { - Base.showWarning(Language.interpolate("contrib.errors.update_on_restart_failed", availableContrib.getName()), - Language.text("contrib.errors.malformed_url"), e); - } - } - - - static private void clearRestartFlags(File root) throws Exception { - File[] folderList = root.listFiles(new FileFilter() { - public boolean accept(File folder) { - return folder.isDirectory(); - } - }); - for (File folder : folderList) { - LocalContribution.clearRestartFlags(folder); - } - } -} +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2013 The Processing Foundation + Copyright (c) 2011-12 Ben Fry and Casey Reas + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 + as published by the Free Software Foundation. + + This program 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 for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +package processing.app.contrib; + +import java.io.*; +import java.net.*; +import java.util.*; + +import javax.swing.SwingWorker; + +import processing.app.Base; +import processing.app.Editor; +import processing.app.Language; + + +public class ContributionManager { + static public final ContributionListing contribListing; + + static { + contribListing = ContributionListing.getInstance(); + } + + + /** + * Blocks until the file is downloaded or an error occurs. Returns true if the + * file was successfully downloaded, false otherwise. + * + * @param source + * the URL of the file to download + * @param dest + * the file on the local system where the file will be written. This + * must be a file (not a directory), and must already exist. + * @param progress + * null if progress is irrelevant, such as when downloading for an + * install during startup, when the ProgressMonitor is useless since + * UI isn't setup yet. + * @throws FileNotFoundException + * if an error occurred downloading the file + */ + static boolean download(URL source, File dest, ProgressMonitor progress) { + boolean success = false; + try { +// System.out.println("downloading file " + source); +// URLConnection conn = source.openConnection(); + HttpURLConnection conn = (HttpURLConnection) source.openConnection(); + HttpURLConnection.setFollowRedirects(true); + conn.setConnectTimeout(15 * 1000); + conn.setReadTimeout(60 * 1000); + conn.setRequestMethod("GET"); + conn.connect(); + + if (progress != null) { + // TODO this is often -1, may need to set progress to indeterminate + int fileSize = conn.getContentLength(); +// System.out.println("file size is " + fileSize); + progress.startTask(Language.text("contrib.progress.downloading"), fileSize); + } + + InputStream in = conn.getInputStream(); + FileOutputStream out = new FileOutputStream(dest); + + byte[] b = new byte[8192]; + int amount; + if (progress != null) { + int total = 0; + while (!progress.isCanceled() && (amount = in.read(b)) != -1) { + out.write(b, 0, amount); + total += amount; + progress.setProgress(total); + } + } else { + while ((amount = in.read(b)) != -1) { + out.write(b, 0, amount); + } + } + out.flush(); + out.close(); + success = true; + + } catch (SocketTimeoutException ste) { + if (progress != null) { + progress.error(ste); + progress.cancel(); + } + } catch (IOException ioe) { + if (progress != null) { + progress.error(ioe); + progress.cancel(); + } + // Hiding stack trace. An error has been shown where needed. +// ioe.printStackTrace(); + } + if (progress != null) + progress.finished(); + return success; + } + + + /** + * Non-blocking call to download and install a contribution in a new thread. + * + * @param url + * Direct link to the contribution. + * @param toBeReplaced + * The Contribution that will be replaced by this library being + * installed (e.g. an advertised version of a contribution, or the + * old version of a contribution that is being updated). Must not be + * null. + */ + static void downloadAndInstall(final Editor editor, + final URL url, + final AvailableContribution ad, + final JProgressMonitor downloadProgress, + final JProgressMonitor installProgress, + final StatusPanel status) { + + new Thread(new Runnable() { + public void run() { + String filename = url.getFile(); + filename = filename.substring(filename.lastIndexOf('/') + 1); + try { + File contribZip = File.createTempFile("download", filename); + contribZip.setWritable(true); // necessary? + + try { + download(url, contribZip, downloadProgress); + + if (!downloadProgress.isCanceled() && !downloadProgress.isError()) { + installProgress.startTask(Language.text("contrib.progress.installing"), ProgressMonitor.UNKNOWN); + LocalContribution contribution = + ad.install(editor.getBase(), contribZip, false, status); + + if (contribution != null) { + contribListing.replaceContribution(ad, contribution); + if (contribution.getType() == ContributionType.MODE) { + ArrayList contribModes = editor.getBase().getModeContribs(); + if (!contribModes.contains(contribution)) + contribModes.add((ModeContribution) contribution); + } + refreshInstalled(editor); + } + installProgress.finished(); + } + else { + if (downloadProgress.exception instanceof SocketTimeoutException) { + status.setErrorMessage(Language + .interpolate("contrib.errors.contrib_download.timeout", + ad.getName())); + } else { + status.setErrorMessage(Language + .interpolate("contrib.errors.download_and_install", + ad.getName())); + } + } + contribZip.delete(); + + } catch (Exception e) { + // Hiding stack trace. The error message ought to suffice. +// e.printStackTrace(); + status + .setErrorMessage(Language + .interpolate("contrib.errors.download_and_install", + ad.getName())); + downloadProgress.cancel(); + installProgress.cancel(); + } + } catch (IOException e) { + status.setErrorMessage(Language.text("contrib.errors.temporary_directory")); + downloadProgress.cancel(); + installProgress.cancel(); + } + } + }, "Contribution Installer").start(); + } + + + + /** + * Non-blocking call to download and install a contribution in a new thread. + * + * @param url + * Direct link to the contribution. + * @param ad + * The AvailableContribution to be downloaded and installed. + */ + static void downloadAndInstallOnStartup(final Base base, final URL url, + final AvailableContribution ad) { + + new Thread(new Runnable() { + public void run() { + String filename = url.getFile(); + filename = filename.substring(filename.lastIndexOf('/') + 1); + try { + File contribZip = File.createTempFile("download", filename); + contribZip.setWritable(true); // necessary? + + try { + download(url, contribZip, null); + + LocalContribution contribution = ad.install(base, contribZip, + false, null); + + if (contribution != null) { + contribListing.replaceContribution(ad, contribution); + if (contribution.getType() == ContributionType.MODE) { + ArrayList contribModes = base + .getModeContribs(); + if (contribModes != null && !contribModes.contains(contribution)) { + contribModes.add((ModeContribution) contribution); + } + } + if (base.getActiveEditor() != null) + refreshInstalled(base.getActiveEditor()); + } + + contribZip.delete(); + + handleUpdateFailedMarkers(ad, filename.substring(0, filename.lastIndexOf('.'))); + + } catch (Exception e) { +// Chuck the stack trace. The user might have no idea why it is appearing, or what (s)he did wrong... +// e.printStackTrace(); + System.out.println("Error during download and install of " + + ad.getName()); + } + } catch (IOException e) { + System.err + .println("Could not write to temporary directory during download and install of " + + ad.getName()); + } + } + }, "Contribution Installer").start(); + } + + +/** + * After install, this function checks whether everything went properly or not. + * If not, it adds a marker file so that the next time Processing is started, installPreviouslyFailed() + * can install the contribution. + * @param ac + * The contribution just installed. + * @param filename + * The name of the folder in which the contribution is supposed to be stored. + */ + static private void handleUpdateFailedMarkers(final AvailableContribution ac, String filename) { + + File contribLocn = ac.getType().getSketchbookFolder(); + + for (File contribDir : contribLocn.listFiles()) + if (contribDir.isDirectory()) { + File[] contents = contribDir.listFiles(new FilenameFilter() { + + @Override + public boolean accept(File dir, String file) { + return file.equals(ac.getType() + ".properties"); + } + }); + if (contents.length > 0 && Base.readSettings(contents[0]).get("name").equals(ac.getName())) { + return; + } + } + + try { + new File(contribLocn, ac.getName()).createNewFile(); + } catch (IOException e) { +// Again, forget about the stack trace. The user ain't done wrong +// e.printStackTrace(); + System.err.println("The unupdated contribution marker seems to not like " + + ac.getName() + ". You may have to install it manually to update..."); + } + + } + + + static public void refreshInstalled(Editor e) { + + Iterator iter = e.getBase().getEditors().iterator(); + while (iter.hasNext()) { + Editor ed = iter.next(); + ed.getMode().rebuildImportMenu(); + ed.getMode().resetExamples(); + ed.rebuildToolMenu(); + ed.rebuildModeMenu(); + } + } + + + /** + * Returns a file in the parent folder that does not exist yet. If + * parent/fileName already exists, this will look for parent/fileName(2) + * then parent/fileName(3) and so forth. + * + * @return a file that does not exist yet + */ + public static File getUniqueName(File parentFolder, String fileName) { + File backupFolderForLib; + int i = 1; + do { + String folderName = fileName; + if (i >= 2) { + folderName += "(" + i + ")"; + } + i++; + + backupFolderForLib = new File(parentFolder, folderName); + } while (backupFolderForLib.exists()); + + return backupFolderForLib; + } + + + /** + * Returns the name of a file without its path or extension. + * + * For example, + * "/path/to/helpfullib.zip" returns "helpfullib" + * "helpfullib-0.1.1.plb" returns "helpfullib-0.1.1" + */ + static public String getFileName(File libFile) { + String path = libFile.getPath(); + int lastSeparator = path.lastIndexOf(File.separatorChar); + + String fileName; + if (lastSeparator != -1) { + fileName = path.substring(lastSeparator + 1); + } else { + fileName = path; + } + + int lastDot = fileName.lastIndexOf('.'); + if (lastDot != -1) { + return fileName.substring(0, lastDot); + } + + return fileName; + } + + + /** + * Called by Base to clean up entries previously marked for deletion + * and remove any "requires restart" flags. + * Also updates all entries previously marked for update. + */ + static public void cleanup(final Base base) throws Exception { + + deleteTemp(Base.getSketchbookModesFolder()); + deleteTemp(Base.getSketchbookToolsFolder()); + + deleteFlagged(Base.getSketchbookLibrariesFolder()); + deleteFlagged(Base.getSketchbookModesFolder()); + deleteFlagged(Base.getSketchbookToolsFolder()); + + installPreviouslyFailed(base, Base.getSketchbookModesFolder()); + updateFlagged(base, Base.getSketchbookModesFolder()); + + updateFlagged(base, Base.getSketchbookToolsFolder()); + + SwingWorker s = new SwingWorker() { + + @Override + protected Void doInBackground() throws Exception { + try { + Thread.sleep(1 * 1000); + installPreviouslyFailed(base, Base.getSketchbookToolsFolder()); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return null; + } + }; + s.execute(); + + + + clearRestartFlags(Base.getSketchbookModesFolder()); + clearRestartFlags(Base.getSketchbookToolsFolder()); + } + + + /** + * Deletes the icky tmp folders that were left over from installs and updates + * in the previous run of Processing. Needed to be called only on the tools + * and modes sketchbook folders. + * + * @param root + */ + static private void deleteTemp(File root) { + + LinkedList deleteList = new LinkedList(); + + for (File f : root.listFiles()) + if (f.getName().matches(root.getName().substring(0, 4) + "\\d*" + "tmp")) + deleteList.add(f); + + Iterator folderIter = deleteList.iterator(); + + while (folderIter.hasNext()) { + Base.removeDir(folderIter.next()); + } + } + + + /** + * Deletes all the modes/tools/libs that are flagged for removal. + * + * @param root + * @throws Exception + */ + static private void deleteFlagged(File root) throws Exception { + File[] markedForDeletion = root.listFiles(new FileFilter() { + public boolean accept(File folder) { + return (folder.isDirectory() && LocalContribution + .isDeletionFlagged(folder)); + } + }); + for (File folder : markedForDeletion) { + Base.removeDir(folder); + } + } + + + /** + * Installs all the modes/tools whose installation failed during an + * auto-update the previous time Processing was started up. + * + * @param base + * @param root + * @throws Exception + */ + static private void installPreviouslyFailed(Base base, File root) throws Exception { + File[] installList = root.listFiles(new FileFilter() { + public boolean accept(File folder) { + return (folder.isFile()); + } + }); + + for (File file : installList) { + Iterator iter = contribListing.advertisedContributions.iterator(); + while (iter.hasNext()) { + AvailableContribution availableContrib = iter.next(); + if (file.getName().equals(availableContrib.getName())) { + file.delete(); + installOnStartUp(base, availableContrib); + contribListing + .replaceContribution(availableContrib, availableContrib); + } + } + } + } + + + /** + * Updates all the flagged modes/tools. + * + * @param base + * @param root + * @throws Exception + */ + static private void updateFlagged(Base base, File root) throws Exception { + File[] markedForUpdate = root.listFiles(new FileFilter() { + public boolean accept(File folder) { + return (folder.isDirectory() && LocalContribution + .isUpdateFlagged(folder)); + } + }); + + ArrayList updateContribsNames = new ArrayList(); + LinkedList updateContribsList = new LinkedList(); + + String type = root.getName().substring(root.getName().lastIndexOf('/') + 1); + String propFileName = null; + + if (type.equalsIgnoreCase("tools")) + propFileName = "tool.properties"; + else if (type.equalsIgnoreCase("modes")) + propFileName = "mode.properties"; + else if (type.equalsIgnoreCase("libraries")) //putting this here, just in case + propFileName = "libraries.properties"; + + for (File folder : markedForUpdate) { + HashMap properties = Base + .readSettings(new File(folder, propFileName)); + updateContribsNames.add(properties.get("name")); + Base.removeDir(folder); + } + + Iterator iter = contribListing.advertisedContributions.iterator(); + while (iter.hasNext()) { + AvailableContribution availableContribs = iter.next(); + if (updateContribsNames.contains(availableContribs.getName())) { + updateContribsList.add(availableContribs); + } + } + + Iterator iter2 = updateContribsList.iterator(); + while (iter2.hasNext()) { + AvailableContribution contribToUpdate = iter2.next(); + installOnStartUp(base, contribToUpdate); + contribListing.replaceContribution(contribToUpdate, contribToUpdate); + } + } + + + static private void installOnStartUp(final Base base, final AvailableContribution availableContrib) { + if (availableContrib.link == null) { + Base.showWarning(Language.interpolate("contrib.errors.update_on_restart_failed", availableContrib.getName()), + Language.text("contrib.unsupported_operating_system")); + return; + } + try { + URL downloadUrl = new URL(availableContrib.link); + + ContributionManager.downloadAndInstallOnStartup(base, downloadUrl, availableContrib); + + } catch (MalformedURLException e) { + Base.showWarning(Language.interpolate("contrib.errors.update_on_restart_failed", availableContrib.getName()), + Language.text("contrib.errors.malformed_url"), e); + } + } + + + static private void clearRestartFlags(File root) throws Exception { + File[] folderList = root.listFiles(new FileFilter() { + public boolean accept(File folder) { + return folder.isDirectory(); + } + }); + for (File folder : folderList) { + LocalContribution.clearRestartFlags(folder); + } + } +} diff --git a/app/src/processing/app/contrib/LocalContribution.java b/app/src/processing/app/contrib/LocalContribution.java index bb6faf1ea..929625cd0 100644 --- a/app/src/processing/app/contrib/LocalContribution.java +++ b/app/src/processing/app/contrib/LocalContribution.java @@ -1,677 +1,677 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2013 The Processing Foundation - Copyright (c) 2011-12 Ben Fry and Casey Reas - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. - - This program 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 for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -package processing.app.contrib; - -import java.io.*; -import java.net.URL; -import java.net.URLClassLoader; -import java.text.SimpleDateFormat; -import java.util.*; -import java.util.zip.*; - -import javax.swing.JOptionPane; - -import processing.app.*; -import processing.core.PApplet; - - -/** - * A contribution that has been downloaded to the disk, and may or may not - * be installed. - */ -public abstract class LocalContribution extends Contribution { - static public final String DELETION_FLAG = "marked_for_deletion"; - static public final String UPDATE_FLAGGED = "marked_for_update"; - static public final String RESTART_FLAG = "requires_restart"; - - protected String id; // 1 (unique id for this library) - protected int latestVersion; // 103 - protected File folder; - protected HashMap properties; - protected ClassLoader loader; - - - public LocalContribution(File folder) { - this.folder = folder; - - // required for contributed modes, but not for built-in core modes - File propertiesFile = new File(folder, getTypeName() + ".properties"); - if (propertiesFile.exists()) { - properties = Base.readSettings(propertiesFile); - - name = properties.get("name"); - id = properties.get("id"); - categories = parseCategories(properties.get("category")); - if (name == null) { - name = folder.getName(); - } - authorList = properties.get("authorList"); - url = properties.get("url"); - sentence = properties.get("sentence"); - paragraph = properties.get("paragraph"); - - try { - version = Integer.parseInt(properties.get("version")); - } catch (NumberFormatException e) { - System.err.println("The version number for the “" + name + "” library is not set properly."); - System.err.println("Please contact the library author to fix it according to the guidelines."); - } - - prettyVersion = properties.get("prettyVersion"); - - try { - lastUpdated = Long.parseLong(properties.get("lastUpdated")); - } catch (NumberFormatException e) { - lastUpdated = 0; - - // Better comment these out till all contribs have a lastUpdated -// System.err.println("The last updated timestamp for the “" + name + "” library is not set properly."); -// System.err.println("Please contact the library author to fix it according to the guidelines."); - } - - String minRev = properties.get("minRevision"); - if (minRev != null) { - minRevision = PApplet.parseInt(minRev, 0); - } - - String maxRev = properties.get("maxRevision"); - if (maxRev != null) { - maxRevision = PApplet.parseInt(maxRev, 0); - } - - } else { - Base.log("No properties file at " + propertiesFile.getAbsolutePath()); - // We'll need this to be set at a minimum. - name = folder.getName(); - categories = defaultCategory(); - } - - if (categories.contains(SPECIAL_CATEGORY_NAME)) - validateSpecial(); - } - - - private void validateSpecial() { - for (AvailableContribution available : ContributionListing.getInstance().advertisedContributions) - if (available.getName().equals(name)) { - if (!available.isSpecial()) - categories.remove(SPECIAL_CATEGORY_NAME); - } - return; - } - - - public String initLoader(String className) throws Exception { - File modeDirectory = new File(folder, getTypeName()); - if (modeDirectory.exists()) { - Base.log("checking mode folder regarding " + className); - // If no class name specified, search the main .jar for the - // full name package and mode name. - if (className == null) { - String shortName = folder.getName(); - File mainJar = new File(modeDirectory, shortName + ".jar"); - if (mainJar.exists()) { - className = findClassInZipFile(shortName, mainJar); - } else { - throw new IgnorableException(mainJar.getAbsolutePath() + " does not exist."); - } - - if (className == null) { - throw new IgnorableException("Could not find " + shortName + - " class inside " + mainJar.getAbsolutePath()); - } - } - - // Add .jar and .zip files from the "mode" folder into the classpath - File[] archives = Base.listJarFiles(modeDirectory); - if (archives != null && archives.length > 0) { - URL[] urlList = new URL[archives.length]; - for (int j = 0; j < urlList.length; j++) { - Base.log("Found archive " + archives[j] + " for " + getName()); - urlList[j] = archives[j].toURI().toURL(); - } -// loader = new URLClassLoader(urlList, Thread.currentThread().getContextClassLoader()); - loader = new URLClassLoader(urlList); - Base.log("loading above JARs with loader " + loader); -// System.out.println("listing classes for loader " + loader); -// listClasses(loader); - } - } - - // If no archives were found, just use the regular ClassLoader - if (loader == null) { - loader = Thread.currentThread().getContextClassLoader(); - } - return className; - } - - - /* - // doesn't work with URLClassLoader, but works with the system CL - static void listClasses(ClassLoader loader) { -// loader = Thread.currentThread().getContextClassLoader(); - try { - Field f = ClassLoader.class.getDeclaredField("classes"); - f.setAccessible(true); - Vector classes = (Vector) f.get(loader); - for (Class c : classes) { - System.out.println(c.getName()); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - */ - - -// static protected boolean isCandidate(File potential, final ContributionType type) { -// return (potential.isDirectory() && -// new File(potential, type.getFolderName()).exists()); -// } -// -// -// /** -// * Return a list of directories that have the necessary subfolder for this -// * contribution type. For instance, a list of folders that have a 'mode' -// * subfolder if this is a ModeContribution. -// */ -// static protected File[] listCandidates(File folder, final ContributionType type) { -// return folder.listFiles(new FileFilter() { -// public boolean accept(File potential) { -// return isCandidate(potential, type); -// } -// }); -// } -// -// -// /** -// * Return the first directory that has the necessary subfolder for this -// * contribution type. For instance, the first folder that has a 'mode' -// * subfolder if this is a ModeContribution. -// */ -// static protected File findCandidate(File folder, final ContributionType type) { -// File[] folders = listCandidates(folder, type); -// -// if (folders.length == 0) { -// return null; -// -// } else if (folders.length > 1) { -// Base.log("More than one " + type.toString() + " found inside " + folder.getAbsolutePath()); -// } -// return folders[0]; -// } - - - LocalContribution copyAndLoad(Base base, - boolean confirmReplace, - StatusPanel status) { -// NOTE: null status => function is called on startup when Editor objects, et al. aren't ready - - String contribFolderName = getFolder().getName(); - - File contribTypeFolder = getType().getSketchbookFolder(); - File contribFolder = new File(contribTypeFolder, contribFolderName); - - if (status != null) { // when status != null, install is not occurring on startup - - Editor editor = base.getActiveEditor(); - - ArrayList oldContribs = - getType().listContributions(editor); - - // In case an update marker exists, and the user wants to install, delete the update marker - if (contribFolder.exists() && !contribFolder.isDirectory()) { - contribFolder.delete(); - contribFolder = new File(contribTypeFolder, contribFolderName); - } - - for (LocalContribution oldContrib : oldContribs) { - if ((oldContrib.getFolder().exists() && oldContrib.getFolder().equals(contribFolder)) || - (oldContrib.getId() != null && oldContrib.getId().equals(getId()))) { - - if (oldContrib.getType().requiresRestart()) { - // XXX: We can't replace stuff, soooooo.... do something different - if (!oldContrib.backup(editor, false, status)) { - return null; - } - } else { - int result = 0; - boolean doBackup = Preferences.getBoolean("contribution.backup.on_install"); - if (confirmReplace) { - if (doBackup) { - result = Base.showYesNoQuestion(editor, "Replace", - "Replace pre-existing \"" + oldContrib.getName() + "\" library?", - "A pre-existing copy of the \"" + oldContrib.getName() + "\" library
"+ - "has been found in your sketchbook. Clicking “Yes”
"+ - "will move the existing library to a backup folder
" + - "in libraries/old before replacing it."); - if (result != JOptionPane.YES_OPTION || !oldContrib.backup(editor, true, status)) { - return null; - } - } else { - result = Base.showYesNoQuestion(editor, "Replace", - "Replace pre-existing \"" + oldContrib.getName() + "\" library?", - "A pre-existing copy of the \"" + oldContrib.getName() + "\" library
"+ - "has been found in your sketchbook. Clicking “Yes”
"+ - "will permanently delete this library and all of its contents
"+ - "before replacing it."); - if (result != JOptionPane.YES_OPTION || !oldContrib.getFolder().delete()) { - return null; - } - } - } else { - if ((doBackup && !oldContrib.backup(editor, true, status)) || - (!doBackup && !oldContrib.getFolder().delete())) { - return null; - } - } - } - } - } - - // At this point it should be safe to replace this fella - if (contribFolder.exists()) { - Base.removeDir(contribFolder); - } - - } - else { - // This if should ideally never happen, since this function is to be called only when restarting on update - if (contribFolder.exists() && contribFolder.isDirectory()) { - Base.removeDir(contribFolder); - } - else if (contribFolder.exists()) { - contribFolder.delete(); - contribFolder = new File(contribTypeFolder, contribFolderName); - } - } - - File oldFolder = getFolder(); - - try { - Base.copyDir(oldFolder, contribFolder); - } catch (IOException e) { - status.setErrorMessage("Could not copy " + getTypeName() + - " \"" + getName() + "\" to the sketchbook."); - e.printStackTrace(); - return null; - } - - - /* - if (!getFolder().renameTo(contribFolder)) { - status.setErrorMessage("Could not move " + getTypeName() + - " \"" + getName() + "\" to the sketchbook."); - return null; - } - */ - - return getType().load(base, contribFolder); - } - - - /** - * Moves the given contribution to a backup folder. - * @param deleteOriginal - * true if the file should be moved to the directory, false if it - * should instead be copied, leaving the original in place - */ - boolean backup(Editor editor, boolean deleteOriginal, StatusPanel status) { - File backupFolder = getType().createBackupFolder(status); - - boolean success = false; - if (backupFolder != null) { - String libFolderName = getFolder().getName(); - String prefix = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); - final String backupName = prefix + " " + libFolderName; - File backupSubFolder = - ContributionManager.getUniqueName(backupFolder, backupName); - - if (deleteOriginal) { - success = getFolder().renameTo(backupSubFolder); - } else { - try { - Base.copyDir(getFolder(), backupSubFolder); - success = true; - } catch (IOException e) { } - } - if (!success) { - status.setErrorMessage("Could not move contribution to backup folder."); - } - } - return success; - } - - - /** - * Non-blocking call to remove a contribution in a new thread. - */ - void removeContribution(final Editor editor, - final ProgressMonitor pm, - final StatusPanel status) { - new Thread(new Runnable() { - public void run() { - remove(editor, - pm, - status, - ContributionListing.getInstance()); - } - }, "Contribution Uninstaller").start(); - } - - - void remove(final Editor editor, - final ProgressMonitor pm, - final StatusPanel status, - final ContributionListing contribListing) { - pm.startTask("Removing", ProgressMonitor.UNKNOWN); - - boolean doBackup = Preferences.getBoolean("contribution.backup.on_remove"); -// if (getType().requiresRestart()) { -// if (!doBackup || (doBackup && backup(editor, false, status))) { -// if (setDeletionFlag(true)) { -// contribListing.replaceContribution(this, this); -// } -// } -// } else { - boolean success = false; - if (getType() == ContributionType.MODE) { - boolean isModeActive = false; - ModeContribution m = (ModeContribution) this; - Iterator iter = editor.getBase().getEditors().iterator(); - while (iter.hasNext()) { - Editor e = iter.next(); - if (e.getMode().equals(m.getMode())) { - isModeActive = true; - break; - } - } - if (!isModeActive) - m.clearClassLoader(editor.getBase()); - else { - pm.cancel(); - Base.showMessage("Mode Manager", - "Please save your Sketch and change the Mode of all Editor\nwindows that have " - + this.name + " as the active Mode."); - return; - } - } - - if (getType() == ContributionType.TOOL) { - ToolContribution t = (ToolContribution) this; - Iterator iter = editor.getBase().getEditors().iterator(); - while (iter.hasNext()) { - Editor ed = iter.next(); - ed.clearToolMenu(); - } - t.clearClassLoader(editor.getBase()); - } - - if (doBackup) { - success = backup(editor, true, status); - } else { - Base.removeDir(getFolder()); - success = !getFolder().exists(); - } - - if (success) { - if (getType() == ContributionType.TOOL) { - editor.removeTool(); - } - - Contribution advertisedVersion = contribListing - .getAvailableContribution(this); - - if (advertisedVersion == null) { - contribListing.removeContribution(this); - } else { - contribListing.replaceContribution(this, advertisedVersion); - } - } - else { - // There was a failure backing up the folder - if (!doBackup || (doBackup && backup(editor, false, status))) { - if (setDeletionFlag(true)) { - contribListing.replaceContribution(this, this); - } - } - else - status.setErrorMessage("Could not delete the contribution's files"); - } -// } - ContributionManager.refreshInstalled(editor); - if (success) - pm.finished(); - else - pm.cancel(); - } - - - public File getFolder() { - return folder; - } - - - public boolean isInstalled() { - return folder != null; - } - - -// public String getCategory() { -// return category; -// } -// -// -// public String getName() { -// return name; -// } - - - public String getId() { - return id; - } - - -// public String getAuthorList() { -// return authorList; -// } -// -// -// public String getUrl() { -// return url; -// } -// -// -// public String getSentence() { -// return sentence; -// } -// -// -// public String getParagraph() { -// return paragraph; -// } -// -// -// public int getVersion() { -// return version; -// } - - - public int getLatestVersion() { - return latestVersion; - } - - -// public String getPrettyVersion() { -// return prettyVersion; -// } -// -// -// public String getTypeName() { -// return getType().toString(); -// } - - - /* - static protected String findClassInZipFileList(String base, File[] fileList) { - for (File file : fileList) { - String found = findClassInZipFile(base, file); - if (found != null) { - return found; - } - } - return null; - } - */ - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - boolean setDeletionFlag(boolean flag) { - return setFlag(DELETION_FLAG, flag); - } - - - boolean isDeletionFlagged() { - return isDeletionFlagged(getFolder()); - } - - - static boolean isDeletionFlagged(File folder) { - return isFlagged(folder, DELETION_FLAG); - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - boolean setUpdateFlag(boolean flag) { - return setFlag(UPDATE_FLAGGED, flag); - } - - - boolean isUpdateFlagged() { - return isUpdateFlagged(getFolder()); - } - - - static boolean isUpdateFlagged(File folder) { - return isFlagged(folder, UPDATE_FLAGGED); - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - boolean setRestartFlag() { - //System.out.println("setting restart flag for " + folder); - return setFlag(RESTART_FLAG, true); - } - - - @Override - boolean isRestartFlagged() { - //System.out.println("checking for restart inside LocalContribution for " + getName()); - return isFlagged(getFolder(), RESTART_FLAG); - } - - - static void clearRestartFlags(File folder) { - File restartFlag = new File(folder, RESTART_FLAG); - if (restartFlag.exists()) { - restartFlag.delete(); - } - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - private boolean setFlag(String flagFilename, boolean flag) { - if (flag) { - // Only returns false if the file already exists, so we can - // ignore the return value. - try { - new File(getFolder(), flagFilename).createNewFile(); - return true; - } catch (IOException e) { - return false; - } - } else { - return new File(getFolder(), flagFilename).delete(); - } - } - - - static private boolean isFlagged(File folder, String flagFilename) { - return new File(folder, flagFilename).exists(); - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - /** - * - * @param base name of the class, with or without the package - * @param file - * @return name of class (with full package name) or null if not found - */ - static protected String findClassInZipFile(String base, File file) { - // Class file to search for - String classFileName = "/" + base + ".class"; - - try { - ZipFile zipFile = new ZipFile(file); - Enumeration entries = zipFile.entries(); - while (entries.hasMoreElements()) { - ZipEntry entry = (ZipEntry) entries.nextElement(); - - if (!entry.isDirectory()) { - String name = entry.getName(); -// System.out.println("entry: " + name); - - if (name.endsWith(classFileName)) { - //int slash = name.lastIndexOf('/'); - //String packageName = (slash == -1) ? "" : name.substring(0, slash); - // Remove .class and convert slashes to periods. - zipFile.close(); - return name.substring(0, name.length() - 6).replace('/', '.'); - } - } - } - zipFile.close(); - } catch (IOException e) { - //System.err.println("Ignoring " + filename + " (" + e.getMessage() + ")"); - e.printStackTrace(); - } - return null; - } - - - static protected class IgnorableException extends Exception { - public IgnorableException(String msg) { - super(msg); - } - } -} +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2013 The Processing Foundation + Copyright (c) 2011-12 Ben Fry and Casey Reas + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 + as published by the Free Software Foundation. + + This program 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 for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +package processing.app.contrib; + +import java.io.*; +import java.net.URL; +import java.net.URLClassLoader; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.zip.*; + +import javax.swing.JOptionPane; + +import processing.app.*; +import processing.core.PApplet; + + +/** + * A contribution that has been downloaded to the disk, and may or may not + * be installed. + */ +public abstract class LocalContribution extends Contribution { + static public final String DELETION_FLAG = "marked_for_deletion"; + static public final String UPDATE_FLAGGED = "marked_for_update"; + static public final String RESTART_FLAG = "requires_restart"; + + protected String id; // 1 (unique id for this library) + protected int latestVersion; // 103 + protected File folder; + protected HashMap properties; + protected ClassLoader loader; + + + public LocalContribution(File folder) { + this.folder = folder; + + // required for contributed modes, but not for built-in core modes + File propertiesFile = new File(folder, getTypeName() + ".properties"); + if (propertiesFile.exists()) { + properties = Base.readSettings(propertiesFile); + + name = properties.get("name"); + id = properties.get("id"); + categories = parseCategories(properties.get("category")); + if (name == null) { + name = folder.getName(); + } + authorList = properties.get("authorList"); + url = properties.get("url"); + sentence = properties.get("sentence"); + paragraph = properties.get("paragraph"); + + try { + version = Integer.parseInt(properties.get("version")); + } catch (NumberFormatException e) { + System.err.println("The version number for the “" + name + "” library is not set properly."); + System.err.println("Please contact the library author to fix it according to the guidelines."); + } + + prettyVersion = properties.get("prettyVersion"); + + try { + lastUpdated = Long.parseLong(properties.get("lastUpdated")); + } catch (NumberFormatException e) { + lastUpdated = 0; + + // Better comment these out till all contribs have a lastUpdated +// System.err.println("The last updated timestamp for the “" + name + "” library is not set properly."); +// System.err.println("Please contact the library author to fix it according to the guidelines."); + } + + String minRev = properties.get("minRevision"); + if (minRev != null) { + minRevision = PApplet.parseInt(minRev, 0); + } + + String maxRev = properties.get("maxRevision"); + if (maxRev != null) { + maxRevision = PApplet.parseInt(maxRev, 0); + } + + } else { + Base.log("No properties file at " + propertiesFile.getAbsolutePath()); + // We'll need this to be set at a minimum. + name = folder.getName(); + categories = defaultCategory(); + } + + if (categories.contains(SPECIAL_CATEGORY_NAME)) + validateSpecial(); + } + + + private void validateSpecial() { + for (AvailableContribution available : ContributionListing.getInstance().advertisedContributions) + if (available.getName().equals(name)) { + if (!available.isSpecial()) + categories.remove(SPECIAL_CATEGORY_NAME); + } + return; + } + + + public String initLoader(String className) throws Exception { + File modeDirectory = new File(folder, getTypeName()); + if (modeDirectory.exists()) { + Base.log("checking mode folder regarding " + className); + // If no class name specified, search the main .jar for the + // full name package and mode name. + if (className == null) { + String shortName = folder.getName(); + File mainJar = new File(modeDirectory, shortName + ".jar"); + if (mainJar.exists()) { + className = findClassInZipFile(shortName, mainJar); + } else { + throw new IgnorableException(mainJar.getAbsolutePath() + " does not exist."); + } + + if (className == null) { + throw new IgnorableException("Could not find " + shortName + + " class inside " + mainJar.getAbsolutePath()); + } + } + + // Add .jar and .zip files from the "mode" folder into the classpath + File[] archives = Base.listJarFiles(modeDirectory); + if (archives != null && archives.length > 0) { + URL[] urlList = new URL[archives.length]; + for (int j = 0; j < urlList.length; j++) { + Base.log("Found archive " + archives[j] + " for " + getName()); + urlList[j] = archives[j].toURI().toURL(); + } +// loader = new URLClassLoader(urlList, Thread.currentThread().getContextClassLoader()); + loader = new URLClassLoader(urlList); + Base.log("loading above JARs with loader " + loader); +// System.out.println("listing classes for loader " + loader); +// listClasses(loader); + } + } + + // If no archives were found, just use the regular ClassLoader + if (loader == null) { + loader = Thread.currentThread().getContextClassLoader(); + } + return className; + } + + + /* + // doesn't work with URLClassLoader, but works with the system CL + static void listClasses(ClassLoader loader) { +// loader = Thread.currentThread().getContextClassLoader(); + try { + Field f = ClassLoader.class.getDeclaredField("classes"); + f.setAccessible(true); + Vector classes = (Vector) f.get(loader); + for (Class c : classes) { + System.out.println(c.getName()); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + */ + + +// static protected boolean isCandidate(File potential, final ContributionType type) { +// return (potential.isDirectory() && +// new File(potential, type.getFolderName()).exists()); +// } +// +// +// /** +// * Return a list of directories that have the necessary subfolder for this +// * contribution type. For instance, a list of folders that have a 'mode' +// * subfolder if this is a ModeContribution. +// */ +// static protected File[] listCandidates(File folder, final ContributionType type) { +// return folder.listFiles(new FileFilter() { +// public boolean accept(File potential) { +// return isCandidate(potential, type); +// } +// }); +// } +// +// +// /** +// * Return the first directory that has the necessary subfolder for this +// * contribution type. For instance, the first folder that has a 'mode' +// * subfolder if this is a ModeContribution. +// */ +// static protected File findCandidate(File folder, final ContributionType type) { +// File[] folders = listCandidates(folder, type); +// +// if (folders.length == 0) { +// return null; +// +// } else if (folders.length > 1) { +// Base.log("More than one " + type.toString() + " found inside " + folder.getAbsolutePath()); +// } +// return folders[0]; +// } + + + LocalContribution copyAndLoad(Base base, + boolean confirmReplace, + StatusPanel status) { +// NOTE: null status => function is called on startup when Editor objects, et al. aren't ready + + String contribFolderName = getFolder().getName(); + + File contribTypeFolder = getType().getSketchbookFolder(); + File contribFolder = new File(contribTypeFolder, contribFolderName); + + if (status != null) { // when status != null, install is not occurring on startup + + Editor editor = base.getActiveEditor(); + + ArrayList oldContribs = + getType().listContributions(editor); + + // In case an update marker exists, and the user wants to install, delete the update marker + if (contribFolder.exists() && !contribFolder.isDirectory()) { + contribFolder.delete(); + contribFolder = new File(contribTypeFolder, contribFolderName); + } + + for (LocalContribution oldContrib : oldContribs) { + if ((oldContrib.getFolder().exists() && oldContrib.getFolder().equals(contribFolder)) || + (oldContrib.getId() != null && oldContrib.getId().equals(getId()))) { + + if (oldContrib.getType().requiresRestart()) { + // XXX: We can't replace stuff, soooooo.... do something different + if (!oldContrib.backup(editor, false, status)) { + return null; + } + } else { + int result = 0; + boolean doBackup = Preferences.getBoolean("contribution.backup.on_install"); + if (confirmReplace) { + if (doBackup) { + result = Base.showYesNoQuestion(editor, "Replace", + "Replace pre-existing \"" + oldContrib.getName() + "\" library?", + "A pre-existing copy of the \"" + oldContrib.getName() + "\" library
"+ + "has been found in your sketchbook. Clicking “Yes”
"+ + "will move the existing library to a backup folder
" + + "in libraries/old before replacing it."); + if (result != JOptionPane.YES_OPTION || !oldContrib.backup(editor, true, status)) { + return null; + } + } else { + result = Base.showYesNoQuestion(editor, "Replace", + "Replace pre-existing \"" + oldContrib.getName() + "\" library?", + "A pre-existing copy of the \"" + oldContrib.getName() + "\" library
"+ + "has been found in your sketchbook. Clicking “Yes”
"+ + "will permanently delete this library and all of its contents
"+ + "before replacing it."); + if (result != JOptionPane.YES_OPTION || !oldContrib.getFolder().delete()) { + return null; + } + } + } else { + if ((doBackup && !oldContrib.backup(editor, true, status)) || + (!doBackup && !oldContrib.getFolder().delete())) { + return null; + } + } + } + } + } + + // At this point it should be safe to replace this fella + if (contribFolder.exists()) { + Base.removeDir(contribFolder); + } + + } + else { + // This if should ideally never happen, since this function is to be called only when restarting on update + if (contribFolder.exists() && contribFolder.isDirectory()) { + Base.removeDir(contribFolder); + } + else if (contribFolder.exists()) { + contribFolder.delete(); + contribFolder = new File(contribTypeFolder, contribFolderName); + } + } + + File oldFolder = getFolder(); + + try { + Base.copyDir(oldFolder, contribFolder); + } catch (IOException e) { + status.setErrorMessage("Could not copy " + getTypeName() + + " \"" + getName() + "\" to the sketchbook."); + e.printStackTrace(); + return null; + } + + + /* + if (!getFolder().renameTo(contribFolder)) { + status.setErrorMessage("Could not move " + getTypeName() + + " \"" + getName() + "\" to the sketchbook."); + return null; + } + */ + + return getType().load(base, contribFolder); + } + + + /** + * Moves the given contribution to a backup folder. + * @param deleteOriginal + * true if the file should be moved to the directory, false if it + * should instead be copied, leaving the original in place + */ + boolean backup(Editor editor, boolean deleteOriginal, StatusPanel status) { + File backupFolder = getType().createBackupFolder(status); + + boolean success = false; + if (backupFolder != null) { + String libFolderName = getFolder().getName(); + String prefix = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); + final String backupName = prefix + " " + libFolderName; + File backupSubFolder = + ContributionManager.getUniqueName(backupFolder, backupName); + + if (deleteOriginal) { + success = getFolder().renameTo(backupSubFolder); + } else { + try { + Base.copyDir(getFolder(), backupSubFolder); + success = true; + } catch (IOException e) { } + } + if (!success) { + status.setErrorMessage("Could not move contribution to backup folder."); + } + } + return success; + } + + + /** + * Non-blocking call to remove a contribution in a new thread. + */ + void removeContribution(final Editor editor, + final ProgressMonitor pm, + final StatusPanel status) { + new Thread(new Runnable() { + public void run() { + remove(editor, + pm, + status, + ContributionListing.getInstance()); + } + }, "Contribution Uninstaller").start(); + } + + + void remove(final Editor editor, + final ProgressMonitor pm, + final StatusPanel status, + final ContributionListing contribListing) { + pm.startTask("Removing", ProgressMonitor.UNKNOWN); + + boolean doBackup = Preferences.getBoolean("contribution.backup.on_remove"); +// if (getType().requiresRestart()) { +// if (!doBackup || (doBackup && backup(editor, false, status))) { +// if (setDeletionFlag(true)) { +// contribListing.replaceContribution(this, this); +// } +// } +// } else { + boolean success = false; + if (getType() == ContributionType.MODE) { + boolean isModeActive = false; + ModeContribution m = (ModeContribution) this; + Iterator iter = editor.getBase().getEditors().iterator(); + while (iter.hasNext()) { + Editor e = iter.next(); + if (e.getMode().equals(m.getMode())) { + isModeActive = true; + break; + } + } + if (!isModeActive) + m.clearClassLoader(editor.getBase()); + else { + pm.cancel(); + Base.showMessage("Mode Manager", + "Please save your Sketch and change the Mode of all Editor\nwindows that have " + + this.name + " as the active Mode."); + return; + } + } + + if (getType() == ContributionType.TOOL) { + ToolContribution t = (ToolContribution) this; + Iterator iter = editor.getBase().getEditors().iterator(); + while (iter.hasNext()) { + Editor ed = iter.next(); + ed.clearToolMenu(); + } + t.clearClassLoader(editor.getBase()); + } + + if (doBackup) { + success = backup(editor, true, status); + } else { + Base.removeDir(getFolder()); + success = !getFolder().exists(); + } + + if (success) { + if (getType() == ContributionType.TOOL) { + editor.removeTool(); + } + + Contribution advertisedVersion = contribListing + .getAvailableContribution(this); + + if (advertisedVersion == null) { + contribListing.removeContribution(this); + } else { + contribListing.replaceContribution(this, advertisedVersion); + } + } + else { + // There was a failure backing up the folder + if (!doBackup || (doBackup && backup(editor, false, status))) { + if (setDeletionFlag(true)) { + contribListing.replaceContribution(this, this); + } + } + else + status.setErrorMessage("Could not delete the contribution's files"); + } +// } + ContributionManager.refreshInstalled(editor); + if (success) + pm.finished(); + else + pm.cancel(); + } + + + public File getFolder() { + return folder; + } + + + public boolean isInstalled() { + return folder != null; + } + + +// public String getCategory() { +// return category; +// } +// +// +// public String getName() { +// return name; +// } + + + public String getId() { + return id; + } + + +// public String getAuthorList() { +// return authorList; +// } +// +// +// public String getUrl() { +// return url; +// } +// +// +// public String getSentence() { +// return sentence; +// } +// +// +// public String getParagraph() { +// return paragraph; +// } +// +// +// public int getVersion() { +// return version; +// } + + + public int getLatestVersion() { + return latestVersion; + } + + +// public String getPrettyVersion() { +// return prettyVersion; +// } +// +// +// public String getTypeName() { +// return getType().toString(); +// } + + + /* + static protected String findClassInZipFileList(String base, File[] fileList) { + for (File file : fileList) { + String found = findClassInZipFile(base, file); + if (found != null) { + return found; + } + } + return null; + } + */ + + + // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + + + boolean setDeletionFlag(boolean flag) { + return setFlag(DELETION_FLAG, flag); + } + + + boolean isDeletionFlagged() { + return isDeletionFlagged(getFolder()); + } + + + static boolean isDeletionFlagged(File folder) { + return isFlagged(folder, DELETION_FLAG); + } + + + // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + + + boolean setUpdateFlag(boolean flag) { + return setFlag(UPDATE_FLAGGED, flag); + } + + + boolean isUpdateFlagged() { + return isUpdateFlagged(getFolder()); + } + + + static boolean isUpdateFlagged(File folder) { + return isFlagged(folder, UPDATE_FLAGGED); + } + + + // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + + + boolean setRestartFlag() { + //System.out.println("setting restart flag for " + folder); + return setFlag(RESTART_FLAG, true); + } + + + @Override + boolean isRestartFlagged() { + //System.out.println("checking for restart inside LocalContribution for " + getName()); + return isFlagged(getFolder(), RESTART_FLAG); + } + + + static void clearRestartFlags(File folder) { + File restartFlag = new File(folder, RESTART_FLAG); + if (restartFlag.exists()) { + restartFlag.delete(); + } + } + + + // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + + + private boolean setFlag(String flagFilename, boolean flag) { + if (flag) { + // Only returns false if the file already exists, so we can + // ignore the return value. + try { + new File(getFolder(), flagFilename).createNewFile(); + return true; + } catch (IOException e) { + return false; + } + } else { + return new File(getFolder(), flagFilename).delete(); + } + } + + + static private boolean isFlagged(File folder, String flagFilename) { + return new File(folder, flagFilename).exists(); + } + + + // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + + + /** + * + * @param base name of the class, with or without the package + * @param file + * @return name of class (with full package name) or null if not found + */ + static protected String findClassInZipFile(String base, File file) { + // Class file to search for + String classFileName = "/" + base + ".class"; + + try { + ZipFile zipFile = new ZipFile(file); + Enumeration entries = zipFile.entries(); + while (entries.hasMoreElements()) { + ZipEntry entry = (ZipEntry) entries.nextElement(); + + if (!entry.isDirectory()) { + String name = entry.getName(); +// System.out.println("entry: " + name); + + if (name.endsWith(classFileName)) { + //int slash = name.lastIndexOf('/'); + //String packageName = (slash == -1) ? "" : name.substring(0, slash); + // Remove .class and convert slashes to periods. + zipFile.close(); + return name.substring(0, name.length() - 6).replace('/', '.'); + } + } + } + zipFile.close(); + } catch (IOException e) { + //System.err.println("Ignoring " + filename + " (" + e.getMessage() + ")"); + e.printStackTrace(); + } + return null; + } + + + static protected class IgnorableException extends Exception { + public IgnorableException(String msg) { + super(msg); + } + } +} diff --git a/app/src/processing/app/contrib/ModeContribution.java b/app/src/processing/app/contrib/ModeContribution.java index e37c28464..2598ffaee 100644 --- a/app/src/processing/app/contrib/ModeContribution.java +++ b/app/src/processing/app/contrib/ModeContribution.java @@ -1,176 +1,176 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2013 The Processing Foundation - Copyright (c) 2011-12 Ben Fry and Casey Reas - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. - - This program 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 for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -package processing.app.contrib; - -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Constructor; -import java.net.URLClassLoader; -import java.util.*; - -import processing.app.Base; -import processing.app.Mode; - - -public class ModeContribution extends LocalContribution { - private Mode mode; - - - static public ModeContribution load(Base base, File folder) { - return load(base, folder, null); - } - - - static public ModeContribution load(Base base, File folder, - String searchName) { - try { - return new ModeContribution(base, folder, searchName); - - } catch (IgnorableException ig) { - Base.log(ig.getMessage()); - - } catch (Throwable err) { - // Throwable to catch Exceptions or UnsupportedClassVersionError et al - if (searchName == null) { - err.printStackTrace(); - } else { - // For the built-in modes, don't print the exception, just log it - // for debugging. This should be impossible for most users to reach, - // but it helps us load experimental mode when it's available. - Base.log("ModeContribution.load() failed for " + searchName, err); - } - } - return null; - } - - - /** - * - * @param base the base object that this will be tied to - * @param folder location inside the sketchbook modes folder or contrib - * @param className name of class and full package, or null to use default - * @throws Exception - */ - private ModeContribution(Base base, File folder, - String className) throws Exception { - super(folder); - - className = initLoader(className); - if (className != null) { - Class modeClass = loader.loadClass(className); - Constructor con = modeClass.getConstructor(Base.class, File.class); - mode = (Mode) con.newInstance(base, folder); - mode.setClassLoader(loader); - if (base != null) { - mode.setupGUI(); - } - } - } - - /** - * Method to close the ClassLoader so that the archives are no longer "locked" - * and a mode can be removed without restart. - */ - public void clearClassLoader(Base base) { - - ArrayList contribModes = base.getModeContribs(); - int botherToRemove = contribModes.indexOf(this); - if (botherToRemove != -1) { // The poor thing isn't even loaded, and we're trying to remove it... - contribModes.remove(botherToRemove); - - try { - ((URLClassLoader) loader).close(); - // The typecast should be safe, since the only case when loader is not of - // type URLClassLoader is when no archives were found in the first - // place... - } catch (IOException e) { - e.printStackTrace(); - } - } - } - - static public void loadMissing(Base base) { - File modesFolder = Base.getSketchbookModesFolder(); - ArrayList contribModes = base.getModeContribs(); - - HashMap existing = new HashMap(); - for (ModeContribution contrib : contribModes) { - existing.put(contrib.getFolder(), contrib); - } - File[] potential = ContributionType.MODE.listCandidates(modesFolder); - // If modesFolder does not exist or is inaccessible (folks might like to - // mess with folders then report it as a bug) 'potential' will be null. - if (potential != null) { - for (File folder : potential) { - if (!existing.containsKey(folder)) { - try { - contribModes.add(new ModeContribution(base, folder, null)); - } catch (IgnorableException ig) { - Base.log(ig.getMessage()); - } catch (Throwable e) { - e.printStackTrace(); - } - } - } - } - - // This allows you to build and test your Mode code from Eclipse. - // -Dusemode=com.foo.FrobMode:/path/to/FrobMode - final String useMode = System.getProperty("usemode"); - if (useMode != null) { - final String[] modeInfo = useMode.split(":", 2); - final String modeClass = modeInfo[0]; - final String modeResourcePath = modeInfo[1]; - System.out.println("Attempting to load " + modeClass + " with resources at " + modeResourcePath); - contribModes.add(ModeContribution.load(base, new File(modeResourcePath), modeClass)); - } - } - - - public Mode getMode() { - return mode; - } - - - public ContributionType getType() { - return ContributionType.MODE; - } - - - public boolean equals(Object o) { - if (o == null || !(o instanceof ModeContribution)) { - return false; - } - ModeContribution other = (ModeContribution) o; - return loader.equals(other.loader) && mode.equals(other.getMode()); - } - - -// static protected List discover(File folder) { -// File[] folders = listCandidates(folder, "mode"); -// if (folders == null) { -// return new ArrayList(); -// } else { -// return Arrays.asList(folders); -// } -// } -} +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2013 The Processing Foundation + Copyright (c) 2011-12 Ben Fry and Casey Reas + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 + as published by the Free Software Foundation. + + This program 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 for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +package processing.app.contrib; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.net.URLClassLoader; +import java.util.*; + +import processing.app.Base; +import processing.app.Mode; + + +public class ModeContribution extends LocalContribution { + private Mode mode; + + + static public ModeContribution load(Base base, File folder) { + return load(base, folder, null); + } + + + static public ModeContribution load(Base base, File folder, + String searchName) { + try { + return new ModeContribution(base, folder, searchName); + + } catch (IgnorableException ig) { + Base.log(ig.getMessage()); + + } catch (Throwable err) { + // Throwable to catch Exceptions or UnsupportedClassVersionError et al + if (searchName == null) { + err.printStackTrace(); + } else { + // For the built-in modes, don't print the exception, just log it + // for debugging. This should be impossible for most users to reach, + // but it helps us load experimental mode when it's available. + Base.log("ModeContribution.load() failed for " + searchName, err); + } + } + return null; + } + + + /** + * + * @param base the base object that this will be tied to + * @param folder location inside the sketchbook modes folder or contrib + * @param className name of class and full package, or null to use default + * @throws Exception + */ + private ModeContribution(Base base, File folder, + String className) throws Exception { + super(folder); + + className = initLoader(className); + if (className != null) { + Class modeClass = loader.loadClass(className); + Constructor con = modeClass.getConstructor(Base.class, File.class); + mode = (Mode) con.newInstance(base, folder); + mode.setClassLoader(loader); + if (base != null) { + mode.setupGUI(); + } + } + } + + /** + * Method to close the ClassLoader so that the archives are no longer "locked" + * and a mode can be removed without restart. + */ + public void clearClassLoader(Base base) { + + ArrayList contribModes = base.getModeContribs(); + int botherToRemove = contribModes.indexOf(this); + if (botherToRemove != -1) { // The poor thing isn't even loaded, and we're trying to remove it... + contribModes.remove(botherToRemove); + + try { + ((URLClassLoader) loader).close(); + // The typecast should be safe, since the only case when loader is not of + // type URLClassLoader is when no archives were found in the first + // place... + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + static public void loadMissing(Base base) { + File modesFolder = Base.getSketchbookModesFolder(); + ArrayList contribModes = base.getModeContribs(); + + HashMap existing = new HashMap(); + for (ModeContribution contrib : contribModes) { + existing.put(contrib.getFolder(), contrib); + } + File[] potential = ContributionType.MODE.listCandidates(modesFolder); + // If modesFolder does not exist or is inaccessible (folks might like to + // mess with folders then report it as a bug) 'potential' will be null. + if (potential != null) { + for (File folder : potential) { + if (!existing.containsKey(folder)) { + try { + contribModes.add(new ModeContribution(base, folder, null)); + } catch (IgnorableException ig) { + Base.log(ig.getMessage()); + } catch (Throwable e) { + e.printStackTrace(); + } + } + } + } + + // This allows you to build and test your Mode code from Eclipse. + // -Dusemode=com.foo.FrobMode:/path/to/FrobMode + final String useMode = System.getProperty("usemode"); + if (useMode != null) { + final String[] modeInfo = useMode.split(":", 2); + final String modeClass = modeInfo[0]; + final String modeResourcePath = modeInfo[1]; + System.out.println("Attempting to load " + modeClass + " with resources at " + modeResourcePath); + contribModes.add(ModeContribution.load(base, new File(modeResourcePath), modeClass)); + } + } + + + public Mode getMode() { + return mode; + } + + + public ContributionType getType() { + return ContributionType.MODE; + } + + + public boolean equals(Object o) { + if (o == null || !(o instanceof ModeContribution)) { + return false; + } + ModeContribution other = (ModeContribution) o; + return loader.equals(other.loader) && mode.equals(other.getMode()); + } + + +// static protected List discover(File folder) { +// File[] folders = listCandidates(folder, "mode"); +// if (folders == null) { +// return new ArrayList(); +// } else { +// return Arrays.asList(folders); +// } +// } +} diff --git a/app/src/processing/app/contrib/ToolContribution.java b/app/src/processing/app/contrib/ToolContribution.java index 978f12447..bb8ca790c 100644 --- a/app/src/processing/app/contrib/ToolContribution.java +++ b/app/src/processing/app/contrib/ToolContribution.java @@ -1,182 +1,182 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2013 The Processing Foundation - Copyright (c) 2011-12 Ben Fry and Casey Reas - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. - - This program 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 for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -package processing.app.contrib; - -import java.io.*; -import java.net.URLClassLoader; -//import java.net.*; -import java.util.*; - -import processing.app.Base; -//import processing.app.Base; -import processing.app.Editor; -import processing.app.tools.Tool; - - -public class ToolContribution extends LocalContribution implements Tool { - private Tool tool; - - private File referenceFile; // shortname/reference/index.html - - static public ToolContribution load(File folder) { - try { - return new ToolContribution(folder); - } catch (IgnorableException ig) { - Base.log(ig.getMessage()); +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2013 The Processing Foundation + Copyright (c) 2011-12 Ben Fry and Casey Reas + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 + as published by the Free Software Foundation. + + This program 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 for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +package processing.app.contrib; + +import java.io.*; +import java.net.URLClassLoader; +//import java.net.*; +import java.util.*; + +import processing.app.Base; +//import processing.app.Base; +import processing.app.Editor; +import processing.app.tools.Tool; + + +public class ToolContribution extends LocalContribution implements Tool { + private Tool tool; + + private File referenceFile; // shortname/reference/index.html + + static public ToolContribution load(File folder) { + try { + return new ToolContribution(folder); + } catch (IgnorableException ig) { + Base.log(ig.getMessage()); } catch (VerifyError ve) { // incompatible // avoid the excessive error spew that happens here } catch (Throwable e) { // unknown error e.printStackTrace(); - } - return null; - } - - + } + return null; + } + + private ToolContribution(File folder) throws Throwable { - super(folder); - - String className = initLoader(null); - if (className != null) { - Class toolClass = loader.loadClass(className); - tool = (Tool) toolClass.newInstance(); - } - - referenceFile = new File(folder, "reference/index.html"); - } - - - /** - * Method to close the ClassLoader so that the archives are no longer "locked" and - * a tool can be removed without restart. - */ - public void clearClassLoader(Base base) { - try { - ((URLClassLoader) this.loader).close(); - } catch (IOException e1) { - e1.printStackTrace(); - } - Iterator editorIter = base.getEditors().iterator(); - while (editorIter.hasNext()) { - Editor editor = editorIter.next(); - ArrayList contribTools = editor.contribTools; - for (ToolContribution toolContrib : contribTools) - if (toolContrib.getName().equals(this.name)) { - try { - ((URLClassLoader) toolContrib.loader).close(); - editor.contribTools.remove(toolContrib); - break; - } catch (IOException e) { - e.printStackTrace(); - } -// base.getActiveEditor().rebuildToolMenu(); - } - } - } - - -// static protected List discover(File folder) { -// File[] folders = listCandidates(folder, "tool"); -// if (folders == null) { -// return new ArrayList(); -// } else { -// return Arrays.asList(folders); -// } -// } - - - static public ArrayList loadAll(File toolsFolder) { - File[] list = ContributionType.TOOL.listCandidates(toolsFolder); - ArrayList outgoing = new ArrayList(); - // If toolsFolder does not exist or is inaccessible (stranger things have - // happened, and are reported as bugs) list will come back null. - if (list != null) { - for (File folder : list) { - try { - ToolContribution tc = load(folder); - if (tc != null) { - outgoing.add(tc); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - } - return outgoing; - } - - -// Editor editor; // used to send error messages - - public void init(Editor editor) { -// try { -// this.editor = editor; - tool.init(editor); -// } catch (NoSuchMethodError nsme) { -// editor.statusError(tool.getMenuTitle() + " is not compatible with this version of Processing"); -// nsme.printStackTrace(); -// } - } - - - public void run() { -// try { - tool.run(); -// } catch (NoSuchMethodError nsme) { -// editor.statusError(tool.getMenuTitle() + " is not compatible with this version of Processing"); -// nsme.printStackTrace(); -// } - } - - - public String getMenuTitle() { - return tool.getMenuTitle(); - } - - - public ContributionType getType() { - return ContributionType.TOOL; - } - - - /** - * Returns the object stored in the referenceFile field, which contains an - * instance of the file object representing the index file of the reference - * - * @return referenceFile - */ - public File getReferenceIndexFile() { - return referenceFile; - } - - - /** - * Tests whether the reference's index file indicated by referenceFile exists. - * - * @return true if and only if the file denoted by referenceFile exists; false - * otherwise. - */ - public boolean hasReference() { - return referenceFile.exists(); - } + super(folder); + + String className = initLoader(null); + if (className != null) { + Class toolClass = loader.loadClass(className); + tool = (Tool) toolClass.newInstance(); + } + + referenceFile = new File(folder, "reference/index.html"); + } + + + /** + * Method to close the ClassLoader so that the archives are no longer "locked" and + * a tool can be removed without restart. + */ + public void clearClassLoader(Base base) { + try { + ((URLClassLoader) this.loader).close(); + } catch (IOException e1) { + e1.printStackTrace(); + } + Iterator editorIter = base.getEditors().iterator(); + while (editorIter.hasNext()) { + Editor editor = editorIter.next(); + ArrayList contribTools = editor.contribTools; + for (ToolContribution toolContrib : contribTools) + if (toolContrib.getName().equals(this.name)) { + try { + ((URLClassLoader) toolContrib.loader).close(); + editor.contribTools.remove(toolContrib); + break; + } catch (IOException e) { + e.printStackTrace(); + } +// base.getActiveEditor().rebuildToolMenu(); + } + } + } + + +// static protected List discover(File folder) { +// File[] folders = listCandidates(folder, "tool"); +// if (folders == null) { +// return new ArrayList(); +// } else { +// return Arrays.asList(folders); +// } +// } + + + static public ArrayList loadAll(File toolsFolder) { + File[] list = ContributionType.TOOL.listCandidates(toolsFolder); + ArrayList outgoing = new ArrayList(); + // If toolsFolder does not exist or is inaccessible (stranger things have + // happened, and are reported as bugs) list will come back null. + if (list != null) { + for (File folder : list) { + try { + ToolContribution tc = load(folder); + if (tc != null) { + outgoing.add(tc); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + return outgoing; + } + + +// Editor editor; // used to send error messages + + public void init(Editor editor) { +// try { +// this.editor = editor; + tool.init(editor); +// } catch (NoSuchMethodError nsme) { +// editor.statusError(tool.getMenuTitle() + " is not compatible with this version of Processing"); +// nsme.printStackTrace(); +// } + } + + + public void run() { +// try { + tool.run(); +// } catch (NoSuchMethodError nsme) { +// editor.statusError(tool.getMenuTitle() + " is not compatible with this version of Processing"); +// nsme.printStackTrace(); +// } + } + + + public String getMenuTitle() { + return tool.getMenuTitle(); + } + + + public ContributionType getType() { + return ContributionType.TOOL; + } + + + /** + * Returns the object stored in the referenceFile field, which contains an + * instance of the file object representing the index file of the reference + * + * @return referenceFile + */ + public File getReferenceIndexFile() { + return referenceFile; + } + + + /** + * Tests whether the reference's index file indicated by referenceFile exists. + * + * @return true if and only if the file denoted by referenceFile exists; false + * otherwise. + */ + public boolean hasReference() { + return referenceFile.exists(); + } } diff --git a/app/src/processing/mode/java/preproc/pde.g b/app/src/processing/mode/java/preproc/pde.g index 4355c2b79..6b2b58fd5 100644 --- a/app/src/processing/mode/java/preproc/pde.g +++ b/app/src/processing/mode/java/preproc/pde.g @@ -1,394 +1,394 @@ -/* -*- mode: antlr; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -header { -package processing.mode.java.preproc; -} - -class PdeRecognizer extends JavaRecognizer; - -options { - importVocab = Java; - exportVocab = PdePartial; - - //codeGenMakeSwitchThreshold=10; // this is set high for debugging - //codeGenBitsetTestThreshold=10; // this is set high for debugging - - // developers may to want to set this to true for better - // debugging messages, however, doing so disables highlighting errors - // in the editor. - defaultErrorHandler = false; //true; -} - -tokens { - CONSTRUCTOR_CAST; EMPTY_FIELD; -} - -{ - // this clause copied from java15.g! ANTLR does not copy this - // section from the super grammar. - /** - * Counts the number of LT seen in the typeArguments production. - * It is used in semantic predicates to ensure we have seen - * enough closing '>' characters; which actually may have been - * either GT, SR or BSR tokens. - */ - private int ltCounter = 0; - - private PdePreprocessor pp; - public PdeRecognizer(final PdePreprocessor pp, final TokenStream ts) { - this(ts); - this.pp = pp; - } - - private void mixed() throws RecognitionException, TokenStreamException { - throw new RecognitionException("It looks like you're mixing \"active\" and \"static\" modes.", - getFilename(), LT(1).getLine(), LT(1).getColumn()); - } -} - -pdeProgram - : - // Some programs can be equally well interpreted as STATIC or ACTIVE; - // this forces the parser to prefer the STATIC interpretation. - (staticProgram) => staticProgram - { pp.setMode(PdePreprocessor.Mode.STATIC); } - - | (activeProgram) => activeProgram - { pp.setMode(PdePreprocessor.Mode.ACTIVE); } - - | staticProgram - { pp.setMode(PdePreprocessor.Mode.STATIC); } - ; - -// advanced mode is really just a normal java file -javaProgram - : compilationUnit - ; - -activeProgram - : ( - (IDENT LPAREN) => IDENT LPAREN { mixed(); } - | possiblyEmptyField - )+ EOF! - ; - -staticProgram - : ( - statement - )* EOF! - ; - -// copy of the java.g rule with WEBCOLOR_LITERAL added -constant - : NUM_INT - | CHAR_LITERAL - | STRING_LITERAL - | NUM_FLOAT - | NUM_LONG - | NUM_DOUBLE - | webcolor_literal - ; - -// fix bug http://dev.processing.org/bugs/show_bug.cgi?id=1519 -// by altering a syntactic predicate whose sole purpose is to -// emit a useless error with no line numbers. -// These are from Java15.g, with a few lines edited to make nice errors. - -// Type arguments to a class or interface type -typeArguments -{int currentLtLevel = 0;} - : - {currentLtLevel = ltCounter;} - LT! {ltCounter++;} - typeArgument - (options{greedy=true;}: // match as many as possible - {if (! (inputState.guessing !=0 || ltCounter == currentLtLevel + 1)) { - throw new RecognitionException("Maybe too many > characters?", - getFilename(), LT(1).getLine(), LT(1).getColumn()); - }} - COMMA! typeArgument - )* - - ( // turn warning off since Antlr generates the right code, - // plus we have our semantic predicate below - options{generateAmbigWarnings=false;}: - typeArgumentsOrParametersEnd - )? - - // make sure we have gobbled up enough '>' characters - // if we are at the "top level" of nested typeArgument productions - {if (! ((currentLtLevel != 0) || ltCounter == currentLtLevel)) { - throw new RecognitionException("Maybe too many > characters?", - getFilename(), LT(1).getLine(), LT(1).getColumn()); - }} - - {#typeArguments = #(#[TYPE_ARGUMENTS, "TYPE_ARGUMENTS"], #typeArguments);} - ; - -typeParameters -{int currentLtLevel = 0;} - : - {currentLtLevel = ltCounter;} - LT! {ltCounter++;} - typeParameter (COMMA! typeParameter)* - (typeArgumentsOrParametersEnd)? - - // make sure we have gobbled up enough '>' characters - // if we are at the "top level" of nested typeArgument productions - {if (! ((currentLtLevel != 0) || ltCounter == currentLtLevel)) { - throw new RecognitionException("Maybe too many > characters?", - getFilename(), LT(1).getLine(), LT(1).getColumn()); - }} - - {#typeParameters = #(#[TYPE_PARAMETERS, "TYPE_PARAMETERS"], #typeParameters);} - ; - - -// this gobbles up *some* amount of '>' characters, and counts how many -// it gobbled. -protected typeArgumentsOrParametersEnd - : GT! {ltCounter-=1;} - | SR! {ltCounter-=2;} - | BSR! {ltCounter-=3;} - ; - -// of the form #cc008f in PDE -webcolor_literal - : w:WEBCOLOR_LITERAL - { if (! (processing.app.Preferences.getBoolean("preproc.web_colors") - && - w.getText().length() == 6)) { - throw new RecognitionException("Web colors must be exactly 6 hex digits. This looks like " + w.getText().length() + ".", - getFilename(), LT(1).getLine(), LT(1).getColumn()); - }} // must be exactly 6 hex digits - ; - -// copy of the java.g builtInType rule -builtInConsCastType - : "void" - | "boolean" - | "byte" - | "char" - | "short" - | "int" - | "float" - | "long" - | "double" - ; - -// our types include the java types and "color". this is separated into two -// rules so that constructor casts can just use the original typelist, since -// we don't want to support the color type as a constructor cast. -// -builtInType - : builtInConsCastType - | "color" // aliased to an int in PDE - { processing.app.Preferences.getBoolean("preproc.color_datatype") }? - ; - -// constructor style casts. -constructorCast! - : t:consCastTypeSpec[true] - LPAREN! - e:expression - RPAREN! - // if this is a string literal, make sure the type we're trying to cast - // to is one of the supported ones - // - { (#e == null) || - ( (#e.getType() != STRING_LITERAL) || - ( #t.getType() == LITERAL_boolean || - #t.getType() == LITERAL_double || - #t.getType() == LITERAL_float || - #t.getType() == LITERAL_int || - #t.getType() == LITERAL_long || - #t.getType() == LITERAL_short )) }? - // create the node - // - {#constructorCast = #(#[CONSTRUCTOR_CAST,"CONSTRUCTOR_CAST"], t, e);} - ; - -// A list of types that be used as the destination type in a constructor-style -// cast. Ideally, this would include all class types, not just "String". -// Unfortunately, it's not possible to tell whether Foo(5) is supposed to be -// a method call or a constructor cast without have a table of all valid -// types or methods, which requires semantic analysis (eg processing of import -// statements). So we accept the set of built-in types plus "String". -// -consCastTypeSpec[boolean addImagNode] -// : stringTypeSpec[addImagNode] -// | builtInConsCastTypeSpec[addImagNode] - : builtInConsCastTypeSpec[addImagNode] -// trying to remove String() cast [fry] - ; - -//stringTypeSpec[boolean addImagNode] -// : id:IDENT { #id.getText().equals("String") }? -// { -// if ( addImagNode ) { -// #stringTypeSpec = #(#[TYPE,"TYPE"], -// #stringTypeSpec); -// } -// } -// ; - -builtInConsCastTypeSpec[boolean addImagNode] - : builtInConsCastType - { - if ( addImagNode ) { - #builtInConsCastTypeSpec = #(#[TYPE,"TYPE"], - #builtInConsCastTypeSpec); - } - } - ; - -// Since "color" tokens are lexed as LITERAL_color now, we need to have a rule -// that can generate a method call from an expression that starts with this -// token -// -colorMethodCall - : c:"color" {#c.setType(IDENT);} // this would default to LITERAL_color - lp:LPAREN^ {#lp.setType(METHOD_CALL);} - argList - RPAREN! - ; - -// copy of the java.g rule with added constructorCast and colorMethodCall -// alternatives -primaryExpression - : (consCastTypeSpec[false] LPAREN) => constructorCast - { processing.app.Preferences.getBoolean("preproc.enhanced_casting") }? - | identPrimary ( options {greedy=true;} : DOT^ "class" )? - | constant - | "true" - | "false" - | "null" - | newExpression - | "this" - | "super" - | LPAREN! assignmentExpression RPAREN! - | colorMethodCall - // look for int.class and int[].class - | builtInType - ( lbt:LBRACK^ {#lbt.setType(ARRAY_DECLARATOR);} RBRACK! )* - DOT^ "class" - ; - -// the below variable rule hacks are needed so that it's possible for the -// emitter to correctly output variable declarations of the form "float a, b" -// from the AST. This means that our AST has a somewhat different form in -// these rules than the java one does, and this new form may have its own -// semantic issues. But it seems to fix the comma declaration issues. -// -variableDefinitions![AST mods, AST t] - : vd:variableDeclarator[getASTFactory().dupTree(mods), - getASTFactory().dupTree(t)] - {#variableDefinitions = #(#[VARIABLE_DEF,"VARIABLE_DEF"], mods, - t, vd);} - ; -variableDeclarator[AST mods, AST t] - : ( id:IDENT (lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!)* - v:varInitializer (COMMA!)? )+ - ; - -// java.g builds syntax trees with an inconsistent structure. override one of -// the rules there to fix this. -// -explicitConstructorInvocation! - : (typeArguments)? - t:"this" LPAREN a1:argList RPAREN SEMI - {#explicitConstructorInvocation = #(#[CTOR_CALL, "CTOR_CALL"], - #t, #a1);} - | s:"super" LPAREN a2:argList RPAREN SEMI - {#explicitConstructorInvocation = #(#[SUPER_CTOR_CALL, - "SUPER_CTOR_CALL"], - #s, #a2);} - ; - -// quick-n-dirty hack to the get the advanced class name. we should -// really be getting it from the AST and not forking this rule from -// the java.g copy at all. Since this is a recursive descent parser, we get -// the last class name in the file so that we don't end up with the classname -// of an inner class. If there is more than one "outer" class in a file, -// this heuristic will fail. -// -classDefinition![AST modifiers] - : "class" i:IDENT - // it _might_ have type paramaters - (tp:typeParameters)? - // it _might_ have a superclass... - sc:superClassClause - // it might implement some interfaces... - ic:implementsClause - // now parse the body of the class - cb:classBlock - {#classDefinition = #(#[CLASS_DEF,"CLASS_DEF"], - modifiers,i,tp,sc,ic,cb); - pp.setAdvClassName(i.getText());} - ; - -possiblyEmptyField - : classField - | s:SEMI {#s.setType(EMPTY_FIELD);} - ; - -class PdeLexer extends JavaLexer; - -options { - importVocab=PdePartial; - exportVocab=Pde; -} - -// We need to preserve whitespace and commentary instead of ignoring -// like the supergrammar does. Otherwise Jikes won't be able to give -// us error messages that point to the equivalent PDE code. - -// WS, SL_COMMENT, ML_COMMENT are copies of the original productions, -// but with the SKIP assigment removed. - -WS : ( ' ' - | '\t' - | '\f' - // handle newlines - | ( options {generateAmbigWarnings=false;} - : "\r\n" // Evil DOS - | '\r' // Macintosh - | '\n' // Unix (the right way) - ) - { newline(); } - )+ - ; - -// Single-line comments -SL_COMMENT - : "//" - (~('\n'|'\r'))* ('\n'|'\r'('\n')?) - {newline();} - ; - -// multiple-line comments -ML_COMMENT - : "/*" - ( /* '\r' '\n' can be matched in one alternative or by matching - '\r' in one iteration and '\n' in another. I am trying to - handle any flavor of newline that comes in, but the language - that allows both "\r\n" and "\r" and "\n" to all be valid - newline is ambiguous. Consequently, the resulting grammar - must be ambiguous. I'm shutting this warning off. - */ - options { - generateAmbigWarnings=false; - } - : - { LA(2)!='/' }? '*' - | '\r' '\n' {newline();} - | '\r' {newline();} - | '\n' {newline();} - | ~('*'|'\n'|'\r') - )* - "*/" - ; - -WEBCOLOR_LITERAL - : '#'! (HEX_DIGIT)+ - ; - +/* -*- mode: antlr; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +header { +package processing.mode.java.preproc; +} + +class PdeRecognizer extends JavaRecognizer; + +options { + importVocab = Java; + exportVocab = PdePartial; + + //codeGenMakeSwitchThreshold=10; // this is set high for debugging + //codeGenBitsetTestThreshold=10; // this is set high for debugging + + // developers may to want to set this to true for better + // debugging messages, however, doing so disables highlighting errors + // in the editor. + defaultErrorHandler = false; //true; +} + +tokens { + CONSTRUCTOR_CAST; EMPTY_FIELD; +} + +{ + // this clause copied from java15.g! ANTLR does not copy this + // section from the super grammar. + /** + * Counts the number of LT seen in the typeArguments production. + * It is used in semantic predicates to ensure we have seen + * enough closing '>' characters; which actually may have been + * either GT, SR or BSR tokens. + */ + private int ltCounter = 0; + + private PdePreprocessor pp; + public PdeRecognizer(final PdePreprocessor pp, final TokenStream ts) { + this(ts); + this.pp = pp; + } + + private void mixed() throws RecognitionException, TokenStreamException { + throw new RecognitionException("It looks like you're mixing \"active\" and \"static\" modes.", + getFilename(), LT(1).getLine(), LT(1).getColumn()); + } +} + +pdeProgram + : + // Some programs can be equally well interpreted as STATIC or ACTIVE; + // this forces the parser to prefer the STATIC interpretation. + (staticProgram) => staticProgram + { pp.setMode(PdePreprocessor.Mode.STATIC); } + + | (activeProgram) => activeProgram + { pp.setMode(PdePreprocessor.Mode.ACTIVE); } + + | staticProgram + { pp.setMode(PdePreprocessor.Mode.STATIC); } + ; + +// advanced mode is really just a normal java file +javaProgram + : compilationUnit + ; + +activeProgram + : ( + (IDENT LPAREN) => IDENT LPAREN { mixed(); } + | possiblyEmptyField + )+ EOF! + ; + +staticProgram + : ( + statement + )* EOF! + ; + +// copy of the java.g rule with WEBCOLOR_LITERAL added +constant + : NUM_INT + | CHAR_LITERAL + | STRING_LITERAL + | NUM_FLOAT + | NUM_LONG + | NUM_DOUBLE + | webcolor_literal + ; + +// fix bug http://dev.processing.org/bugs/show_bug.cgi?id=1519 +// by altering a syntactic predicate whose sole purpose is to +// emit a useless error with no line numbers. +// These are from Java15.g, with a few lines edited to make nice errors. + +// Type arguments to a class or interface type +typeArguments +{int currentLtLevel = 0;} + : + {currentLtLevel = ltCounter;} + LT! {ltCounter++;} + typeArgument + (options{greedy=true;}: // match as many as possible + {if (! (inputState.guessing !=0 || ltCounter == currentLtLevel + 1)) { + throw new RecognitionException("Maybe too many > characters?", + getFilename(), LT(1).getLine(), LT(1).getColumn()); + }} + COMMA! typeArgument + )* + + ( // turn warning off since Antlr generates the right code, + // plus we have our semantic predicate below + options{generateAmbigWarnings=false;}: + typeArgumentsOrParametersEnd + )? + + // make sure we have gobbled up enough '>' characters + // if we are at the "top level" of nested typeArgument productions + {if (! ((currentLtLevel != 0) || ltCounter == currentLtLevel)) { + throw new RecognitionException("Maybe too many > characters?", + getFilename(), LT(1).getLine(), LT(1).getColumn()); + }} + + {#typeArguments = #(#[TYPE_ARGUMENTS, "TYPE_ARGUMENTS"], #typeArguments);} + ; + +typeParameters +{int currentLtLevel = 0;} + : + {currentLtLevel = ltCounter;} + LT! {ltCounter++;} + typeParameter (COMMA! typeParameter)* + (typeArgumentsOrParametersEnd)? + + // make sure we have gobbled up enough '>' characters + // if we are at the "top level" of nested typeArgument productions + {if (! ((currentLtLevel != 0) || ltCounter == currentLtLevel)) { + throw new RecognitionException("Maybe too many > characters?", + getFilename(), LT(1).getLine(), LT(1).getColumn()); + }} + + {#typeParameters = #(#[TYPE_PARAMETERS, "TYPE_PARAMETERS"], #typeParameters);} + ; + + +// this gobbles up *some* amount of '>' characters, and counts how many +// it gobbled. +protected typeArgumentsOrParametersEnd + : GT! {ltCounter-=1;} + | SR! {ltCounter-=2;} + | BSR! {ltCounter-=3;} + ; + +// of the form #cc008f in PDE +webcolor_literal + : w:WEBCOLOR_LITERAL + { if (! (processing.app.Preferences.getBoolean("preproc.web_colors") + && + w.getText().length() == 6)) { + throw new RecognitionException("Web colors must be exactly 6 hex digits. This looks like " + w.getText().length() + ".", + getFilename(), LT(1).getLine(), LT(1).getColumn()); + }} // must be exactly 6 hex digits + ; + +// copy of the java.g builtInType rule +builtInConsCastType + : "void" + | "boolean" + | "byte" + | "char" + | "short" + | "int" + | "float" + | "long" + | "double" + ; + +// our types include the java types and "color". this is separated into two +// rules so that constructor casts can just use the original typelist, since +// we don't want to support the color type as a constructor cast. +// +builtInType + : builtInConsCastType + | "color" // aliased to an int in PDE + { processing.app.Preferences.getBoolean("preproc.color_datatype") }? + ; + +// constructor style casts. +constructorCast! + : t:consCastTypeSpec[true] + LPAREN! + e:expression + RPAREN! + // if this is a string literal, make sure the type we're trying to cast + // to is one of the supported ones + // + { (#e == null) || + ( (#e.getType() != STRING_LITERAL) || + ( #t.getType() == LITERAL_boolean || + #t.getType() == LITERAL_double || + #t.getType() == LITERAL_float || + #t.getType() == LITERAL_int || + #t.getType() == LITERAL_long || + #t.getType() == LITERAL_short )) }? + // create the node + // + {#constructorCast = #(#[CONSTRUCTOR_CAST,"CONSTRUCTOR_CAST"], t, e);} + ; + +// A list of types that be used as the destination type in a constructor-style +// cast. Ideally, this would include all class types, not just "String". +// Unfortunately, it's not possible to tell whether Foo(5) is supposed to be +// a method call or a constructor cast without have a table of all valid +// types or methods, which requires semantic analysis (eg processing of import +// statements). So we accept the set of built-in types plus "String". +// +consCastTypeSpec[boolean addImagNode] +// : stringTypeSpec[addImagNode] +// | builtInConsCastTypeSpec[addImagNode] + : builtInConsCastTypeSpec[addImagNode] +// trying to remove String() cast [fry] + ; + +//stringTypeSpec[boolean addImagNode] +// : id:IDENT { #id.getText().equals("String") }? +// { +// if ( addImagNode ) { +// #stringTypeSpec = #(#[TYPE,"TYPE"], +// #stringTypeSpec); +// } +// } +// ; + +builtInConsCastTypeSpec[boolean addImagNode] + : builtInConsCastType + { + if ( addImagNode ) { + #builtInConsCastTypeSpec = #(#[TYPE,"TYPE"], + #builtInConsCastTypeSpec); + } + } + ; + +// Since "color" tokens are lexed as LITERAL_color now, we need to have a rule +// that can generate a method call from an expression that starts with this +// token +// +colorMethodCall + : c:"color" {#c.setType(IDENT);} // this would default to LITERAL_color + lp:LPAREN^ {#lp.setType(METHOD_CALL);} + argList + RPAREN! + ; + +// copy of the java.g rule with added constructorCast and colorMethodCall +// alternatives +primaryExpression + : (consCastTypeSpec[false] LPAREN) => constructorCast + { processing.app.Preferences.getBoolean("preproc.enhanced_casting") }? + | identPrimary ( options {greedy=true;} : DOT^ "class" )? + | constant + | "true" + | "false" + | "null" + | newExpression + | "this" + | "super" + | LPAREN! assignmentExpression RPAREN! + | colorMethodCall + // look for int.class and int[].class + | builtInType + ( lbt:LBRACK^ {#lbt.setType(ARRAY_DECLARATOR);} RBRACK! )* + DOT^ "class" + ; + +// the below variable rule hacks are needed so that it's possible for the +// emitter to correctly output variable declarations of the form "float a, b" +// from the AST. This means that our AST has a somewhat different form in +// these rules than the java one does, and this new form may have its own +// semantic issues. But it seems to fix the comma declaration issues. +// +variableDefinitions![AST mods, AST t] + : vd:variableDeclarator[getASTFactory().dupTree(mods), + getASTFactory().dupTree(t)] + {#variableDefinitions = #(#[VARIABLE_DEF,"VARIABLE_DEF"], mods, + t, vd);} + ; +variableDeclarator[AST mods, AST t] + : ( id:IDENT (lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!)* + v:varInitializer (COMMA!)? )+ + ; + +// java.g builds syntax trees with an inconsistent structure. override one of +// the rules there to fix this. +// +explicitConstructorInvocation! + : (typeArguments)? + t:"this" LPAREN a1:argList RPAREN SEMI + {#explicitConstructorInvocation = #(#[CTOR_CALL, "CTOR_CALL"], + #t, #a1);} + | s:"super" LPAREN a2:argList RPAREN SEMI + {#explicitConstructorInvocation = #(#[SUPER_CTOR_CALL, + "SUPER_CTOR_CALL"], + #s, #a2);} + ; + +// quick-n-dirty hack to the get the advanced class name. we should +// really be getting it from the AST and not forking this rule from +// the java.g copy at all. Since this is a recursive descent parser, we get +// the last class name in the file so that we don't end up with the classname +// of an inner class. If there is more than one "outer" class in a file, +// this heuristic will fail. +// +classDefinition![AST modifiers] + : "class" i:IDENT + // it _might_ have type paramaters + (tp:typeParameters)? + // it _might_ have a superclass... + sc:superClassClause + // it might implement some interfaces... + ic:implementsClause + // now parse the body of the class + cb:classBlock + {#classDefinition = #(#[CLASS_DEF,"CLASS_DEF"], + modifiers,i,tp,sc,ic,cb); + pp.setAdvClassName(i.getText());} + ; + +possiblyEmptyField + : classField + | s:SEMI {#s.setType(EMPTY_FIELD);} + ; + +class PdeLexer extends JavaLexer; + +options { + importVocab=PdePartial; + exportVocab=Pde; +} + +// We need to preserve whitespace and commentary instead of ignoring +// like the supergrammar does. Otherwise Jikes won't be able to give +// us error messages that point to the equivalent PDE code. + +// WS, SL_COMMENT, ML_COMMENT are copies of the original productions, +// but with the SKIP assigment removed. + +WS : ( ' ' + | '\t' + | '\f' + // handle newlines + | ( options {generateAmbigWarnings=false;} + : "\r\n" // Evil DOS + | '\r' // Macintosh + | '\n' // Unix (the right way) + ) + { newline(); } + )+ + ; + +// Single-line comments +SL_COMMENT + : "//" + (~('\n'|'\r'))* ('\n'|'\r'('\n')?) + {newline();} + ; + +// multiple-line comments +ML_COMMENT + : "/*" + ( /* '\r' '\n' can be matched in one alternative or by matching + '\r' in one iteration and '\n' in another. I am trying to + handle any flavor of newline that comes in, but the language + that allows both "\r\n" and "\r" and "\n" to all be valid + newline is ambiguous. Consequently, the resulting grammar + must be ambiguous. I'm shutting this warning off. + */ + options { + generateAmbigWarnings=false; + } + : + { LA(2)!='/' }? '*' + | '\r' '\n' {newline();} + | '\r' {newline();} + | '\n' {newline();} + | ~('*'|'\n'|'\r') + )* + "*/" + ; + +WEBCOLOR_LITERAL + : '#'! (HEX_DIGIT)+ + ; + diff --git a/app/test/resources/bug1064.expected b/app/test/resources/bug1064.expected index 2fd1f3ef0..d77173b44 100644 --- a/app/test/resources/bug1064.expected +++ b/app/test/resources/bug1064.expected @@ -1,29 +1,29 @@ -import processing.core.*; -import processing.data.*; -import processing.event.*; -import processing.opengl.*; - -import java.util.HashMap; -import java.util.ArrayList; -import java.io.File; -import java.io.BufferedReader; -import java.io.PrintWriter; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.IOException; - -public class bug1064 extends PApplet { - public void setup() { -// import "; - noLoop(); - } - - static public void main(String[] passedArgs) { - String[] appletArgs = new String[] { "bug1064" }; - if (passedArgs != null) { - PApplet.main(concat(appletArgs, passedArgs)); - } else { - PApplet.main(appletArgs); - } - } -} +import processing.core.*; +import processing.data.*; +import processing.event.*; +import processing.opengl.*; + +import java.util.HashMap; +import java.util.ArrayList; +import java.io.File; +import java.io.BufferedReader; +import java.io.PrintWriter; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; + +public class bug1064 extends PApplet { + public void setup() { +// import "; + noLoop(); + } + + static public void main(String[] passedArgs) { + String[] appletArgs = new String[] { "bug1064" }; + if (passedArgs != null) { + PApplet.main(concat(appletArgs, passedArgs)); + } else { + PApplet.main(appletArgs); + } + } +} diff --git a/app/test/resources/bug136.expected b/app/test/resources/bug136.expected index 3ed7a5fc5..9909098a3 100644 --- a/app/test/resources/bug136.expected +++ b/app/test/resources/bug136.expected @@ -1,41 +1,41 @@ -import processing.core.*; -import processing.data.*; -import processing.event.*; -import processing.opengl.*; - -import java.util.Collections; - -import java.util.HashMap; -import java.util.ArrayList; -import java.io.File; -import java.io.BufferedReader; -import java.io.PrintWriter; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.IOException; - -public class bug136 extends PApplet { - - -java.util.List alist = Collections.synchronizedList(new ArrayList()); - -public void setup() { -size(400, 200); -alist.add("hello"); -} - -public void draw() { -rect(width/4, height/4, width/2, height/2); -synchronized(alist) { -alist.get(0); -} -} - static public void main(String[] passedArgs) { - String[] appletArgs = new String[] { "bug136" }; - if (passedArgs != null) { - PApplet.main(concat(appletArgs, passedArgs)); - } else { - PApplet.main(appletArgs); - } - } -} +import processing.core.*; +import processing.data.*; +import processing.event.*; +import processing.opengl.*; + +import java.util.Collections; + +import java.util.HashMap; +import java.util.ArrayList; +import java.io.File; +import java.io.BufferedReader; +import java.io.PrintWriter; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; + +public class bug136 extends PApplet { + + +java.util.List alist = Collections.synchronizedList(new ArrayList()); + +public void setup() { +size(400, 200); +alist.add("hello"); +} + +public void draw() { +rect(width/4, height/4, width/2, height/2); +synchronized(alist) { +alist.get(0); +} +} + static public void main(String[] passedArgs) { + String[] appletArgs = new String[] { "bug136" }; + if (passedArgs != null) { + PApplet.main(concat(appletArgs, passedArgs)); + } else { + PApplet.main(appletArgs); + } + } +} diff --git a/app/test/resources/bug1362.expected b/app/test/resources/bug1362.expected index 479feefb6..00c81e622 100644 --- a/app/test/resources/bug1362.expected +++ b/app/test/resources/bug1362.expected @@ -1,29 +1,29 @@ -import processing.core.*; -import processing.data.*; -import processing.event.*; -import processing.opengl.*; - -import java.util.HashMap; -import java.util.ArrayList; -import java.io.File; -import java.io.BufferedReader; -import java.io.PrintWriter; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.IOException; - -public class bug1362 extends PApplet { - public void setup() { -if (true) {} else { new String(); } - noLoop(); - } - - static public void main(String[] passedArgs) { - String[] appletArgs = new String[] { "bug1362" }; - if (passedArgs != null) { - PApplet.main(concat(appletArgs, passedArgs)); - } else { - PApplet.main(appletArgs); - } - } -} +import processing.core.*; +import processing.data.*; +import processing.event.*; +import processing.opengl.*; + +import java.util.HashMap; +import java.util.ArrayList; +import java.io.File; +import java.io.BufferedReader; +import java.io.PrintWriter; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; + +public class bug1362 extends PApplet { + public void setup() { +if (true) {} else { new String(); } + noLoop(); + } + + static public void main(String[] passedArgs) { + String[] appletArgs = new String[] { "bug1362" }; + if (passedArgs != null) { + PApplet.main(concat(appletArgs, passedArgs)); + } else { + PApplet.main(appletArgs); + } + } +} diff --git a/app/test/resources/bug1442.expected b/app/test/resources/bug1442.expected index 1a22ef53a..d48380587 100644 --- a/app/test/resources/bug1442.expected +++ b/app/test/resources/bug1442.expected @@ -1,28 +1,28 @@ -import processing.core.*; -import processing.data.*; -import processing.event.*; -import processing.opengl.*; - -import java.util.HashMap; -import java.util.ArrayList; -import java.io.File; -import java.io.BufferedReader; -import java.io.PrintWriter; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.IOException; - -public class bug1442 extends PApplet { - -public float a() { - return 1.0f; -} - static public void main(String[] passedArgs) { - String[] appletArgs = new String[] { "bug1442" }; - if (passedArgs != null) { - PApplet.main(concat(appletArgs, passedArgs)); - } else { - PApplet.main(appletArgs); - } - } -} +import processing.core.*; +import processing.data.*; +import processing.event.*; +import processing.opengl.*; + +import java.util.HashMap; +import java.util.ArrayList; +import java.io.File; +import java.io.BufferedReader; +import java.io.PrintWriter; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; + +public class bug1442 extends PApplet { + +public float a() { + return 1.0f; +} + static public void main(String[] passedArgs) { + String[] appletArgs = new String[] { "bug1442" }; + if (passedArgs != null) { + PApplet.main(concat(appletArgs, passedArgs)); + } else { + PApplet.main(appletArgs); + } + } +} diff --git a/app/test/resources/bug1511.expected b/app/test/resources/bug1511.expected index 10a0d155a..ca423630f 100644 --- a/app/test/resources/bug1511.expected +++ b/app/test/resources/bug1511.expected @@ -1,37 +1,37 @@ -import processing.core.*; -import processing.data.*; -import processing.event.*; -import processing.opengl.*; - -import java.io.StringWriter; - -import java.util.HashMap; -import java.util.ArrayList; -import java.io.File; -import java.io.BufferedReader; -import java.io.PrintWriter; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.IOException; - -public class bug1511 extends PApplet { - public void setup() { -// \u00df - -/** -* a -*/ - - - noLoop(); - } - - static public void main(String[] passedArgs) { - String[] appletArgs = new String[] { "bug1511" }; - if (passedArgs != null) { - PApplet.main(concat(appletArgs, passedArgs)); - } else { - PApplet.main(appletArgs); - } - } -} +import processing.core.*; +import processing.data.*; +import processing.event.*; +import processing.opengl.*; + +import java.io.StringWriter; + +import java.util.HashMap; +import java.util.ArrayList; +import java.io.File; +import java.io.BufferedReader; +import java.io.PrintWriter; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; + +public class bug1511 extends PApplet { + public void setup() { +// \u00df + +/** +* a +*/ + + + noLoop(); + } + + static public void main(String[] passedArgs) { + String[] appletArgs = new String[] { "bug1511" }; + if (passedArgs != null) { + PApplet.main(concat(appletArgs, passedArgs)); + } else { + PApplet.main(appletArgs); + } + } +} diff --git a/app/test/resources/bug1512.expected b/app/test/resources/bug1512.expected index 511615729..bb2bd9aa0 100644 --- a/app/test/resources/bug1512.expected +++ b/app/test/resources/bug1512.expected @@ -1,29 +1,29 @@ -import processing.core.*; -import processing.data.*; -import processing.event.*; -import processing.opengl.*; - -import java.util.HashMap; -import java.util.ArrayList; -import java.io.File; -import java.io.BufferedReader; -import java.io.PrintWriter; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.IOException; - -public class bug1512 extends PApplet { - public void setup() { -println("oi/*"); - noLoop(); - } - - static public void main(String[] passedArgs) { - String[] appletArgs = new String[] { "bug1512" }; - if (passedArgs != null) { - PApplet.main(concat(appletArgs, passedArgs)); - } else { - PApplet.main(appletArgs); - } - } -} +import processing.core.*; +import processing.data.*; +import processing.event.*; +import processing.opengl.*; + +import java.util.HashMap; +import java.util.ArrayList; +import java.io.File; +import java.io.BufferedReader; +import java.io.PrintWriter; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; + +public class bug1512 extends PApplet { + public void setup() { +println("oi/*"); + noLoop(); + } + + static public void main(String[] passedArgs) { + String[] appletArgs = new String[] { "bug1512" }; + if (passedArgs != null) { + PApplet.main(concat(appletArgs, passedArgs)); + } else { + PApplet.main(appletArgs); + } + } +} diff --git a/app/test/resources/bug1514a.expected b/app/test/resources/bug1514a.expected index 7596c2745..f53288ca6 100644 --- a/app/test/resources/bug1514a.expected +++ b/app/test/resources/bug1514a.expected @@ -1,35 +1,35 @@ -import processing.core.*; -import processing.data.*; -import processing.event.*; -import processing.opengl.*; - -import java.io.StringWriter; - -import java.util.HashMap; -import java.util.ArrayList; -import java.io.File; -import java.io.BufferedReader; -import java.io.PrintWriter; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.IOException; - -public class bug1514a extends PApplet { - public void setup() { -//----- \u00e8\u00e9\u00e9\u00e8\u00e8\u00e9\u00e9\u00e9\u00e0\u00e9\u00e9\u00e8\u00e9''\u00e9\u00e9\u00e9 -//---------------------------------------------------------------- -//--- IMPORTS -//---------------------------------------------------------------- - - noLoop(); - } - - static public void main(String[] passedArgs) { - String[] appletArgs = new String[] { "bug1514a" }; - if (passedArgs != null) { - PApplet.main(concat(appletArgs, passedArgs)); - } else { - PApplet.main(appletArgs); - } - } -} +import processing.core.*; +import processing.data.*; +import processing.event.*; +import processing.opengl.*; + +import java.io.StringWriter; + +import java.util.HashMap; +import java.util.ArrayList; +import java.io.File; +import java.io.BufferedReader; +import java.io.PrintWriter; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; + +public class bug1514a extends PApplet { + public void setup() { +//----- \u00e8\u00e9\u00e9\u00e8\u00e8\u00e9\u00e9\u00e9\u00e0\u00e9\u00e9\u00e8\u00e9''\u00e9\u00e9\u00e9 +//---------------------------------------------------------------- +//--- IMPORTS +//---------------------------------------------------------------- + + noLoop(); + } + + static public void main(String[] passedArgs) { + String[] appletArgs = new String[] { "bug1514a" }; + if (passedArgs != null) { + PApplet.main(concat(appletArgs, passedArgs)); + } else { + PApplet.main(appletArgs); + } + } +} diff --git a/app/test/resources/bug1514b.expected b/app/test/resources/bug1514b.expected index b7628ef32..49b6a19fd 100644 --- a/app/test/resources/bug1514b.expected +++ b/app/test/resources/bug1514b.expected @@ -1,35 +1,35 @@ -import processing.core.*; -import processing.data.*; -import processing.event.*; -import processing.opengl.*; - -import java.io.StringWriter; - -import java.util.HashMap; -import java.util.ArrayList; -import java.io.File; -import java.io.BufferedReader; -import java.io.PrintWriter; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.IOException; - -public class bug1514b extends PApplet { - public void setup() { -//----- \u00e8\u00e9\u00e9\u00e8\u00e8\u00e9\u00e9\u00e9\u00e0\u00e9\u00e9\u00e8\u00e9''\u00e9\u00e9 -//---------------------------------------------------------------- -//--- IMPORTS -//---------------------------------------------------------------- - - noLoop(); - } - - static public void main(String[] passedArgs) { - String[] appletArgs = new String[] { "bug1514b" }; - if (passedArgs != null) { - PApplet.main(concat(appletArgs, passedArgs)); - } else { - PApplet.main(appletArgs); - } - } -} +import processing.core.*; +import processing.data.*; +import processing.event.*; +import processing.opengl.*; + +import java.io.StringWriter; + +import java.util.HashMap; +import java.util.ArrayList; +import java.io.File; +import java.io.BufferedReader; +import java.io.PrintWriter; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; + +public class bug1514b extends PApplet { + public void setup() { +//----- \u00e8\u00e9\u00e9\u00e8\u00e8\u00e9\u00e9\u00e9\u00e0\u00e9\u00e9\u00e8\u00e9''\u00e9\u00e9 +//---------------------------------------------------------------- +//--- IMPORTS +//---------------------------------------------------------------- + + noLoop(); + } + + static public void main(String[] passedArgs) { + String[] appletArgs = new String[] { "bug1514b" }; + if (passedArgs != null) { + PApplet.main(concat(appletArgs, passedArgs)); + } else { + PApplet.main(appletArgs); + } + } +} diff --git a/app/test/resources/bug1515.expected b/app/test/resources/bug1515.expected index f2d0ae2c4..d883739e3 100644 --- a/app/test/resources/bug1515.expected +++ b/app/test/resources/bug1515.expected @@ -1,32 +1,32 @@ -import processing.core.*; -import processing.data.*; -import processing.event.*; -import processing.opengl.*; - -import java.util.HashMap; -import java.util.ArrayList; -import java.io.File; -import java.io.BufferedReader; -import java.io.PrintWriter; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.IOException; - -public class bug1515 extends PApplet { - -// a class definition that does something with things that extend PApplet -class Heythere{ -} - -// method definition which can do things with papplet -public void doSomething( T thing ){ -} - static public void main(String[] passedArgs) { - String[] appletArgs = new String[] { "bug1515" }; - if (passedArgs != null) { - PApplet.main(concat(appletArgs, passedArgs)); - } else { - PApplet.main(appletArgs); - } - } -} +import processing.core.*; +import processing.data.*; +import processing.event.*; +import processing.opengl.*; + +import java.util.HashMap; +import java.util.ArrayList; +import java.io.File; +import java.io.BufferedReader; +import java.io.PrintWriter; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; + +public class bug1515 extends PApplet { + +// a class definition that does something with things that extend PApplet +class Heythere{ +} + +// method definition which can do things with papplet +public void doSomething( T thing ){ +} + static public void main(String[] passedArgs) { + String[] appletArgs = new String[] { "bug1515" }; + if (passedArgs != null) { + PApplet.main(concat(appletArgs, passedArgs)); + } else { + PApplet.main(appletArgs); + } + } +} diff --git a/app/test/resources/bug1516.expected b/app/test/resources/bug1516.expected index 15eb348d3..0fbef0c45 100644 --- a/app/test/resources/bug1516.expected +++ b/app/test/resources/bug1516.expected @@ -1,52 +1,52 @@ -import processing.core.*; -import processing.data.*; -import processing.event.*; -import processing.opengl.*; - -import java.util.ArrayList; -import java.util.List; -import java.util.Collections; -import java.util.Comparator; - -import java.util.HashMap; -import java.util.ArrayList; -import java.io.File; -import java.io.BufferedReader; -import java.io.PrintWriter; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.IOException; - -public class bug1516 extends PApplet { - - - - - - -public void setup() -{ -List list = new ArrayList(); -list.add("foo"); -list.add("bar"); -list.add("baz"); - -Comparator comparator = new Comparator() -{ -public int compare(final String value0, final String value1) -{ -return value0.compareTo(value1); -} -}; - -Collections.sort(list, comparator); -} - static public void main(String[] passedArgs) { - String[] appletArgs = new String[] { "bug1516" }; - if (passedArgs != null) { - PApplet.main(concat(appletArgs, passedArgs)); - } else { - PApplet.main(appletArgs); - } - } -} +import processing.core.*; +import processing.data.*; +import processing.event.*; +import processing.opengl.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.Collections; +import java.util.Comparator; + +import java.util.HashMap; +import java.util.ArrayList; +import java.io.File; +import java.io.BufferedReader; +import java.io.PrintWriter; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; + +public class bug1516 extends PApplet { + + + + + + +public void setup() +{ +List list = new ArrayList(); +list.add("foo"); +list.add("bar"); +list.add("baz"); + +Comparator comparator = new Comparator() +{ +public int compare(final String value0, final String value1) +{ +return value0.compareTo(value1); +} +}; + +Collections.sort(list, comparator); +} + static public void main(String[] passedArgs) { + String[] appletArgs = new String[] { "bug1516" }; + if (passedArgs != null) { + PApplet.main(concat(appletArgs, passedArgs)); + } else { + PApplet.main(appletArgs); + } + } +} diff --git a/app/test/resources/bug1517.expected b/app/test/resources/bug1517.expected index b8bac1af2..5af236bb6 100644 --- a/app/test/resources/bug1517.expected +++ b/app/test/resources/bug1517.expected @@ -1,52 +1,52 @@ -import processing.core.*; -import processing.data.*; -import processing.event.*; -import processing.opengl.*; - -import java.util.ArrayList; -import java.util.List; -import java.util.Collections; -import java.util.Comparator; - -import java.util.HashMap; -import java.util.ArrayList; -import java.io.File; -import java.io.BufferedReader; -import java.io.PrintWriter; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.IOException; - -public class bug1517 extends PApplet { - - - - - - -Comparator comparator = new Comparator() -{ -public int compare(final String value0, final String value1) -{ -return value0.compareTo(value1); -} -}; - -public void setup() -{ -List list = new ArrayList(); -list.add("foo"); -list.add("bar"); -list.add("baz"); - -Collections.sort(list, comparator); -} - static public void main(String[] passedArgs) { - String[] appletArgs = new String[] { "bug1517" }; - if (passedArgs != null) { - PApplet.main(concat(appletArgs, passedArgs)); - } else { - PApplet.main(appletArgs); - } - } -} +import processing.core.*; +import processing.data.*; +import processing.event.*; +import processing.opengl.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.Collections; +import java.util.Comparator; + +import java.util.HashMap; +import java.util.ArrayList; +import java.io.File; +import java.io.BufferedReader; +import java.io.PrintWriter; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; + +public class bug1517 extends PApplet { + + + + + + +Comparator comparator = new Comparator() +{ +public int compare(final String value0, final String value1) +{ +return value0.compareTo(value1); +} +}; + +public void setup() +{ +List list = new ArrayList(); +list.add("foo"); +list.add("bar"); +list.add("baz"); + +Collections.sort(list, comparator); +} + static public void main(String[] passedArgs) { + String[] appletArgs = new String[] { "bug1517" }; + if (passedArgs != null) { + PApplet.main(concat(appletArgs, passedArgs)); + } else { + PApplet.main(appletArgs); + } + } +} diff --git a/app/test/resources/bug1518a.expected b/app/test/resources/bug1518a.expected index 55288cc3c..49c81c14c 100644 --- a/app/test/resources/bug1518a.expected +++ b/app/test/resources/bug1518a.expected @@ -1,45 +1,45 @@ -import processing.core.*; -import processing.data.*; -import processing.event.*; -import processing.opengl.*; - -import java.util.ArrayList; -import java.util.List; - -import java.util.HashMap; -import java.util.ArrayList; -import java.io.File; -import java.io.BufferedReader; -import java.io.PrintWriter; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.IOException; - -public class bug1518a extends PApplet { - - - - -public void setup() -{ -List list = new ArrayList(); -list.add("foo"); -list.add("bar"); -list.add("baz"); - -binarySearch(list, "bar"); -} - -static int binarySearch(List> list, T -key) { -return 0; -} - static public void main(String[] passedArgs) { - String[] appletArgs = new String[] { "bug1518a" }; - if (passedArgs != null) { - PApplet.main(concat(appletArgs, passedArgs)); - } else { - PApplet.main(appletArgs); - } - } -} +import processing.core.*; +import processing.data.*; +import processing.event.*; +import processing.opengl.*; + +import java.util.ArrayList; +import java.util.List; + +import java.util.HashMap; +import java.util.ArrayList; +import java.io.File; +import java.io.BufferedReader; +import java.io.PrintWriter; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; + +public class bug1518a extends PApplet { + + + + +public void setup() +{ +List list = new ArrayList(); +list.add("foo"); +list.add("bar"); +list.add("baz"); + +binarySearch(list, "bar"); +} + +static int binarySearch(List> list, T +key) { +return 0; +} + static public void main(String[] passedArgs) { + String[] appletArgs = new String[] { "bug1518a" }; + if (passedArgs != null) { + PApplet.main(concat(appletArgs, passedArgs)); + } else { + PApplet.main(appletArgs); + } + } +} diff --git a/app/test/resources/bug1518b.expected b/app/test/resources/bug1518b.expected index f4144e7b1..2ca376adf 100644 --- a/app/test/resources/bug1518b.expected +++ b/app/test/resources/bug1518b.expected @@ -1,43 +1,43 @@ -import processing.core.*; -import processing.data.*; -import processing.event.*; -import processing.opengl.*; - -import java.util.ArrayList; -import java.util.List; - -import java.util.HashMap; -import java.util.ArrayList; -import java.io.File; -import java.io.BufferedReader; -import java.io.PrintWriter; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.IOException; - -public class bug1518b extends PApplet { - - - - -public void setup() -{ -List list = new ArrayList(); -list.add("foo"); -list.add("bar"); -list.add("baz"); -} - -static int binarySearch(List> list, T -key) { -return 0; -} - static public void main(String[] passedArgs) { - String[] appletArgs = new String[] { "bug1518b" }; - if (passedArgs != null) { - PApplet.main(concat(appletArgs, passedArgs)); - } else { - PApplet.main(appletArgs); - } - } -} +import processing.core.*; +import processing.data.*; +import processing.event.*; +import processing.opengl.*; + +import java.util.ArrayList; +import java.util.List; + +import java.util.HashMap; +import java.util.ArrayList; +import java.io.File; +import java.io.BufferedReader; +import java.io.PrintWriter; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; + +public class bug1518b extends PApplet { + + + + +public void setup() +{ +List list = new ArrayList(); +list.add("foo"); +list.add("bar"); +list.add("baz"); +} + +static int binarySearch(List> list, T +key) { +return 0; +} + static public void main(String[] passedArgs) { + String[] appletArgs = new String[] { "bug1518b" }; + if (passedArgs != null) { + PApplet.main(concat(appletArgs, passedArgs)); + } else { + PApplet.main(appletArgs); + } + } +} diff --git a/app/test/resources/bug281.expected b/app/test/resources/bug281.expected index d6e7f4154..ffc6ea519 100644 --- a/app/test/resources/bug281.expected +++ b/app/test/resources/bug281.expected @@ -1,32 +1,32 @@ -import processing.core.*; -import processing.data.*; -import processing.event.*; -import processing.opengl.*; - -import java.util.HashMap; -import java.util.ArrayList; -import java.io.File; -import java.io.BufferedReader; -import java.io.PrintWriter; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.IOException; - -public class bug281 extends PApplet { - public void setup() { -if ( "monopoly".charAt( 3 ) == '(' ) -{ - println("parcheesi"); -} - noLoop(); - } - - static public void main(String[] passedArgs) { - String[] appletArgs = new String[] { "bug281" }; - if (passedArgs != null) { - PApplet.main(concat(appletArgs, passedArgs)); - } else { - PApplet.main(appletArgs); - } - } -} +import processing.core.*; +import processing.data.*; +import processing.event.*; +import processing.opengl.*; + +import java.util.HashMap; +import java.util.ArrayList; +import java.io.File; +import java.io.BufferedReader; +import java.io.PrintWriter; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; + +public class bug281 extends PApplet { + public void setup() { +if ( "monopoly".charAt( 3 ) == '(' ) +{ + println("parcheesi"); +} + noLoop(); + } + + static public void main(String[] passedArgs) { + String[] appletArgs = new String[] { "bug281" }; + if (passedArgs != null) { + PApplet.main(concat(appletArgs, passedArgs)); + } else { + PApplet.main(appletArgs); + } + } +} diff --git a/app/test/resources/bug481.expected b/app/test/resources/bug481.expected index ef2848da3..10d76993b 100644 --- a/app/test/resources/bug481.expected +++ b/app/test/resources/bug481.expected @@ -1,32 +1,32 @@ -import processing.core.*; -import processing.data.*; -import processing.event.*; -import processing.opengl.*; - -import java.applet.Applet; - -import java.util.HashMap; -import java.util.ArrayList; -import java.io.File; -import java.io.BufferedReader; -import java.io.PrintWriter; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.IOException; - -public class bug481 extends PApplet { - public void setup() { - -Class[] abc = new Class[]{Applet.class}; - noLoop(); - } - - static public void main(String[] passedArgs) { - String[] appletArgs = new String[] { "bug481" }; - if (passedArgs != null) { - PApplet.main(concat(appletArgs, passedArgs)); - } else { - PApplet.main(appletArgs); - } - } -} +import processing.core.*; +import processing.data.*; +import processing.event.*; +import processing.opengl.*; + +import java.applet.Applet; + +import java.util.HashMap; +import java.util.ArrayList; +import java.io.File; +import java.io.BufferedReader; +import java.io.PrintWriter; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; + +public class bug481 extends PApplet { + public void setup() { + +Class[] abc = new Class[]{Applet.class}; + noLoop(); + } + + static public void main(String[] passedArgs) { + String[] appletArgs = new String[] { "bug481" }; + if (passedArgs != null) { + PApplet.main(concat(appletArgs, passedArgs)); + } else { + PApplet.main(appletArgs); + } + } +} diff --git a/app/test/resources/bug598.expected b/app/test/resources/bug598.expected index 988c1125b..e3c91eef6 100644 --- a/app/test/resources/bug598.expected +++ b/app/test/resources/bug598.expected @@ -1,70 +1,70 @@ -import processing.core.*; -import processing.data.*; -import processing.event.*; -import processing.opengl.*; - -import static java.lang.Math.tanh; -import java.util.concurrent.Callable; -import java.util.List; -import java.util.Comparator; -import java.util.Map; -import java.util.Collection; -import java.util.Arrays; -import java.util.HashSet; - -import java.util.HashMap; -import java.util.ArrayList; -import java.io.File; -import java.io.BufferedReader; -import java.io.PrintWriter; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.IOException; - -public class bug598 extends PApplet { - -// java 5 torture test - - - - - - - - - - - -private static Comparator rotarapmoc = new Comparator() { - public int compare(final String o1, final String o2) - { - return o1.charAt(o1.length() - 1) - o2.charAt(o2.length() - 1); - } -}; - -final void printClass(T t) { - println(t.getClass()); -} -public final List sortem(final String... strings) { - Arrays.sort(strings, rotarapmoc); - return Arrays.asList(strings); -} - -final Map> -charlesDeGaulle = new HashMap>(); - -public void setup() { - charlesDeGaulle.put("banana", new HashSet()); - charlesDeGaulle.get("banana").add(0); - System.out.println(sortem("aztec", "maya", "spanish", "portuguese")); - printClass(12.d); -} - static public void main(String[] passedArgs) { - String[] appletArgs = new String[] { "bug598" }; - if (passedArgs != null) { - PApplet.main(concat(appletArgs, passedArgs)); - } else { - PApplet.main(appletArgs); - } - } -} +import processing.core.*; +import processing.data.*; +import processing.event.*; +import processing.opengl.*; + +import static java.lang.Math.tanh; +import java.util.concurrent.Callable; +import java.util.List; +import java.util.Comparator; +import java.util.Map; +import java.util.Collection; +import java.util.Arrays; +import java.util.HashSet; + +import java.util.HashMap; +import java.util.ArrayList; +import java.io.File; +import java.io.BufferedReader; +import java.io.PrintWriter; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; + +public class bug598 extends PApplet { + +// java 5 torture test + + + + + + + + + + + +private static Comparator rotarapmoc = new Comparator() { + public int compare(final String o1, final String o2) + { + return o1.charAt(o1.length() - 1) - o2.charAt(o2.length() - 1); + } +}; + +final void printClass(T t) { + println(t.getClass()); +} +public final List sortem(final String... strings) { + Arrays.sort(strings, rotarapmoc); + return Arrays.asList(strings); +} + +final Map> +charlesDeGaulle = new HashMap>(); + +public void setup() { + charlesDeGaulle.put("banana", new HashSet()); + charlesDeGaulle.get("banana").add(0); + System.out.println(sortem("aztec", "maya", "spanish", "portuguese")); + printClass(12.d); +} + static public void main(String[] passedArgs) { + String[] appletArgs = new String[] { "bug598" }; + if (passedArgs != null) { + PApplet.main(concat(appletArgs, passedArgs)); + } else { + PApplet.main(appletArgs); + } + } +} diff --git a/app/test/resources/bug5a.expected b/app/test/resources/bug5a.expected index 326bd783e..c29588dfc 100644 --- a/app/test/resources/bug5a.expected +++ b/app/test/resources/bug5a.expected @@ -1,30 +1,30 @@ -import processing.core.*; -import processing.data.*; -import processing.event.*; -import processing.opengl.*; - -import java.util.HashMap; -import java.util.ArrayList; -import java.io.File; -import java.io.BufferedReader; -import java.io.PrintWriter; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.IOException; - -public class bug5a extends PApplet { - public void setup() { -println("The next line should not cause a failure."); -// no newline after me - noLoop(); - } - - static public void main(String[] passedArgs) { - String[] appletArgs = new String[] { "bug5a" }; - if (passedArgs != null) { - PApplet.main(concat(appletArgs, passedArgs)); - } else { - PApplet.main(appletArgs); - } - } -} +import processing.core.*; +import processing.data.*; +import processing.event.*; +import processing.opengl.*; + +import java.util.HashMap; +import java.util.ArrayList; +import java.io.File; +import java.io.BufferedReader; +import java.io.PrintWriter; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; + +public class bug5a extends PApplet { + public void setup() { +println("The next line should not cause a failure."); +// no newline after me + noLoop(); + } + + static public void main(String[] passedArgs) { + String[] appletArgs = new String[] { "bug5a" }; + if (passedArgs != null) { + PApplet.main(concat(appletArgs, passedArgs)); + } else { + PApplet.main(appletArgs); + } + } +} diff --git a/app/test/resources/bug5b.expected b/app/test/resources/bug5b.expected index 3731e6723..058be9ab3 100644 --- a/app/test/resources/bug5b.expected +++ b/app/test/resources/bug5b.expected @@ -1,30 +1,30 @@ -import processing.core.*; -import processing.data.*; -import processing.event.*; -import processing.opengl.*; - -import java.util.HashMap; -import java.util.ArrayList; -import java.io.File; -import java.io.BufferedReader; -import java.io.PrintWriter; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.IOException; - -public class bug5b extends PApplet { - public void setup() { -println("The next line should not cause a failure."); -/* no newline after me */ - noLoop(); - } - - static public void main(String[] passedArgs) { - String[] appletArgs = new String[] { "bug5b" }; - if (passedArgs != null) { - PApplet.main(concat(appletArgs, passedArgs)); - } else { - PApplet.main(appletArgs); - } - } -} +import processing.core.*; +import processing.data.*; +import processing.event.*; +import processing.opengl.*; + +import java.util.HashMap; +import java.util.ArrayList; +import java.io.File; +import java.io.BufferedReader; +import java.io.PrintWriter; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; + +public class bug5b extends PApplet { + public void setup() { +println("The next line should not cause a failure."); +/* no newline after me */ + noLoop(); + } + + static public void main(String[] passedArgs) { + String[] appletArgs = new String[] { "bug5b" }; + if (passedArgs != null) { + PApplet.main(concat(appletArgs, passedArgs)); + } else { + PApplet.main(appletArgs); + } + } +} diff --git a/build/macosx/jAppleMenuBar.url b/build/macosx/jAppleMenuBar.url index 62dc0f635..2e5268909 100644 --- a/build/macosx/jAppleMenuBar.url +++ b/build/macosx/jAppleMenuBar.url @@ -1,2 +1,2 @@ -[InternetShortcut] -URL=https://github.com/kritzikratzi/jAppleMenuBar +[InternetShortcut] +URL=https://github.com/kritzikratzi/jAppleMenuBar diff --git a/build/shared/lib/fonts/LICENSE.txt b/build/shared/lib/fonts/LICENSE.txt index d154618a7..117733042 100644 --- a/build/shared/lib/fonts/LICENSE.txt +++ b/build/shared/lib/fonts/LICENSE.txt @@ -1,93 +1,93 @@ -Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. - -This Font Software is licensed under the SIL Open Font License, Version 1.1. - -This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. +Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/build/windows/processing.bat b/build/windows/processing.bat index 7f0b9b3ea..64e7291eb 100755 --- a/build/windows/processing.bat +++ b/build/windows/processing.bat @@ -1,3 +1,3 @@ -@echo off - +@echo off + .\java\bin\java -cp lib/pde.jar;core/library/core.jar;lib/jna.jar;lib/antlr.jar;lib/ant.jar;lib/ant-launcher.jar;lib/org-netbeans-swing-outline.jar;lib/com.ibm.icu_4.4.2.v20110823.jar;lib/jdi.jar;lib/jdimodel.jar;lib/org.eclipse.osgi_3.8.1.v20120830-144521.jar processing.app.Base \ No newline at end of file diff --git a/java/libraries/dxf/.settings/org.eclipse.jdt.core.prefs b/java/libraries/dxf/.settings/org.eclipse.jdt.core.prefs index d8cc55f4b..2770cf1bf 100644 --- a/java/libraries/dxf/.settings/org.eclipse.jdt.core.prefs +++ b/java/libraries/dxf/.settings/org.eclipse.jdt.core.prefs @@ -1,12 +1,12 @@ -#Sat Nov 12 10:56:00 CST 2011 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.6 +#Sat Nov 12 10:56:00 CST 2011 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/java/libraries/serial/.settings/org.eclipse.jdt.core.prefs b/java/libraries/serial/.settings/org.eclipse.jdt.core.prefs index 5a822da57..f709eac1e 100644 --- a/java/libraries/serial/.settings/org.eclipse.jdt.core.prefs +++ b/java/libraries/serial/.settings/org.eclipse.jdt.core.prefs @@ -1,12 +1,12 @@ -#Sat Nov 12 10:56:44 CST 2011 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.6 +#Sat Nov 12 10:56:44 CST 2011 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 From 96e2e188eac32ba715d97e79abe3ca6f992c7d53 Mon Sep 17 00:00:00 2001 From: Kyle Feuz Date: Fri, 21 Nov 2014 00:59:22 -0700 Subject: [PATCH 2/2] .bat files always have windows line endings. build/macosx/jAppleMenuBar.url does as well --- .gitattributes | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.gitattributes b/.gitattributes index f4fc69cb2..b7d98e49d 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,12 @@ +# Set the default behavior, in case people don't have core.autocrlf set. * text=auto + +# Files which should always be normalized and converted +# to native line endings on checkout. *.java text *.pde text + +# Files that will always have CRLF line endings on checkout. +*.bat eol=crlf +build/macosx/jAppleMenuBar.url eol=crlf +