Experiment with new CachedResource framework

This commit is contained in:
Reinhard Pointner 2016-03-07 12:30:12 +00:00
parent c5c8525b49
commit 95ce706e2e
4 changed files with 83 additions and 124 deletions

View File

@ -1,22 +1,23 @@
package net.filebot; package net.filebot;
import static java.awt.GraphicsEnvironment.*; import static java.awt.GraphicsEnvironment.*;
import static java.util.stream.Collectors.*;
import static javax.swing.JOptionPane.*; import static javax.swing.JOptionPane.*;
import static net.filebot.Logging.*; import static net.filebot.Logging.*;
import static net.filebot.Settings.*; import static net.filebot.Settings.*;
import static net.filebot.util.FileUtilities.*; import static net.filebot.util.FileUtilities.*;
import static net.filebot.util.XPathUtilities.*;
import static net.filebot.util.ui.SwingUI.*; import static net.filebot.util.ui.SwingUI.*;
import java.awt.Desktop; import java.awt.Desktop;
import java.awt.Dialog.ModalityType; import java.awt.Dialog.ModalityType;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter; import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent; import java.awt.event.WindowEvent;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.URI; import java.net.URI;
import java.nio.ByteBuffer; import java.net.URL;
import java.nio.channels.Channels; import java.nio.channels.Channels;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
import java.nio.file.StandardOpenOption; import java.nio.file.StandardOpenOption;
@ -26,14 +27,11 @@ import java.security.PermissionCollection;
import java.security.Permissions; import java.security.Permissions;
import java.security.Policy; import java.security.Policy;
import java.security.ProtectionDomain; import java.security.ProtectionDomain;
import java.util.Locale; import java.util.Map;
import java.util.Properties;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.stream.Stream; import java.util.stream.Stream;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JDialog; import javax.swing.JDialog;
import javax.swing.JFrame; import javax.swing.JFrame;
import javax.swing.JLabel; import javax.swing.JLabel;
@ -41,7 +39,6 @@ import javax.swing.JOptionPane;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import javax.swing.UIManager; import javax.swing.UIManager;
import javax.xml.parsers.DocumentBuilderFactory;
import net.filebot.cli.ArgumentBean; import net.filebot.cli.ArgumentBean;
import net.filebot.cli.ArgumentProcessor; import net.filebot.cli.ArgumentProcessor;
@ -54,14 +51,12 @@ import net.filebot.ui.MainFrame;
import net.filebot.ui.PanelBuilder; import net.filebot.ui.PanelBuilder;
import net.filebot.ui.SinglePanelFrame; import net.filebot.ui.SinglePanelFrame;
import net.filebot.ui.transfer.FileTransferable; import net.filebot.ui.transfer.FileTransferable;
import net.filebot.util.ByteBufferInputStream;
import net.filebot.util.PreferencesMap.PreferencesEntry; import net.filebot.util.PreferencesMap.PreferencesEntry;
import net.filebot.util.TeePrintStream; import net.filebot.util.TeePrintStream;
import net.filebot.web.CachedResource;
import net.miginfocom.swing.MigLayout; import net.miginfocom.swing.MigLayout;
import org.kohsuke.args4j.CmdLineException; import org.kohsuke.args4j.CmdLineException;
import org.w3c.dom.NodeList; import org.w3c.dom.Document;
public class Main { public class Main {
@ -276,74 +271,41 @@ public class Main {
* Show update notifications if updates are available * Show update notifications if updates are available
*/ */
private static void checkUpdate() throws Exception { private static void checkUpdate() throws Exception {
final Properties updateProperties = new CachedResource<Properties>(getApplicationProperty("update.url"), Properties.class, CachedResource.ONE_WEEK, 0, 0) { Cache cache = Cache.getCache(getApplicationName(), CacheType.Persistent);
Document dom = cache.xml("update.url", s -> new URL(getApplicationProperty(s)), Cache.ONE_WEEK).get();
@Override // parse update xml
public Properties process(ByteBuffer data) { final Map<String, String> update = streamChildren(dom.getFirstChild()).collect(toMap(n -> n.getNodeName(), n -> n.getTextContent().trim()));
try {
Properties properties = new Properties();
NodeList fields = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new ByteBufferInputStream(data)).getFirstChild().getChildNodes();
for (int i = 0; i < fields.getLength(); i++) {
properties.setProperty(fields.item(i).getNodeName(), fields.item(i).getTextContent().trim());
}
return properties;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}.get();
// check if update is required // check if update is required
int latestRev = Integer.parseInt(updateProperties.getProperty("revision")); int latestRev = Integer.parseInt(update.get("revision"));
int currentRev = getApplicationRevisionNumber(); int currentRev = getApplicationRevisionNumber();
if (latestRev > currentRev && currentRev > 0) { if (latestRev > currentRev && currentRev > 0) {
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(() -> {
final JDialog dialog = new JDialog(JFrame.getFrames()[0], update.get("title"), ModalityType.APPLICATION_MODAL);
final JPanel pane = new JPanel(new MigLayout("fill, nogrid, insets dialog"));
dialog.setContentPane(pane);
@Override pane.add(new JLabel(ResourceManager.getIcon("window.icon.medium")), "aligny top");
public void run() { pane.add(new JLabel(update.get("message")), "gap 10, wrap paragraph:push");
final JDialog dialog = new JDialog(JFrame.getFrames()[0], updateProperties.getProperty("title"), ModalityType.APPLICATION_MODAL);
final JPanel pane = new JPanel(new MigLayout("fill, nogrid, insets dialog"));
dialog.setContentPane(pane);
pane.add(new JLabel(ResourceManager.getIcon("window.icon.medium")), "aligny top"); pane.add(newButton("Download", ResourceManager.getIcon("dialog.continue"), evt -> {
pane.add(new JLabel(updateProperties.getProperty("message")), "gap 10, wrap paragraph:push"); openURI(update.get("download"));
pane.add(new JButton(new AbstractAction("Download", ResourceManager.getIcon("dialog.continue")) { dialog.setVisible(false);
}), "tag ok");
@Override pane.add(newButton("Details", ResourceManager.getIcon("action.report"), evt -> {
public void actionPerformed(ActionEvent evt) { openURI(update.get("discussion"));
try { }), "tag help2");
Desktop.getDesktop().browse(URI.create(updateProperties.getProperty("download")));
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
dialog.setVisible(false);
}
}
}), "tag ok");
pane.add(new JButton(new AbstractAction("Details", ResourceManager.getIcon("action.report")) {
@Override pane.add(newButton("Ignore", ResourceManager.getIcon("dialog.cancel"), evt -> {
public void actionPerformed(ActionEvent evt) { dialog.setVisible(false);
try { }), "tag cancel");
Desktop.getDesktop().browse(URI.create(updateProperties.getProperty("discussion")));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}), "tag help2");
pane.add(new JButton(new AbstractAction("Ignore", ResourceManager.getIcon("dialog.cancel")) {
@Override dialog.pack();
public void actionPerformed(ActionEvent evt) { dialog.setLocation(getOffsetLocation(dialog.getOwner()));
dialog.setVisible(false); dialog.setVisible(true);
}
}), "tag cancel");
dialog.pack();
dialog.setLocation(getOffsetLocation(dialog.getOwner()));
dialog.setVisible(true);
}
}); });
} }
} }
@ -357,9 +319,8 @@ public class Main {
started.setValue("1"); started.setValue("1");
started.flush(); started.flush();
SwingUtilities.invokeLater(() -> { // open Getting Started
GettingStartedStage.start(); SwingUtilities.invokeLater(() -> GettingStartedStage.start());
});
} }
} }
@ -371,18 +332,14 @@ public class Main {
return; return;
} }
String message = String.format(Locale.ROOT, "<html><p style='font-size:16pt; font-weight:bold'>Thank you for using FileBot!</p><br><p>It has taken many nights to develop this application. If you enjoy using it,<br>please consider a donation to me and my work. It will help to<br>make FileBot even better!<p><p style='font-size:14pt; font-weight:bold'>You've renamed %,d files.</p><br><html>", HistorySpooler.getInstance().getPersistentHistoryTotalSize()); String message = String.format("<html><p style='font-size:16pt; font-weight:bold'>Thank you for using FileBot!</p><br><p>It has taken many nights to develop this application. If you enjoy using it,<br>please consider a donation to me and my work. It will help to<br>make FileBot even better!<p><p style='font-size:14pt; font-weight:bold'>You've renamed %,d files.</p><br><html>", HistorySpooler.getInstance().getPersistentHistoryTotalSize());
String[] actions = new String[] { "Donate! :)", donationRev > 0 ? "Not this time" : "Later" }; String[] actions = { "Donate! :)", donationRev > 0 ? "Not this time" : "Later" };
JOptionPane pane = new JOptionPane(message, INFORMATION_MESSAGE, YES_NO_OPTION, ResourceManager.getIcon("message.donate"), actions, actions[0]); JOptionPane pane = new JOptionPane(message, INFORMATION_MESSAGE, YES_NO_OPTION, ResourceManager.getIcon("message.donate"), actions, actions[0]);
pane.createDialog(null, "Please Donate").setVisible(true); pane.createDialog(null, "Please Donate").setVisible(true);
if (pane.getValue() == actions[0]) { if (pane.getValue() == actions[0]) {
try { openURI(getDonateURL());
Desktop.getDesktop().browse(new URI(getDonateURL())); donation.setValue(String.valueOf(currentRev));
} catch (Exception e) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, "Failed to browse URI", e);
} finally {
donation.setValue(String.valueOf(currentRev));
}
} else { } else {
if (donationRev > 0 && donationRev < currentRev) { if (donationRev > 0 && donationRev < currentRev) {
donation.setValue(String.valueOf(currentRev)); donation.setValue(String.valueOf(currentRev));
@ -401,16 +358,20 @@ public class Main {
int currentRev = getApplicationRevisionNumber(); int currentRev = getApplicationRevisionNumber();
donation.setValue(String.valueOf(currentRev)); donation.setValue(String.valueOf(currentRev));
String message = String.format(Locale.ROOT, "<html><p style='font-size:16pt; font-weight:bold'>Thank you for using FileBot!</p><br><p>It has taken many nights to develop this application. If you enjoy using it,<br>please consider writing a nice little review on the %s.<p><p style='font-size:14pt; font-weight:bold'>You've renamed %,d files.</p><br><html>", getAppStoreName(), HistorySpooler.getInstance().getPersistentHistoryTotalSize()); String message = String.format("<html><p style='font-size:16pt; font-weight:bold'>Thank you for using FileBot!</p><br><p>It has taken many nights to develop this application. If you enjoy using it,<br>please consider writing a nice little review on the %s.<p><p style='font-size:14pt; font-weight:bold'>You've renamed %,d files.</p><br><html>", getAppStoreName(), HistorySpooler.getInstance().getPersistentHistoryTotalSize());
String[] actions = new String[] { "Review! I like FileBot. :)", "Never! Don't bother me again." }; String[] actions = { "Review! I like FileBot. :)", "Never! Don't bother me again." };
JOptionPane pane = new JOptionPane(message, INFORMATION_MESSAGE, YES_NO_OPTION, ResourceManager.getIcon("window.icon.large"), actions, actions[0]); JOptionPane pane = new JOptionPane(message, INFORMATION_MESSAGE, YES_NO_OPTION, ResourceManager.getIcon("window.icon.large"), actions, actions[0]);
pane.createDialog(null, "Please rate FileBot").setVisible(true); pane.createDialog(null, "Please rate FileBot").setVisible(true);
if (pane.getValue() == actions[0]) { if (pane.getValue() == actions[0]) {
try { openURI(getAppStoreLink());
Desktop.getDesktop().browse(getAppStoreURI()); // this will naturally only work on Mac or Ubuntu ;) }
} catch (Exception e) { }
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, "Failed to browse URI", e);
} private static void openURI(String uri) {
try {
Desktop.getDesktop().browse(URI.create(uri));
} catch (Exception e) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, "Failed to open URI: " + uri, e);
} }
} }

View File

@ -5,7 +5,6 @@ import static net.filebot.util.StringUtilities.*;
import java.awt.GraphicsEnvironment; import java.awt.GraphicsEnvironment;
import java.io.File; import java.io.File;
import java.net.URI;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
@ -198,11 +197,11 @@ public final class Settings {
return null; return null;
} }
public static URI getAppStoreURI() { public static String getAppStoreLink() {
if (isMacApp()) if (isMacApp())
return getApplicationLink("link.mas"); return getApplicationProperty("link.mas");
if (isUbuntuApp()) if (isUbuntuApp())
return getApplicationLink("link.usc"); return getApplicationProperty("link.usc");
return null; return null;
} }
@ -216,30 +215,27 @@ public final class Settings {
return getApplicationProperty("link.app.help") + '#' + getApplicationDeployment(); return getApplicationProperty("link.app.help") + '#' + getApplicationDeployment();
} }
public static Map<String, URI> getHelpURIs() { public static Map<String, String> getHelpURIs() {
Map<String, URI> links = new LinkedHashMap<String, URI>(); Map<String, String> links = new LinkedHashMap<String, String>();
links.put("Getting Started", getApplicationLink("link.intro"));
links.put("FAQ", getApplicationLink("link.faq")); links.put("Getting Started", getApplicationProperty("link.intro"));
links.put("Forums", getApplicationLink("link.forums")); links.put("FAQ", getApplicationProperty("link.faq"));
links.put("Forums", getApplicationProperty("link.forums"));
if (isMacSandbox()) { if (isMacSandbox()) {
links.put("Report Bugs", getApplicationLink("link.help.mas")); links.put("Report Bugs", getApplicationProperty("link.help.mas"));
links.put("Request Help", getApplicationLink("link.help.mas")); links.put("Request Help", getApplicationProperty("link.help.mas"));
} else { } else {
links.put("Report Bugs", getApplicationLink("link.bugs")); links.put("Report Bugs", getApplicationProperty("link.bugs"));
links.put("Request Help", getApplicationLink("link.help")); links.put("Request Help", getApplicationProperty("link.help"));
} }
links.put("Contact us on Twitter", getApplicationLink("link.twitter")); links.put("Contact us on Twitter", getApplicationProperty("link.twitter"));
links.put("Contact us on Facebook", getApplicationLink("link.facebook")); links.put("Contact us on Facebook", getApplicationProperty("link.facebook"));
return links; return links;
} }
public static URI getApplicationLink(String key) {
return URI.create(getApplicationProperty(key));
}
public static Settings forPackage(Class<?> type) { public static Settings forPackage(Class<?> type) {
return new Settings(Preferences.userNodeForPackage(type)); return new Settings(Preferences.userNodeForPackage(type));
} }

View File

@ -1,17 +1,16 @@
package net.filebot.ui; package net.filebot.ui;
import static net.filebot.util.ui.SwingUI.*;
import java.awt.Desktop; import java.awt.Desktop;
import java.awt.event.ActionEvent;
import java.net.URI; import java.net.URI;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.swing.AbstractAction;
import javax.swing.Action; import javax.swing.Action;
import javax.swing.JMenu; import javax.swing.JMenu;
import javax.swing.JMenuBar; import javax.swing.JMenuBar;
import net.filebot.Main;
import net.filebot.Settings; import net.filebot.Settings;
public class FileBotMenuBar { public class FileBotMenuBar {
@ -19,7 +18,7 @@ public class FileBotMenuBar {
public static JMenuBar createHelp() { public static JMenuBar createHelp() {
JMenu help = new JMenu("Help"); JMenu help = new JMenu("Help");
Settings.getHelpURIs().forEach((title, uri) -> { Settings.getHelpURIs().forEach((title, uri) -> {
help.add(createLink(title, uri)); help.add(createLink(title, URI.create(uri)));
}); });
JMenuBar menuBar = new JMenuBar(); JMenuBar menuBar = new JMenuBar();
@ -28,17 +27,13 @@ public class FileBotMenuBar {
} }
private static Action createLink(final String title, final URI uri) { private static Action createLink(final String title, final URI uri) {
return new AbstractAction(title) { return newAction(title, null, evt -> {
try {
@Override Desktop.getDesktop().browse(uri);
public void actionPerformed(ActionEvent evt) { } catch (Exception e) {
try { Logger.getLogger(FileBotMenuBar.class.getName()).log(Level.SEVERE, "Failed to open URI: " + uri, e);
Desktop.getDesktop().browse(uri);
} catch (Exception e) {
Logger.getLogger(Main.class.getName()).log(Level.WARNING, "Failed to browse URI", e);
}
} }
}; });
} }
} }

View File

@ -3,6 +3,8 @@ package net.filebot.util;
import java.util.AbstractList; import java.util.AbstractList;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import javax.xml.namespace.QName; import javax.xml.namespace.QName;
import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathConstants;
@ -140,11 +142,12 @@ public final class XPathUtilities {
} }
} }
/** public static Stream<Node> streamChildren(Node parent) {
* Dummy constructor to prevent instantiation. return stream(parent.getChildNodes());
*/ }
private XPathUtilities() {
throw new UnsupportedOperationException(); public static Stream<Node> stream(NodeList nodes) {
return IntStream.range(0, nodes.getLength()).mapToObj(nodes::item);
} }
protected static class NodeListDecorator extends AbstractList<Node> { protected static class NodeListDecorator extends AbstractList<Node> {
@ -167,4 +170,8 @@ public final class XPathUtilities {
} }
private XPathUtilities() {
throw new UnsupportedOperationException();
}
} }