went in for import issues, did much housecleaning (fixes #3403)

This commit is contained in:
Ben Fry
2015-06-22 14:41:30 -04:00
parent b6e298073b
commit bc41d058d4
14 changed files with 399 additions and 325 deletions
+33 -28
View File
@@ -44,6 +44,7 @@ import javax.swing.tree.DefaultMutableTreeNode;
import processing.app.contrib.*;
import processing.core.*;
import processing.data.StringDict;
import processing.data.StringList;
@@ -2398,7 +2399,7 @@ public class Base {
* Changed in 3.0a6 to return null (rather than empty hash) if no file,
* and changed return type to Map instead of HashMap.
*/
static public Map<String, String> readSettings(File inputFile) {
static public StringDict readSettings(File inputFile) {
if (!inputFile.exists()) {
if (DEBUG) System.err.println(inputFile + " does not exist.");
return null;
@@ -2416,13 +2417,13 @@ public class Base {
* Parse a String array that contains attribute/value pairs separated
* by = (the equals sign). The # (hash) symbol is used to denote comments.
* Comments can be anywhere on a line. Blank lines are ignored.
* In 3.0a6, no longer taking a blank HahMap as param; no cases in the main
* In 3.0a6, no longer taking a blank HashMap as param; no cases in the main
* PDE code of adding to a (Hash)Map. Also returning the Map instead of void.
* Both changes modify the method signature, but this was only used by the
* contrib classes.
*/
static public Map<String, String> readSettings(String filename, String[] lines) {
Map<String, String> settings = new HashMap<>();
static public StringDict readSettings(String filename, String[] lines) {
StringDict settings = new StringDict();
for (String line : lines) {
// Remove comments
int commentMarker = line.indexOf('#');
@@ -2442,7 +2443,7 @@ public class Base {
} else {
String attr = line.substring(0, equals).trim();
String valu = line.substring(equals + 1).trim();
settings.put(attr, valu);
settings.set(attr, valu);
}
}
}
@@ -2797,8 +2798,9 @@ public class Base {
* @param path the input classpath
* @return array of possible package names
*/
static public String[] packageListFromClassPath(String path) {
Map<String, Object> map = new HashMap<String, Object>();
static public StringList packageListFromClassPath(String path) {
// Map<String, Object> map = new HashMap<String, Object>();
StringList list = new StringList();
String pieces[] =
PApplet.split(path, File.pathSeparatorChar);
@@ -2809,32 +2811,35 @@ public class Base {
if (pieces[i].toLowerCase().endsWith(".jar") ||
pieces[i].toLowerCase().endsWith(".zip")) {
//System.out.println("checking " + pieces[i]);
packageListFromZip(pieces[i], map);
packageListFromZip(pieces[i], list);
} else { // it's another type of file or directory
File dir = new File(pieces[i]);
if (dir.exists() && dir.isDirectory()) {
packageListFromFolder(dir, null, map);
packageListFromFolder(dir, null, list);
//importCount = magicImportsRecursive(dir, null,
// map);
//imports, importCount);
}
}
}
int mapCount = map.size();
String output[] = new String[mapCount];
int index = 0;
Set<String> set = map.keySet();
for (String s : set) {
output[index++] = s.replace('/', '.');
// int mapCount = map.size();
// String output[] = new String[mapCount];
// int index = 0;
// Set<String> set = map.keySet();
// for (String s : set) {
// output[index++] = s.replace('/', '.');
// }
// return output;
StringList outgoing = new StringList(list.size());
for (String item : list) {
outgoing.append(item.replace('/', '.'));
}
//System.arraycopy(imports, 0, output, 0, importCount);
//PApplet.printarr(output);
return output;
return outgoing;
}
static private void packageListFromZip(String filename, Map<String, Object> map) {
static private void packageListFromZip(String filename, StringList list) {
try {
ZipFile file = new ZipFile(filename);
Enumeration entries = file.entries();
@@ -2849,9 +2854,10 @@ public class Base {
if (slash == -1) continue;
String pname = name.substring(0, slash);
if (map.get(pname) == null) {
map.put(pname, new Object());
}
// if (map.get(pname) == null) {
// map.put(pname, new Object());
// }
list.appendUnique(pname);
}
}
}
@@ -2870,10 +2876,8 @@ public class Base {
* walk down into that folder and continue.
*/
static private void packageListFromFolder(File dir, String sofar,
Map<String, Object> map) {
//String imports[],
//int importCount) {
//System.err.println("checking dir '" + dir + "'");
StringList list) {
// Map<String, Object> map) {
boolean foundClass = false;
String files[] = dir.list();
@@ -2884,7 +2888,7 @@ public class Base {
if (sub.isDirectory()) {
String nowfar =
(sofar == null) ? files[i] : (sofar + "." + files[i]);
packageListFromFolder(sub, nowfar, map);
packageListFromFolder(sub, nowfar, list);
//System.out.println(nowfar);
//imports[importCount++] = nowfar;
//importCount = magicImportsRecursive(sub, nowfar,
@@ -2892,7 +2896,8 @@ public class Base {
} else if (!foundClass) { // if no classes found in this folder yet
if (files[i].endsWith(".class")) {
//System.out.println("unique class: " + files[i] + " for " + sofar);
map.put(sofar, new Object());
// map.put(sofar, new Object());
list.appendUnique(sofar);
foundClass = true;
}
}
+37 -29
View File
@@ -5,6 +5,8 @@ import java.util.*;
import processing.app.contrib.*;
import processing.core.*;
import processing.data.StringDict;
import processing.data.StringList;
public class Library extends LocalContribution {
@@ -23,7 +25,7 @@ public class Library extends LocalContribution {
protected String group;
/** Packages provided by this library. */
String[] packageList;
StringList packageList;
/** Per-platform exports for this library. */
HashMap<String,String[]> exportList;
@@ -113,8 +115,8 @@ public class Library extends LocalContribution {
referenceFile = new File(folder, "reference/index.html");
File exportSettings = new File(libraryFolder, "export.txt");
Map<String, String> exportTable = exportSettings.exists() ?
Base.readSettings(exportSettings) : new HashMap<String, String>();
StringDict exportTable = exportSettings.exists() ?
Base.readSettings(exportSettings) : new StringDict();
exportList = new HashMap<String, String[]>();
@@ -437,23 +439,23 @@ public class Library extends LocalContribution {
};
static public ArrayList<File> discover(File folder) {
ArrayList<File> libraries = new ArrayList<File>();
discover(folder, libraries);
return libraries;
}
static public void discover(File folder, ArrayList<File> libraries) {
String[] list = folder.list(junkFolderFilter);
static public List<File> discover(File folder) {
List<File> libraries = new ArrayList<File>();
// discover(folder, libraries);
// return libraries;
// }
//
//
// static void discover(File folder, List<File> libraries) {
String[] folderNames = folder.list(junkFolderFilter);
// if a bad folder or something like that, this might come back null
if (list != null) {
if (folderNames != null) {
// alphabetize list, since it's not always alpha order
// replaced hella slow bubble sort with this feller for 0093
Arrays.sort(list, String.CASE_INSENSITIVE_ORDER);
Arrays.sort(folderNames, String.CASE_INSENSITIVE_ORDER);
for (String potentialName : list) {
for (String potentialName : folderNames) {
File baseFolder = new File(folder, potentialName);
File libraryFolder = new File(baseFolder, "library");
File libraryJar = new File(libraryFolder, potentialName + ".jar");
@@ -476,32 +478,37 @@ public class Library extends LocalContribution {
}
}
}
}
static protected ArrayList<Library> list(File folder) {
ArrayList<Library> libraries = new ArrayList<Library>();
list(folder, libraries);
return libraries;
}
static protected void list(File folder, ArrayList<Library> libraries) {
ArrayList<File> librariesFolders = new ArrayList<File>();
discover(folder, librariesFolders);
static public List<Library> list(File folder) {
List<Library> libraries = new ArrayList<Library>();
// list(folder, libraries);
// return libraries;
// }
//
//
// static void list(File folder, List<Library> libraries) {
List<File> librariesFolders = new ArrayList<File>();
librariesFolders.addAll(discover(folder));
for (File baseFolder : librariesFolders) {
libraries.add(new Library(baseFolder));
}
String[] list = folder.list(junkFolderFilter);
if (list != null) {
for (String subfolderName : list) {
// Support libraries inside of one level of subfolders? I believe this was
// the compromise for supporting library groups, but probably a bad idea
// because it's not compatible with the Manager.
String[] folderNames = folder.list(junkFolderFilter);
if (folderNames != null) {
for (String subfolderName : folderNames) {
File subfolder = new File(folder, subfolderName);
if (!librariesFolders.contains(subfolder)) {
ArrayList<File> discoveredLibFolders = new ArrayList<File>();
discover(subfolder, discoveredLibFolders);
// ArrayList<File> discoveredLibFolders = new ArrayList<File>();
// discover(subfolder, discoveredLibFolders);
List<File> discoveredLibFolders = discover(subfolder);
for (File discoveredFolder : discoveredLibFolders) {
libraries.add(new Library(discoveredFolder, subfolderName));
@@ -509,6 +516,7 @@ public class Library extends LocalContribution {
}
}
}
return libraries;
}
+3 -2
View File
@@ -29,6 +29,7 @@ import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.*;
import java.util.*;
import java.util.List;
import javax.swing.*;
import javax.swing.border.Border;
@@ -76,8 +77,8 @@ public abstract class Mode {
protected File examplesContribFolder;
public ArrayList<Library> coreLibraries;
public ArrayList<Library> contribLibraries;
public List<Library> coreLibraries;
public List<Library> contribLibraries;
/** Library folder for core. (Used for OpenGL in particular.) */
protected Library coreLibrary;
@@ -3,7 +3,7 @@
/*
Part of the Processing project - http://processing.org
Copyright (c) 2013 The Processing Foundation
Copyright (c) 2013-15 The Processing Foundation
Copyright (c) 2011-12 Ben Fry and Casey Reas
This program is free software; you can redistribute it and/or modify
@@ -15,49 +15,52 @@
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
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.util.List;
import java.util.Map;
import processing.app.Base;
import processing.app.Language;
import processing.core.PApplet;
import processing.data.StringDict;
import processing.data.StringList;
/**
* A class to hold information about a Contribution that can be downloaded.
* A class to hold information about a Contribution that can be downloaded.
*/
public class AvailableContribution extends Contribution {
protected final ContributionType type; // Library, tool, etc.
protected final String link; // Direct link to download the file
public AvailableContribution(ContributionType type, Map<String, String> params) {
public AvailableContribution(ContributionType type, StringDict params) {
this.type = type;
this.link = params.get("download");
//category = ContributionListing.getCategory(params.get("category"));
categories = parseCategories(params.get("category"));
imports = parseImports(params.get("imports"));
categories = parseCategories(params);
imports = parseImports(params);
name = params.get("name");
authorList = params.get("authorList");
authors = params.get("authors");
if (authors == null) {
authors = params.get("authorList");
}
url = params.get("url");
sentence = params.get("sentence");
paragraph = params.get("paragraph");
String versionStr = params.get("version");
if (versionStr != null) {
version = PApplet.parseInt(versionStr, 0);
}
prettyVersion = params.get("prettyVersion");
String lastUpdatedStr = params.get("lastUpdated");
if (lastUpdatedStr != null) {
try {
@@ -70,14 +73,14 @@ public class AvailableContribution extends Contribution {
if (minRev != null) {
minRevision = PApplet.parseInt(minRev, 0);
}
String maxRev = params.get("maxRevision");
if (maxRev != null) {
maxRevision = PApplet.parseInt(maxRev, 0);
}
}
/**
* @param contribArchive
* a zip file containing the library to install
@@ -91,12 +94,12 @@ public class AvailableContribution extends Contribution {
*/
public LocalContribution install(Base base, File contribArchive,
boolean confirmReplace, StatusPanel status) {
// Unzip the file into the modes, tools, or libraries folder inside the
// sketchbook. Unzipping to /tmp is problematic because it may be on
// Unzip the file into the modes, tools, or libraries folder inside the
// sketchbook. Unzipping to /tmp is problematic because it may be on
// another file system, so move/rename operations will break.
// File sketchbookContribFolder = type.getSketchbookFolder();
File tempFolder = null;
File tempFolder = null;
try {
tempFolder = type.createTempFolder();
} catch (IOException e) {
@@ -110,15 +113,15 @@ public class AvailableContribution extends Contribution {
// Now go looking for a legit contrib inside what's been unpacked.
File contribFolder = null;
// Sometimes contrib authors place all their folders in the base directory
// of the .zip file instead of in single folder as the guidelines suggest.
// Sometimes contrib authors place all their folders in the base directory
// of the .zip file instead of in single folder as the guidelines suggest.
if (type.isCandidate(tempFolder)) {
/*
// Can't just rename the temp folder, because a contrib with this name
// may already exist. Instead, create a new temp folder, and rename the
// may already exist. Instead, create a new temp folder, and rename the
// old one to be the correct folder.
File enclosingFolder = null;
File enclosingFolder = null;
try {
enclosingFolder = Base.createTempFolder(type.toString(), "tmp", sketchbookContribFolder);
} catch (IOException e) {
@@ -145,27 +148,27 @@ public class AvailableContribution extends Contribution {
if (status != null) {
status.setErrorMessage(Language.interpolate("contrib.errors.no_contribution_found", type));
}
} else {
File propFile = new File(contribFolder, type + ".properties");
if (writePropertiesFile(propFile)) {
// 1. contribFolder now has a legit contribution, load it to get info.
if (writePropertiesFile(propFile)) {
// 1. contribFolder now has a legit contribution, load it to get info.
LocalContribution newContrib = type.load(base, contribFolder);
// 1.1. get info we need to delete the newContrib folder later
File newContribFolder = newContrib.getFolder();
// 2. Check to make sure nothing has the same name already,
// 2. Check to make sure nothing has the same name already,
// backup old if needed, then move things into place and reload.
installedContrib =
installedContrib =
newContrib.copyAndLoad(base, confirmReplace, status);
// Restart no longer needed. Yay!
// if (newContrib != null && type.requiresRestart()) {
// installedContrib.setRestartFlag();
// //status.setMessage("Restart Processing to finish the installation.");
// }
// 3.1 Unlock all the jars if it is a mode or tool
if (newContrib.getType() == ContributionType.MODE) {
((ModeContribution)newContrib).clearClassLoader(base);
@@ -173,13 +176,13 @@ public class AvailableContribution extends Contribution {
else if (newContrib.getType() == ContributionType.TOOL) {
((ToolContribution)newContrib).clearClassLoader(base);
}
// 3.2 Delete the newContrib, do a garbage collection, hope and pray
// that Java will unlock the temp folder on Windows now
newContrib = null;
System.gc();
if (Base.isWindows()) {
// we'll even give it a second to finish up ... because file ops are
// just that flaky on Windows.
@@ -192,7 +195,7 @@ public class AvailableContribution extends Contribution {
// 4. Okay, now actually delete that temp folder
Base.removeDir(newContribFolder);
} else {
if (status != null) {
status.setErrorMessage(Language.text("contrib.errors.overwriting_properties"));
@@ -206,13 +209,13 @@ public class AvailableContribution extends Contribution {
}
return installedContrib;
}
public boolean isInstalled() {
return false;
}
public ContributionType getType() {
return type;
}
@@ -226,20 +229,20 @@ public class AvailableContribution extends Contribution {
* manager. However, it also ensures that valid fields in the properties file
* aren't overwritten, since the properties file may be more recent than the
* contributions.txt file.
*
*
* @param propFile
* @return
*/
public boolean writePropertiesFile(File propFile) {
try {
Map<String, String> properties = Base.readSettings(propFile);
StringDict properties = Base.readSettings(propFile);
String name = properties.get("name");
if (name == null || name.isEmpty())
name = getName();
String category;
List<String> categoryList = parseCategories(properties.get("category"));
StringList categoryList = parseCategories(properties);
if (categoryList.size() == 1 && categoryList.get(0).equals("Unknown")) {
category = getCategoryStr();
} else {
@@ -252,8 +255,9 @@ public class AvailableContribution extends Contribution {
category = sb.toString();
}
String specifiedImport = "";
List<String> importsList = parseImports(properties.get("imports"));
//String specifiedImport = "";
StringList importsList = parseImports(properties);
/*
if (importsList == null || importsList.isEmpty()) {
specifiedImport = getImportStr();
} else {
@@ -265,10 +269,15 @@ public class AvailableContribution extends Contribution {
sbImport.deleteCharAt(sbImport.length() - 1);
specifiedImport = sbImport.toString();
}
*/
String importItem = importsList.join(",");
String authorList = properties.get("authorList");
if (authorList == null || authorList.isEmpty()) {
authorList = getAuthorList();
String authors = properties.get(AUTHORS_PROPERTY);
if (authors == null) {
authors = properties.get("authorList"); // before 3.0a11
}
if (authors == null || authors.isEmpty()) {
authors = getAuthorList();
}
String url = properties.get("url");
@@ -291,20 +300,18 @@ public class AvailableContribution extends Contribution {
version = Integer.parseInt(properties.get("version"));
} catch (NumberFormatException e) {
version = getVersion();
System.err.println("The version number for the “" + name
+ "” contribution is not set properly.");
System.err
.println("Please contact the author to fix it according to the guidelines.");
System.err.println("The version number for “" + name + "” is not set properly.");
System.err.println("Please contact the author to fix it according to the guidelines.");
}
String prettyVersion = properties.get("prettyVersion");
if (prettyVersion == null || prettyVersion.isEmpty())
prettyVersion = getPrettyVersion();
String compatibleContribsList = null;
if (getType() == ContributionType.EXAMPLES) {
compatibleContribsList = properties.get("compatibleModesList");
compatibleContribsList = properties.get(MODES_PROPERTY);
}
long lastUpdated;
@@ -312,7 +319,7 @@ public class AvailableContribution extends Contribution {
lastUpdated = Long.parseLong(properties.get("lastUpdated"));
} catch (NumberFormatException nfe) {
lastUpdated = getLastUpdated();
// Better comment these out till all contribs have a lastUpdated
// Better comment these out till all contribs have a lastUpdated
// System.err.println("The last updated date for the “" + name
// + "” contribution is not set properly.");
// System.err
@@ -335,14 +342,14 @@ public class AvailableContribution extends Contribution {
maxRev = getMaxRevision();
// System.err.println("The maximum compatible revision for the “" + name
// + "” contribution is not set properly. Assuming maximum revision INF.");
}
}
if (propFile.delete() && propFile.createNewFile() && propFile.setWritable(true)) {
PrintWriter writer = PApplet.createWriter(propFile);
writer.println("name=" + name);
writer.println("category=" + category);
writer.println("authorList=" + authorList);
writer.println(AUTHORS_PROPERTY + "=" + authors);
writer.println("url=" + url);
writer.println("sentence=" + sentence);
writer.println("paragraph=" + paragraph);
@@ -352,10 +359,10 @@ public class AvailableContribution extends Contribution {
writer.println("minRevision=" + minRev);
writer.println("maxRevision=" + maxRev);
if (getType() == ContributionType.LIBRARY) {
writer.println("imports=" + specifiedImport);
writer.println("imports=" + importItem);
}
if (getType() == ContributionType.EXAMPLES) {
writer.println("compatibleModesList=" + compatibleContribsList);
writer.println(MODES_PROPERTY + "=" + compatibleContribsList);
}
writer.flush();
@@ -21,36 +21,45 @@
*/
package processing.app.contrib;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import processing.core.PApplet;
import processing.data.StringDict;
import processing.data.StringList;
import processing.app.Language;
abstract public class Contribution {
static final String SPECIAL_CATEGORY_NAME = "Starred";
static final String IMPORTS_PROPERTY = "imports";
static final String CATEGORIES_PROPERTY = "category";
//static final String MODES_PROPERTY = "compatibleModesList";
static final String MODES_PROPERTY = "modes";
//static final String AUTHORS_PROPERTY = "authorList";
static final String AUTHORS_PROPERTY = "authors";
static final String SPECIAL_CATEGORY = "Starred";
static final String UNKNOWN_CATEGORY = "Unknown";
static final List validCategories =
Arrays.asList("3D", "Animation", "Data", "Geometry", "GUI", "Hardware",
"I/O", "Math", "Simulation", "Sound", SPECIAL_CATEGORY_NAME,
"I/O", "Math", "Simulation", "Sound", SPECIAL_CATEGORY,
"Typography", "Utilities", "Video & Vision", "Other");
protected List<String> categories; // "Sound", "Typography"
protected String name; // "pdf" or "PDF Export"
protected String authorList; // [Ben Fry](http://benfry.com)
protected String url; // http://processing.org
protected String sentence; // Write graphics to PDF files.
protected String paragraph; // <paragraph length description for site>
protected int version; // 102
protected String prettyVersion; // "1.0.2"
protected long lastUpdated; // 1402805757
protected int minRevision; // 0
protected int maxRevision; // 227
protected List<String> imports; // pdf.export.*,pdf.convert.common.*
protected StringList categories; // "Sound", "Typography"
protected String name; // "pdf" or "PDF Export"
protected String authors; // [Ben Fry](http://benfry.com)
protected String url; // http://processing.org
protected String sentence; // Write graphics to PDF files.
protected String paragraph; // <paragraph length description for site>
protected int version; // 102
protected String prettyVersion; // "1.0.2"
protected long lastUpdated; // 1402805757
protected int minRevision; // 0
protected int maxRevision; // 227
protected StringList imports; // pdf.export,pdf.convert.common (list of packages, not imports)
// "Sound", "Utilities"... see valid list in ContributionListing
protected List<String> getCategories() {
protected StringList getCategories() {
return categories;
}
@@ -79,11 +88,11 @@ abstract public class Contribution {
// pdf.export.*,pdf.convert.common.*
protected List<String> getImports() {
protected StringList getImports() {
return imports;
}
/*
protected String getImportStr() {
if (imports == null || imports.isEmpty()) {
return "";
@@ -96,12 +105,12 @@ abstract public class Contribution {
sb.deleteCharAt(sb.length() - 1); // delete last comma
return sb.toString();
}
*/
protected boolean hasImport(String importName) {
if (imports != null && importName != null) {
for (String c : imports) {
if (importName.equalsIgnoreCase(c)) {
if (importName.equals(c)) {
return true;
}
}
@@ -118,7 +127,7 @@ abstract public class Contribution {
// "[Ben Fry](http://benfry.com/)"
public String getAuthorList() {
return authorList;
return authors;
}
@@ -180,6 +189,12 @@ abstract public class Contribution {
}
/** Get the name of the properties file for this type of contribution. */
public String getPropertiesName() {
return getTypeName() + ".properties";
}
abstract public boolean isInstalled();
@@ -209,28 +224,29 @@ abstract public class Contribution {
/**
* Returns true if the contribution is a starred/recommended contribution, or
* is by the Processing Foundation.
*
* @return
* Returns true if the contribution is a starred/recommended contribution,
* or is by the Processing Foundation.
*/
boolean isSpecial() {
try {
return (authorList.indexOf("The Processing Foundation") != -1 ||
categories.contains(SPECIAL_CATEGORY_NAME));
} catch (NullPointerException npe) {
return false;
if (authors != null &&
authors.contains("The Processing Foundation")) {
return true;
}
if (categories != null &&
categories.hasValue(SPECIAL_CATEGORY)) {
return true;
}
return false;
}
/**
* @return a single element list with "Unknown" as the category.
*/
static List<String> defaultCategory() {
List<String> outgoing = new ArrayList<String>();
outgoing.add("Unknown");
return outgoing;
static StringList unknownCategory() {
return new StringList(UNKNOWN_CATEGORY);
}
@@ -238,35 +254,42 @@ abstract public class Contribution {
* @return the list of categories that this contribution is part of
* (e.g. "Typography / Geometry"). "Unknown" if the category null.
*/
static List<String> parseCategories(String categoryStr) {
List<String> outgoing = new ArrayList<String>();
static StringList parseCategories(StringDict properties) {
StringList outgoing = new StringList();
String categoryStr = properties.get(CATEGORIES_PROPERTY);
if (categoryStr != null) {
String[] listing = PApplet.trim(PApplet.split(categoryStr, ','));
for (String category : listing) {
if (validCategories.contains(category)) {
category = translateCategory(category);
outgoing.add(category);
outgoing.append(category);
}
}
}
if (outgoing.size() == 0) {
return defaultCategory();
return unknownCategory();
}
return outgoing;
}
/**
* @return the list of imports that this contribution (library) contains.
* Returns the list of imports specified by this library author. Only
* necessary for library authors that want to override the default behavior
* of importing all packages in their library.
* @return null if no entries found
*/
static List<String> parseImports(String importStr) {
List<String> outgoing = new ArrayList<String>();
static StringList parseImports(StringDict properties) {
StringList outgoing = new StringList();
String importStr = properties.get(IMPORTS_PROPERTY);
if (importStr != null) {
String[] importList = PApplet.trim(PApplet.split(importStr, ','));
for (String importName : importList) {
outgoing.add(importName);
if (!importName.isEmpty()) {
outgoing.append(importName);
}
}
}
return (outgoing.size() > 0) ? outgoing : null;
@@ -3,7 +3,7 @@
/*
Part of the Processing project - http://processing.org
Copyright (c) 2013 The Processing Foundation
Copyright (c) 2013-15 The Processing Foundation
Copyright (c) 2011-12 Ben Fry and Casey Reas
This program is free software; you can redistribute it and/or modify
@@ -30,6 +30,7 @@ import java.util.concurrent.locks.ReentrantLock;
import processing.app.Base;
import processing.app.Library;
import processing.core.PApplet;
import processing.data.StringDict;
public class ContributionListing {
@@ -555,7 +556,7 @@ public class ContributionListing {
String[] contribLines = PApplet.subset(lines, start, end-start);
Map<String, String> contribParams = Base.readSettings(file.getName(), contribLines);
StringDict contribParams = Base.readSettings(file.getName(), contribLines);
outgoing.add(new AvailableContribution(contribType, contribParams));
start = end + 1;
@@ -31,6 +31,7 @@ import processing.app.Base;
import processing.app.Editor;
import processing.app.Language;
import processing.core.PApplet;
import processing.data.StringDict;
public class ContributionManager {
@@ -613,9 +614,8 @@ public class ContributionManager {
propFileName = "libraries.properties";
for (File folder : markedForUpdate) {
Map<String, String> properties =
Base.readSettings(new File(folder, propFileName));
updateContribsNames.add(properties.get("name"));
StringDict props = Base.readSettings(new File(folder, propFileName));
updateContribsNames.add(props.get("name"));
Base.removeDir(folder);
}
@@ -54,30 +54,27 @@ public enum ContributionType {
* @return Mode for mode, Tool for tool, etc.
*/
public String getTitle() {
String s = toString();
if (this == EXAMPLES)
return Character.toUpperCase(s.charAt(0))
+ s.substring(1, s.indexOf('-') + 1)
+ Character.toUpperCase(s.charAt(s.indexOf('-') + 1))
+ s.substring(s.indexOf('-') + 2);
else
return Character.toUpperCase(s.charAt(0)) + s.substring(1);
String lower = toString();
return Character.toUpperCase(lower.charAt(0)) + lower.substring(1);
}
public String getFolderName() {
switch (this) {
case LIBRARY:
return "libraries";
case TOOL:
return "tools";
case MODE:
return "modes";
case EXAMPLES:
return "examples";
}
return null; // should be unreachable
}
// public String getFolderName() {
// return toString();
// /*
// switch (this) {
// case LIBRARY:
// return "libraries";
// case TOOL:
// return "tools";
// case MODE:
// return "modes";
// case EXAMPLES:
// return "examples";
// }
// return null; // should be unreachable
// */
// }
public File createTempFolder() throws IOException {
@@ -1,59 +1,66 @@
package processing.app.contrib;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import processing.app.Base;
import processing.core.PApplet;
import processing.data.StringDict;
import processing.data.StringList;
import static processing.app.contrib.ContributionType.EXAMPLES;
public class ExamplesContribution extends LocalContribution {
private StringList modeList;
private ArrayList<String> compatibleModesList;
static public ExamplesContribution load(File folder) {
return new ExamplesContribution(folder);
}
private ExamplesContribution(File folder) {
super(folder);
if (properties != null) {
compatibleModesList = parseCompatibleModesList(properties
.get("compatibleModesList"));
modeList = parseModeList(properties);
}
}
private static ArrayList<String> parseCompatibleModesList(String unparsedModes) {
ArrayList<String> modesList = new ArrayList<String>();
if (unparsedModes == null || unparsedModes.isEmpty())
return modesList;
String[] splitStr = PApplet.trim(PApplet.split(unparsedModes, ','));//unparsedModes.split(",");
for (String mode : splitStr)
modesList.add(mode.trim());
return modesList;
static private StringList parseModeList(StringDict properties) {
String unparsedModes = properties.get(MODES_PROPERTY);
StringList outgoing = new StringList();
if (unparsedModes != null) {
outgoing.append(PApplet.trim(PApplet.split(unparsedModes, ',')));
}
return outgoing;
}
/**
* Function to determine whether or not the example present in the
* exampleLocation directory is compatible with the present mode.
* exampleLocation directory is compatible with the current mode.
*
* @param base
* @param exampleLocationFolder
* @param exampleFolder
* @return true if the example is compatible with the mode of the currently
* active editor
*/
public static boolean isExamplesCompatible(Base base,
File exampleLocationFolder) {
File propertiesFile = new File(exampleLocationFolder,
ContributionType.EXAMPLES.toString()
+ ".properties");
public boolean isCompatible(Base base, File exampleFolder) {
String currentIdentifier = base.getActiveEditor().getMode().getIdentifier();
File propertiesFile =
new File(exampleFolder, getPropertiesName());
if (propertiesFile.exists()) {
ArrayList<String> compModesList = parseCompatibleModesList(Base
.readSettings(propertiesFile).get("compatibleModesList"));
for (String c : compModesList) {
if (c.equalsIgnoreCase(base.getActiveEditor().getMode().getIdentifier())) {
StringList compatibleList =
parseModeList(Base.readSettings(propertiesFile));
if (compatibleList.size() == 0) {
return true; // if no mode specified, just include everywhere
}
for (String c : compatibleList) {
if (c.equals(currentIdentifier)) {
return true;
}
}
@@ -61,6 +68,7 @@ public class ExamplesContribution extends LocalContribution {
return false;
}
static public void loadMissing(Base base) {
File examplesFolder = Base.getSketchbookExamplesFolder();
List<ExamplesContribution> contribExamples = base.getExampleContribs();
@@ -69,7 +77,7 @@ public class ExamplesContribution extends LocalContribution {
for (ExamplesContribution contrib : contribExamples) {
existing.put(contrib.getFolder(), contrib);
}
File[] potential = ContributionType.EXAMPLES.listCandidates(examplesFolder);
File[] potential = EXAMPLES.listCandidates(examplesFolder);
// 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) {
@@ -81,13 +89,14 @@ public class ExamplesContribution extends LocalContribution {
}
}
@Override
public ContributionType getType() {
return ContributionType.EXAMPLES;
return EXAMPLES;
}
public ArrayList<String> getCompatibleModesList() {
return compatibleModesList;
}
public StringList getModeList() {
return modeList;
}
}
@@ -3,7 +3,7 @@
/*
Part of the Processing project - http://processing.org
Copyright (c) 2013 The Processing Foundation
Copyright (c) 2013-15 The Processing Foundation
Copyright (c) 2011-12 Ben Fry and Casey Reas
This program is free software; you can redistribute it and/or modify
@@ -15,7 +15,7 @@
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
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
*/
@@ -32,9 +32,11 @@ import javax.swing.JOptionPane;
import processing.app.*;
import processing.core.PApplet;
import processing.data.StringDict;
import processing.data.StringList;
/**
/**
* A contribution that has been downloaded to the disk, and may or may not
* be installed.
*/
@@ -42,13 +44,14 @@ 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 Map<String, String> properties;
protected StringDict properties;
protected ClassLoader loader;
public LocalContribution(File folder) {
this.folder = folder;
@@ -59,12 +62,16 @@ public abstract class LocalContribution extends Contribution {
name = properties.get("name");
id = properties.get("id");
categories = parseCategories(properties.get("category"));
imports = parseImports(properties.get("imports"));
categories = parseCategories(properties);
imports = parseImports(properties);
if (name == null) {
name = folder.getName();
}
authorList = properties.get("authorList");
// changing to 'authors' in 3.0a11
authors = properties.get(AUTHORS_PROPERTY);
if (authors == null) {
authors = properties.get("authorList");
}
url = properties.get("url");
sentence = properties.get("sentence");
paragraph = properties.get("paragraph");
@@ -75,15 +82,15 @@ public abstract class LocalContribution extends Contribution {
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
// 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.");
}
@@ -92,31 +99,34 @@ public abstract class LocalContribution extends Contribution {
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();
categories = unknownCategory();
}
if (categories.contains(SPECIAL_CATEGORY_NAME))
if (categories.hasValue(SPECIAL_CATEGORY)) {
validateSpecial();
}
}
private void validateSpecial() {
for (AvailableContribution available : ContributionListing.getInstance().advertisedContributions)
for (AvailableContribution available : ContributionListing.getInstance().advertisedContributions) {
if (available.getName().equals(name)) {
if (!available.isSpecial())
categories.remove(SPECIAL_CATEGORY_NAME);
if (!available.isSpecial()) {
categories.removeValue(SPECIAL_CATEGORY);
}
}
return;
break;
}
}
@@ -187,8 +197,8 @@ public abstract class LocalContribution extends Contribution {
// 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'
@@ -210,34 +220,34 @@ public abstract class LocalContribution extends Contribution {
// */
// 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,
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<LocalContribution> oldContribs =
ArrayList<LocalContribution> 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();
@@ -292,7 +302,7 @@ public abstract class LocalContribution extends Contribution {
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
@@ -304,7 +314,7 @@ public abstract class LocalContribution extends Contribution {
contribFolder = new File(contribTypeFolder, contribFolderName);
}
}
File oldFolder = getFolder();
try {
@@ -319,12 +329,12 @@ public abstract class LocalContribution extends Contribution {
/*
if (!getFolder().renameTo(contribFolder)) {
status.setErrorMessage("Could not move " + getTypeName() +
status.setErrorMessage("Could not move " + getTypeName() +
" \"" + getName() + "\" to the sketchbook.");
return null;
}
*/
return getType().load(base, contribFolder);
}
@@ -337,13 +347,13 @@ public abstract class LocalContribution extends Contribution {
*/
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 =
File backupSubFolder =
ContributionManager.getUniqueName(backupFolder, backupName);
if (deleteOriginal) {
@@ -372,16 +382,16 @@ public abstract class LocalContribution extends Contribution {
public void run() {
remove(editor,
pm,
status,
ContributionListing.getInstance());
status,
ContributionListing.getInstance());
}
}, "Contribution Uninstaller").start();
}
void remove(final Editor editor,
final ContribProgressMonitor pm,
final StatusPanel status,
final StatusPanel status,
final ContributionListing contribListing) {
pm.startTask("Removing", ContribProgressMonitor.UNKNOWN);
@@ -415,7 +425,7 @@ public abstract class LocalContribution extends Contribution {
return;
}
}
if (getType() == ContributionType.TOOL) {
ToolContribution t = (ToolContribution) this;
Iterator<Editor> iter = editor.getBase().getEditors().iterator();
@@ -425,7 +435,7 @@ public abstract class LocalContribution extends Contribution {
}
t.clearClassLoader(editor.getBase());
}
if (doBackup) {
success = backup(editor, true, status);
} else {
@@ -446,7 +456,7 @@ public abstract class LocalContribution extends Contribution {
} else {
contribListing.replaceContribution(this, advertisedVersion);
}
}
}
else {
// There was a failure backing up the folder
if (!doBackup || (doBackup && backup(editor, false, status))) {
@@ -465,7 +475,7 @@ public abstract class LocalContribution extends Contribution {
pm.cancel();
}
public File getFolder() {
return folder;
}
@@ -474,7 +484,7 @@ public abstract class LocalContribution extends Contribution {
public boolean isInstalled() {
return folder != null;
}
// public String getCategory() {
// return category;
@@ -542,51 +552,54 @@ public abstract class LocalContribution extends Contribution {
return null;
}
*/
/**
* Returns the imports (package-names) for a library, as specified in its library.properties
* (e.g., imports=libname.*,libname.support.*)
*
* (e.g., imports=libname.*,libname.support.*)
*
* @return String[] packageNames (without wildcards) or null if none are specified
*/
public String[] getSpecifiedImports() {
return imports != null ? imports.toArray(new String[0]) : null;
public StringList getImports() {
//return imports != null ? imports.toArray(new String[0]) : null;
return imports;
}
/**
* @return the list of Java imports to be added to the sketch when the library is imported
* or null if none are specified
*/
protected static List<String> parseImports(String importsStr) {
List<String> outgoing = new ArrayList<String>();
if (importsStr != null) {
String[] listing = PApplet.trim(PApplet.split(importsStr, ','));
for (String imp : listing) {
// In case the wildcard is specified, strip it, as it gets added later)
if (imp.endsWith(".*")) {
// this duplicates code found in Contribution (though that version doesn't check for .* at the end)
// /**
// * @return the list of Java imports to be added to the sketch when the library is imported
// * or null if none are specified
// */
// static StringList parseImports(String importsStr) {
// StringList outgoing = new StringList();
//
// if (importsStr != null) {
// String[] listing = PApplet.trim(PApplet.split(importsStr, ','));
// for (String imp : listing) {
//
// // In case the wildcard is specified, strip it, as it gets added later)
// if (imp.endsWith(".*")) {
//
// imp = imp.substring(0, imp.length() - 2);
// }
//
// outgoing.add(imp);
// }
// }
//// return (outgoing.size() > 0) ? outgoing : null;
// return outgoing;
// }
imp = imp.substring(0, imp.length() - 2);
}
outgoing.add(imp);
}
}
return (outgoing.size() > 0) ? outgoing : null;
}
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
boolean setDeletionFlag(boolean flag) {
return setFlag(DELETION_FLAG, flag);
}
boolean isDeletionFlagged() {
return isDeletionFlagged(getFolder());
}
@@ -595,16 +608,16 @@ public abstract class LocalContribution extends Contribution {
static boolean isDeletionFlagged(File folder) {
return isFlagged(folder, DELETION_FLAG);
}
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
boolean setUpdateFlag(boolean flag) {
return setFlag(UPDATE_FLAGGED, flag);
}
boolean isUpdateFlagged() {
return isUpdateFlagged(getFolder());
}
@@ -613,24 +626,24 @@ public abstract class LocalContribution extends Contribution {
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()) {
@@ -638,7 +651,7 @@ public abstract class LocalContribution extends Contribution {
}
}
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
@@ -653,19 +666,19 @@ public abstract class LocalContribution extends Contribution {
return false;
}
} else {
return new File(getFolder(), flagFilename).delete();
return new File(getFolder(), flagFilename).delete();
}
}
static private boolean isFlagged(File folder, String flagFilename) {
return new File(folder, flagFilename).exists();
return new File(folder, flagFilename).exists();
}
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
/**
*
* @param base name of the class, with or without the package
+2 -1
View File
@@ -34,6 +34,7 @@ import org.apache.tools.ant.ProjectHelper;
import processing.app.*;
import processing.app.exec.ProcessHelper;
import processing.core.*;
import processing.data.StringList;
import processing.data.XML;
import processing.mode.java.preproc.*;
@@ -212,7 +213,7 @@ public class JavaBuild {
// figure out the contents of the code folder to see if there
// are files that need to be added to the imports
String[] codeFolderPackages = null;
StringList codeFolderPackages = null;
if (sketch.hasCodeFolder()) {
File codeFolder = sketch.getCodeFolder();
javaLibraryPath = codeFolder.getAbsolutePath();
@@ -22,6 +22,7 @@ import javax.swing.text.Document;
import org.eclipse.jdt.core.compiler.IProblem;
import processing.core.PApplet;
import processing.data.StringList;
import processing.app.*;
import processing.app.Toolkit;
import processing.app.contrib.AvailableContribution;
@@ -527,7 +528,7 @@ public class JavaEditor extends Editor {
* are to be added
* @return true if and only if any JMenuItems were added; false otherwise
*/
private boolean addLibReferencesToSubMenu(ArrayList<Library> libsList, JMenu subMenu) {
private boolean addLibReferencesToSubMenu(List<Library> libsList, JMenu subMenu) {
boolean isItemAdded = false;
Iterator<Library> iter = libsList.iterator();
while (iter.hasNext()) {
@@ -1265,16 +1266,18 @@ public class JavaEditor extends Editor {
// could also scan the text in the file to see if each import
// statement is already in there, but if the user has the import
// commented out, then this will be a problem.
String[] list = lib.getSpecifiedImports(); // ask the library for its imports
StringList list = lib.getImports(); // ask the library for its imports
if (list == null) {
// Default to old behavior and load each package in the primary jar
list = Base.packageListFromClassPath(lib.getJarPath());
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < list.length; i++) {
// for (int i = 0; i < list.length; i++) {
for (String item : list) {
sb.append("import ");
sb.append(list[i]);
// sb.append(list[i]);
sb.append(item);
sb.append(".*;\n");
}
sb.append('\n');
@@ -645,7 +645,7 @@ public class PdePreprocessor {
public PreprocessorResult write(Writer out, String program,
String codeFolderPackages[])
StringList codeFolderPackages)
throws SketchException, RecognitionException, TokenStreamException {
// these ones have the .* at the end, since a class name might be at the end
+6
View File
@@ -10,6 +10,12 @@ X Show "not compatible" error message in the manager
X https://github.com/processing/processing/issues/3386
X Add more code for handling low-level errors on startup
manager
X changed compatibleModesList to modes in examples.properties
X changed authorList to authors to keep in line w/ the others
_ need to make a note of these
_ should we change category to categories?
contribs
X Use correct localized strings in JavaEditor.java
X https://github.com/processing/processing/pull/3376