mirror of
https://github.com/processing/processing4.git
synced 2026-06-16 04:26:26 +02:00
Update on next restart if net isnt available during auto-update on restart
And some Spring Cleaning * Changed for-each to iterator * Removed a few redundant functions
This commit is contained in:
@@ -26,7 +26,6 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import processing.app.Base;
|
||||
import processing.app.Editor;
|
||||
import processing.core.PApplet;
|
||||
|
||||
|
||||
@@ -70,9 +69,12 @@ class AvailableContribution extends Contribution {
|
||||
* @param confirmReplace
|
||||
* true to open a dialog asking the user to confirm removing/moving
|
||||
* the library when a library by the same name already exists
|
||||
* @param status
|
||||
* the StatusPanel. Pass null if this function is called for an
|
||||
* install-on-startup
|
||||
* @return
|
||||
*/
|
||||
public LocalContribution install(Editor editor, File contribArchive,
|
||||
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
|
||||
@@ -83,7 +85,8 @@ class AvailableContribution extends Contribution {
|
||||
try {
|
||||
tempFolder = type.createTempFolder();
|
||||
} catch (IOException e) {
|
||||
status.setErrorMessage("Could not create a temporary folder to install.");
|
||||
if (status != null)
|
||||
status.setErrorMessage("Could not create a temporary folder to install.");
|
||||
return null;
|
||||
}
|
||||
Base.unzip(contribArchive, tempFolder);
|
||||
@@ -111,7 +114,8 @@ class AvailableContribution extends Contribution {
|
||||
tempFolder.renameTo(contribFolder);
|
||||
tempFolder = enclosingFolder;
|
||||
*/
|
||||
status.setErrorMessage(getName() + " needs to be repackaged according to the " + type.getTitle() + " guidelines.");
|
||||
if (status != null)
|
||||
status.setErrorMessage(getName() + " needs to be repackaged according to the " + type.getTitle() + " guidelines.");
|
||||
//status.setErrorMessage("This " + type + " needs to be repackaged according to the guidelines.");
|
||||
return null;
|
||||
}
|
||||
@@ -123,14 +127,15 @@ class AvailableContribution extends Contribution {
|
||||
LocalContribution installedContrib = null;
|
||||
|
||||
if (contribFolder == null) {
|
||||
status.setErrorMessage("Could not find a " + type + " in the downloaded file.");
|
||||
if (status != null)
|
||||
status.setErrorMessage("Could not find a " + type + " in the downloaded file.");
|
||||
|
||||
} else {
|
||||
File propFile = new File(contribFolder, type + ".properties");
|
||||
if (writePropertiesFile(propFile)) {
|
||||
// 1. contribFolder now has a legit contribution, load it to get info.
|
||||
LocalContribution newContrib =
|
||||
type.load(editor.getBase(), contribFolder);
|
||||
type.load(base, contribFolder);
|
||||
|
||||
// 1.1. get info we need to delete the newContrib folder later
|
||||
File newContribFolder = newContrib.getFolder();
|
||||
@@ -138,7 +143,7 @@ class AvailableContribution extends Contribution {
|
||||
// 2. Check to make sure nothing has the same name already,
|
||||
// backup old if needed, then move things into place and reload.
|
||||
installedContrib =
|
||||
newContrib.copyAndLoad(editor, confirmReplace, status);
|
||||
newContrib.copyAndLoad(base, confirmReplace, status);
|
||||
|
||||
// Restart no longer needed. Yay!
|
||||
// if (newContrib != null && type.requiresRestart()) {
|
||||
@@ -148,12 +153,10 @@ class AvailableContribution extends Contribution {
|
||||
|
||||
// 3.1 Unlock all the jars if it is a mode or tool
|
||||
if (newContrib.getType() == ContributionType.MODE) {
|
||||
((ModeContribution)newContrib).clearClassLoader(editor.getBase());
|
||||
System.out.println("ismode");
|
||||
((ModeContribution)newContrib).clearClassLoader(base);
|
||||
}
|
||||
else if (newContrib.getType() == ContributionType.TOOL) {
|
||||
((ToolContribution)newContrib).clearClassLoader(editor.getBase());
|
||||
System.out.println("istool");
|
||||
((ToolContribution)newContrib).clearClassLoader(base);
|
||||
}
|
||||
|
||||
// 3.2 Delete the newContrib, do a garbage collection, hope and pray
|
||||
@@ -176,7 +179,8 @@ class AvailableContribution extends Contribution {
|
||||
Base.removeDir(newContribFolder);
|
||||
|
||||
} else {
|
||||
status.setErrorMessage("Error overwriting .properties file.");
|
||||
if (status != null)
|
||||
status.setErrorMessage("Error overwriting .properties file.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,90 +192,6 @@ class AvailableContribution extends Contribution {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param contribArchive
|
||||
* a zip file containing the library to install
|
||||
* @return
|
||||
*/
|
||||
public LocalContribution installOnStartup(Base base, File contribArchive, 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
|
||||
// another file system, so move/rename operations will break.
|
||||
|
||||
File tempFolder = null;
|
||||
|
||||
try {
|
||||
tempFolder = type.createTempFolder();
|
||||
} catch (IOException e) {
|
||||
status.setErrorMessage("Could not create a temporary folder to install.");
|
||||
return null;
|
||||
}
|
||||
Base.unzip(contribArchive, tempFolder);
|
||||
|
||||
// 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.
|
||||
if (type.isCandidate(tempFolder)) {
|
||||
status.setErrorMessage(getName() + " needs to be repackaged according to the " + type.getTitle() + " guidelines.");
|
||||
return null;
|
||||
}
|
||||
|
||||
contribFolder = type.findCandidate(tempFolder);
|
||||
LocalContribution installedContrib = null;
|
||||
|
||||
if (contribFolder == null) {
|
||||
status.setErrorMessage("Could not find a " + type + " in the downloaded file.");
|
||||
|
||||
} else {
|
||||
File propFile = new File(contribFolder, type + ".properties");
|
||||
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,
|
||||
// backup old if needed, then move things into place and reload.
|
||||
installedContrib =
|
||||
newContrib.copyAndLoadOnStartup(base, status);
|
||||
|
||||
// 3. 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 2 seconds to finish up ... because file ops are
|
||||
// just that flaky on Windows.
|
||||
try {
|
||||
Thread.sleep(2000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Okay, now actually delete that temp folder
|
||||
Base.removeDir(newContribFolder);
|
||||
|
||||
} else {
|
||||
status.setErrorMessage("Error overwriting .properties file.");
|
||||
}
|
||||
}
|
||||
|
||||
// Remove any remaining ickies
|
||||
if (tempFolder.exists()) {
|
||||
Base.removeDir(tempFolder);
|
||||
}
|
||||
return installedContrib;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public boolean isInstalled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -23,11 +23,7 @@ package processing.app.contrib;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.*;
|
||||
|
||||
import processing.app.Base;
|
||||
import processing.app.Editor;
|
||||
@@ -43,8 +39,8 @@ public class ContributionManager {
|
||||
|
||||
|
||||
/**
|
||||
* Blocks until the file is downloaded or an error occurs.
|
||||
* Returns true if the file was successfully downloaded, false otherwise.
|
||||
* 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
|
||||
@@ -52,6 +48,9 @@ public class ContributionManager {
|
||||
* 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
|
||||
*/
|
||||
@@ -67,83 +66,48 @@ public class ContributionManager {
|
||||
conn.setRequestMethod("GET");
|
||||
conn.connect();
|
||||
|
||||
// TODO this is often -1, may need to set progress to indeterminate
|
||||
int fileSize = conn.getContentLength();
|
||||
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("contributions.progress.downloading"), fileSize);
|
||||
progress.startTask(Language.text("contributions.progress.downloading"), fileSize);
|
||||
}
|
||||
|
||||
InputStream in = conn.getInputStream();
|
||||
FileOutputStream out = new FileOutputStream(dest);
|
||||
|
||||
byte[] b = new byte[8192];
|
||||
int amount;
|
||||
int total = 0;
|
||||
while (!progress.isCanceled() && (amount = in.read(b)) != -1) {
|
||||
out.write(b, 0, amount);
|
||||
total += amount;
|
||||
progress.setProgress(total);
|
||||
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) {
|
||||
progress.error(ste);
|
||||
|
||||
if (progress != null)
|
||||
progress.error(ste);
|
||||
} catch (IOException ioe) {
|
||||
progress.error(ioe);
|
||||
if (progress != null)
|
||||
progress.error(ioe);
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
progress.finished();
|
||||
if (progress != null)
|
||||
progress.finished();
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Blocks until the file is downloaded or an error occurs.
|
||||
* Returns true if the file was successfully downloaded, false otherwise.
|
||||
* Used at startup for automatically downloading and installing.
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
static boolean download(URL source, File dest) {
|
||||
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();
|
||||
|
||||
InputStream in = conn.getInputStream();
|
||||
FileOutputStream out = new FileOutputStream(dest);
|
||||
|
||||
byte[] b = new byte[8192];
|
||||
int amount;
|
||||
while ((amount = in.read(b)) != -1) {
|
||||
out.write(b, 0, amount);
|
||||
}
|
||||
out.flush();
|
||||
out.close();
|
||||
success = true;
|
||||
|
||||
} catch (SocketTimeoutException ste) {
|
||||
// When there's no internet...
|
||||
// TODO: Will have to find a way to download later
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Non-blocking call to download and install a contribution in a new thread.
|
||||
*
|
||||
@@ -176,7 +140,7 @@ public class ContributionManager {
|
||||
if (!downloadProgress.isCanceled() && !downloadProgress.isError()) {
|
||||
installProgress.startTask("Installing...", ProgressMonitor.UNKNOWN);
|
||||
LocalContribution contribution =
|
||||
ad.install(editor, contribZip, false, status);
|
||||
ad.install(editor.getBase(), contribZip, false, status);
|
||||
|
||||
if (contribution != null) {
|
||||
contribListing.replaceContribution(ad, contribution);
|
||||
@@ -224,38 +188,27 @@ public class ContributionManager {
|
||||
contribZip.setWritable(true); // necessary?
|
||||
|
||||
try {
|
||||
download(url, contribZip);
|
||||
download(url, contribZip, null);
|
||||
|
||||
StatusPanel status = new StatusPanel();
|
||||
LocalContribution contribution = ad.installOnStartup(base,
|
||||
contribZip,
|
||||
status);
|
||||
LocalContribution contribution = ad.install(base, contribZip,
|
||||
false, null);
|
||||
|
||||
if (contribution != null) {
|
||||
contribListing.replaceContribution(ad, contribution);
|
||||
if (contribution.getType() == ContributionType.MODE) {
|
||||
ArrayList<ModeContribution> contribModes = base
|
||||
.getModeContribs();
|
||||
if (contribModes != null) {
|
||||
if (contribModes != null && !contribModes.contains(contribution)) {
|
||||
contribModes.add((ModeContribution) contribution);
|
||||
if (contribution.getType() == ContributionType.MODE
|
||||
&& base.getActiveEditor() != null) {
|
||||
ArrayList<ModeContribution> contribModesList = base
|
||||
.getModeContribs();
|
||||
if (!contribModesList.contains(contribution))
|
||||
contribModesList.add((ModeContribution) contribution);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (base.getActiveEditor() != null)
|
||||
refreshInstalled(base.getActiveEditor());
|
||||
}
|
||||
|
||||
System.out.println(status.getText());
|
||||
// if (contribution != null) {
|
||||
// contribListing.replaceContribution(ad, contribution);
|
||||
// }
|
||||
contribZip.delete();
|
||||
|
||||
handleUpdateFailedMarkers(ad, filename.substring(0, filename.lastIndexOf('.')));
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@@ -272,9 +225,34 @@ public class ContributionManager {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
try {
|
||||
new File(contribLocn, ac.getName()).createNewFile();
|
||||
} catch (IOException e) {
|
||||
// File already exists...
|
||||
//e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static public void refreshInstalled(Editor e) {
|
||||
List<Editor> editor = e.getBase().getEditors();
|
||||
for (Editor ed : editor) {
|
||||
|
||||
Iterator<Editor> iter = e.getBase().getEditors().iterator();
|
||||
while (iter.hasNext()) {
|
||||
Editor ed = iter.next();
|
||||
ed.getMode().rebuildImportMenu();
|
||||
ed.getMode().resetExamples();
|
||||
ed.rebuildToolMenu();
|
||||
@@ -340,6 +318,7 @@ public class ContributionManager {
|
||||
* Also updates all entries previously marked for update.
|
||||
*/
|
||||
static public void cleanup(Base base) throws Exception {
|
||||
|
||||
deleteTemp(Base.getSketchbookModesFolder());
|
||||
deleteTemp(Base.getSketchbookToolsFolder());
|
||||
|
||||
@@ -347,7 +326,9 @@ public class ContributionManager {
|
||||
deleteFlagged(Base.getSketchbookModesFolder());
|
||||
deleteFlagged(Base.getSketchbookToolsFolder());
|
||||
|
||||
updateFlagged(base, Base.getSketchbookLibrariesFolder());
|
||||
installPreviouslyFailed(base, Base.getSketchbookModesFolder());
|
||||
installPreviouslyFailed(base, Base.getSketchbookToolsFolder());
|
||||
|
||||
updateFlagged(base, Base.getSketchbookModesFolder());
|
||||
updateFlagged(base, Base.getSketchbookToolsFolder());
|
||||
|
||||
@@ -356,27 +337,40 @@ public class ContributionManager {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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<File> deleteList = new LinkedList<File>();
|
||||
|
||||
|
||||
for (File f : root.listFiles())
|
||||
if (f.getName().matches(root.getName().substring(0, 4) + "\\d*" + "tmp"))
|
||||
deleteList.add(f);
|
||||
|
||||
|
||||
Iterator<File> folderIter = deleteList.iterator();
|
||||
|
||||
while(folderIter.hasNext()) {
|
||||
|
||||
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));
|
||||
return (folder.isDirectory() && LocalContribution
|
||||
.isDeletionFlagged(folder));
|
||||
}
|
||||
});
|
||||
for (File folder : markedForDeletion) {
|
||||
@@ -385,38 +379,81 @@ public class ContributionManager {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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<AvailableContribution> iter = contribListing.advertisedContributions.iterator();
|
||||
while (iter.hasNext()) {
|
||||
AvailableContribution availableContrib = iter.next();
|
||||
if (file.getName().equals(availableContrib.getName())) {
|
||||
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));
|
||||
return (folder.isDirectory() && LocalContribution
|
||||
.isUpdateFlagged(folder));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
ArrayList<String> updateContribsNames = new ArrayList<String>();
|
||||
LinkedList<AvailableContribution> updateContribsList = new LinkedList<AvailableContribution>();
|
||||
|
||||
|
||||
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<String, String> properties = Base.readSettings(new File(folder, propFileName));
|
||||
HashMap<String, String> properties = Base
|
||||
.readSettings(new File(folder, propFileName));
|
||||
updateContribsNames.add(properties.get("name"));
|
||||
Base.removeDir(folder);
|
||||
}
|
||||
for (AvailableContribution availableContribs : contribListing.advertisedContributions) {
|
||||
if(updateContribsNames.contains(availableContribs.getName())) {
|
||||
|
||||
Iterator<AvailableContribution> iter = contribListing.advertisedContributions.iterator();
|
||||
while (iter.hasNext()) {
|
||||
AvailableContribution availableContribs = iter.next();
|
||||
if (updateContribsNames.contains(availableContribs.getName())) {
|
||||
updateContribsList.add(availableContribs);
|
||||
}
|
||||
}
|
||||
for (AvailableContribution contribToUpdate : updateContribsList) {
|
||||
|
||||
Iterator<AvailableContribution> iter2 = updateContribsList.iterator();
|
||||
while (iter2.hasNext()) {
|
||||
AvailableContribution contribToUpdate = iter2.next();
|
||||
installOnStartUp(base, contribToUpdate);
|
||||
contribListing.replaceContribution(contribToUpdate, contribToUpdate);
|
||||
}
|
||||
|
||||
@@ -95,7 +95,9 @@ public class ContributionManagerDialog {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent arg0) {
|
||||
|
||||
for (Editor ed : editor.getBase().getEditors())
|
||||
Iterator<Editor> iter = editor.getBase().getEditors().iterator();
|
||||
while (iter.hasNext()) {
|
||||
Editor ed = iter.next();
|
||||
if (ed.getSketch().isModified() || ed.getSketch().isUntitled()) {
|
||||
int option = Base
|
||||
.showYesNoQuestion(editor, title,
|
||||
@@ -107,6 +109,7 @@ public class ContributionManagerDialog {
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Thanks to http://stackoverflow.com/a/4160543
|
||||
StringBuilder cmd = new StringBuilder();
|
||||
|
||||
@@ -26,7 +26,7 @@ import java.awt.event.*;
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.Date;
|
||||
@@ -133,9 +133,10 @@ class ContributionPanel extends JPanel {
|
||||
LocalContribution installed = (LocalContribution) contrib;
|
||||
installed.setDeletionFlag(false);
|
||||
contribListing.replaceContribution(contrib, contrib); // ??
|
||||
ArrayList<Contribution> contribsList = contribListing.allContributions;
|
||||
Iterator<Contribution> contribsListIter = contribListing.allContributions.iterator();
|
||||
boolean toBeRestarted = false;
|
||||
for(Contribution contribElement : contribsList)
|
||||
while (contribsListIter.hasNext()) {
|
||||
Contribution contribElement = contribsListIter.next();
|
||||
if (contrib.getType().equals(contribElement.getType())) {
|
||||
if (contribElement.isDeletionFlagged() || contribElement.isUpdateFlagged())
|
||||
{
|
||||
@@ -143,6 +144,7 @@ class ContributionPanel extends JPanel {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
listPanel.contribManager.restartButton.setVisible(toBeRestarted);
|
||||
}
|
||||
}
|
||||
@@ -399,6 +401,7 @@ class ContributionPanel extends JPanel {
|
||||
|
||||
JPanel updateBox = new JPanel();
|
||||
updateBox.setLayout(new BorderLayout());
|
||||
updateBox.setInheritsPopupMenu(true);
|
||||
updateBox.add(notificationBlock, BorderLayout.WEST);
|
||||
updateBox.setBorder(new EmptyBorder(4, 7, 7, 7));
|
||||
updateBox.setOpaque(false);
|
||||
@@ -412,26 +415,24 @@ class ContributionPanel extends JPanel {
|
||||
add(rightPane, BorderLayout.EAST);
|
||||
|
||||
|
||||
if (updateButton.isVisible() && !isRemoveInProgress && !contrib.isDeletionFlagged()) {//installRemoveButton.getText().equals("Remove") &&
|
||||
if (updateButton.isVisible() && !isRemoveInProgress && !contrib.isDeletionFlagged()) {
|
||||
JPanel updateRemovePanel = new JPanel();
|
||||
updateRemovePanel.setLayout(new FlowLayout());
|
||||
updateRemovePanel.setOpaque(false);
|
||||
updateRemovePanel.add(updateButton);
|
||||
updateRemovePanel.setInheritsPopupMenu(true);
|
||||
updateRemovePanel.add(installRemoveButton);
|
||||
updateBox.add(updateRemovePanel, BorderLayout.EAST);
|
||||
|
||||
JPanel barPane = new JPanel();
|
||||
barPane.setOpaque(false);
|
||||
barPane.setInheritsPopupMenu(true);
|
||||
barPane.add(installProgressBar);
|
||||
rightPane.add(barPane);
|
||||
|
||||
if (isUpdateInProgress)
|
||||
((CardLayout) barButtonCardPane.getLayout()).show(barButtonCardPane, PROGRESS_BAR_CONSTRAINT);
|
||||
|
||||
// barButtonCardPane.removeAll();
|
||||
// barButtonCardPane.add(barPane, PROGRESS_BAR_CONSTRAINT);
|
||||
// ((CardLayout) barButtonCardPane.getLayout()).show(barButtonCardPane, PROGRESS_BAR_CONSTRAINT);
|
||||
// rightPane.add(barButtonCardPane);
|
||||
|
||||
}
|
||||
else {
|
||||
updateBox.add(updateButton, BorderLayout.EAST);
|
||||
@@ -439,10 +440,12 @@ class ContributionPanel extends JPanel {
|
||||
|
||||
JPanel barPane = new JPanel();
|
||||
barPane.setOpaque(false);
|
||||
barPane.setInheritsPopupMenu(true);
|
||||
barPane.add(installProgressBar);
|
||||
|
||||
JPanel buttonPane = new JPanel();
|
||||
buttonPane.setOpaque(false);
|
||||
buttonPane.setInheritsPopupMenu(true);
|
||||
buttonPane.add(installRemoveButton);
|
||||
|
||||
barButtonCardPane.add(buttonPane, BUTTON_CONSTRAINT);
|
||||
@@ -624,8 +627,6 @@ class ContributionPanel extends JPanel {
|
||||
installRemoveButton.setText(Language.text("contributions.install"));
|
||||
}
|
||||
|
||||
// reorganizePaneComponents();
|
||||
|
||||
contextMenu.removeAll();
|
||||
|
||||
if (contrib.isInstalled()) {
|
||||
|
||||
@@ -195,104 +195,90 @@ public abstract class LocalContribution extends Contribution {
|
||||
// }
|
||||
|
||||
|
||||
LocalContribution copyAndLoad(Editor editor,
|
||||
LocalContribution copyAndLoad(Base base,
|
||||
boolean confirmReplace,
|
||||
StatusPanel status) {
|
||||
ArrayList<LocalContribution> oldContribs =
|
||||
getType().listContributions(editor);
|
||||
// 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 =
|
||||
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()))) {
|
||||
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<br>"+
|
||||
"has been found in your sketchbook. Clicking “Yes”<br>"+
|
||||
"will move the existing library to a backup folder<br>" +
|
||||
"in <i>libraries/old</i> 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<br>"+
|
||||
"has been found in your sketchbook. Clicking “Yes”<br>"+
|
||||
"will permanently delete this library and all of its contents<br>"+
|
||||
"before replacing it.");
|
||||
if (result != JOptionPane.YES_OPTION || !oldContrib.getFolder().delete()) {
|
||||
return null;
|
||||
}
|
||||
if (oldContrib.getType().requiresRestart()) {
|
||||
// XXX: We can't replace stuff, soooooo.... do something different
|
||||
if (!oldContrib.backup(editor, false, status)) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
if ((doBackup && !oldContrib.backup(editor, true, status)) ||
|
||||
(!doBackup && !oldContrib.getFolder().delete())) {
|
||||
return null;
|
||||
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<br>"+
|
||||
"has been found in your sketchbook. Clicking “Yes”<br>"+
|
||||
"will move the existing library to a backup folder<br>" +
|
||||
"in <i>libraries/old</i> 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<br>"+
|
||||
"has been found in your sketchbook. Clicking “Yes”<br>"+
|
||||
"will permanently delete this library and all of its contents<br>"+
|
||||
"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);
|
||||
// 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(editor.getBase(), contribFolder);
|
||||
}
|
||||
|
||||
|
||||
LocalContribution copyAndLoadOnStartup(Base base, StatusPanel status) {
|
||||
|
||||
String contribFolderName = getFolder().getName();
|
||||
|
||||
File contribTypeFolder = getType().getSketchbookFolder();
|
||||
File contribFolder = new File(contribTypeFolder, contribFolderName);
|
||||
|
||||
// This if should ideally never happen, since this function is to be called only when restarting on update
|
||||
if (contribFolder.exists()) {
|
||||
Base.removeDir(contribFolder);
|
||||
}
|
||||
|
||||
|
||||
File oldFolder = getFolder();
|
||||
|
||||
try {
|
||||
@@ -317,7 +303,6 @@ public abstract class LocalContribution extends Contribution {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Moves the given contribution to a backup folder.
|
||||
* @param deleteOriginal
|
||||
@@ -367,8 +352,11 @@ public abstract class LocalContribution extends Contribution {
|
||||
}).start();
|
||||
}
|
||||
|
||||
void remove(final Editor editor, final ProgressMonitor pm,
|
||||
final StatusPanel status, final ContributionListing contribListing) {
|
||||
|
||||
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");
|
||||
@@ -383,11 +371,14 @@ public abstract class LocalContribution extends Contribution {
|
||||
if (getType() == ContributionType.MODE) {
|
||||
boolean isModeActive = false;
|
||||
ModeContribution m = (ModeContribution) this;
|
||||
for (Editor e : editor.getBase().getEditors())
|
||||
Iterator<Editor> 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 {
|
||||
@@ -401,8 +392,11 @@ public abstract class LocalContribution extends Contribution {
|
||||
}
|
||||
if (getType() == ContributionType.TOOL) {
|
||||
ToolContribution t = (ToolContribution) this;
|
||||
for (Editor ed : editor.getBase().getEditors())
|
||||
Iterator<Editor> iter = editor.getBase().getEditors().iterator();
|
||||
while (iter.hasNext()) {
|
||||
Editor ed = iter.next();
|
||||
ed.clearToolMenu();
|
||||
}
|
||||
t.clearClassLoader(editor.getBase());
|
||||
}
|
||||
if (doBackup) {
|
||||
|
||||
@@ -21,17 +21,13 @@
|
||||
*/
|
||||
package processing.app.contrib;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.*;
|
||||
|
||||
import javax.swing.JRadioButtonMenuItem;
|
||||
|
||||
import processing.app.Base;
|
||||
import processing.app.Editor;
|
||||
import processing.app.Mode;
|
||||
|
||||
|
||||
@@ -77,6 +73,7 @@ public class ModeContribution extends LocalContribution {
|
||||
private ModeContribution(Base base, File folder,
|
||||
String className) throws Exception {
|
||||
super(folder);
|
||||
|
||||
className = initLoader(className);
|
||||
if (className != null) {
|
||||
Class<?> modeClass = loader.loadClass(className);
|
||||
@@ -90,26 +87,16 @@ public class ModeContribution extends LocalContribution {
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to close the ClassLoader so that the archives are no longer "locked" and
|
||||
* a mode can be removed without restart.
|
||||
* 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<ModeContribution> 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);
|
||||
/* List<Editor> editorList = base.getEditors();
|
||||
for (Editor editor : editorList) {
|
||||
Component[] j = editor.getModeMenu().getPopupMenu().getComponents();
|
||||
for (Component component : j) {
|
||||
JRadioButtonMenuItem cbmi = null;
|
||||
if (component instanceof JRadioButtonMenuItem) {
|
||||
cbmi = (JRadioButtonMenuItem) component;
|
||||
if (cbmi.getText().equals(mode.toString()))
|
||||
editor.getModeMenu().getPopupMenu().remove(component);
|
||||
}
|
||||
}
|
||||
} */
|
||||
|
||||
try {
|
||||
((URLClassLoader) loader).close();
|
||||
// The typecast should be safe, since the only case when loader is not of
|
||||
|
||||
@@ -76,8 +76,9 @@ public class ToolContribution extends LocalContribution implements Tool {
|
||||
} catch (IOException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
List<Editor> editors = base.getEditors();
|
||||
for (Editor editor : editors) {
|
||||
Iterator<Editor> editorIter = base.getEditors().iterator();
|
||||
while (editorIter.hasNext()) {
|
||||
Editor editor = editorIter.next();
|
||||
ArrayList<ToolContribution> contribTools = editor.contribTools;
|
||||
for (ToolContribution toolContrib : contribTools)
|
||||
if (toolContrib.getName().equals(this.name)) {
|
||||
|
||||
Reference in New Issue
Block a user