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:
joelmoniz
2014-07-22 14:38:28 +04:00
parent 2665a6f50c
commit 251acc6067
7 changed files with 259 additions and 316 deletions
@@ -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)) {