From a097daf079965e5cd064658d4438beeeb7c9f9fb Mon Sep 17 00:00:00 2001 From: Reinhard Pointner Date: Fri, 30 Dec 2011 10:35:26 +0000 Subject: [PATCH] * improved fault-tolerance for fetch banner script * santize Groovy stack trace --- .../filebot/cli/ArgumentProcessor.java | 5 +- .../sourceforge/filebot/cli/CLILogging.java | 14 ++-- .../sourceforge/filebot/cli/ScriptShell.java | 37 +++++----- .../filebot/web/TheTVDBClient.java | 72 ++++++++++++++----- website/scripts/artwork.tvdb.groovy | 5 +- 5 files changed, 89 insertions(+), 44 deletions(-) diff --git a/source/net/sourceforge/filebot/cli/ArgumentProcessor.java b/source/net/sourceforge/filebot/cli/ArgumentProcessor.java index 4b56bd04..47a621f8 100644 --- a/source/net/sourceforge/filebot/cli/ArgumentProcessor.java +++ b/source/net/sourceforge/filebot/cli/ArgumentProcessor.java @@ -10,6 +10,7 @@ import java.io.File; import java.security.AccessController; import java.util.LinkedHashSet; import java.util.Set; +import java.util.logging.Level; import javax.script.Bindings; import javax.script.SimpleBindings; @@ -93,8 +94,8 @@ public class ArgumentProcessor { CLILogger.finest("Done ヾ(@⌒ー⌒@)ノ"); return 0; - } catch (Exception e) { - CLILogger.severe(String.format("%s: %s", getRootCause(e).getClass().getSimpleName(), getRootCauseMessage(e))); + } catch (Throwable e) { + CLILogger.log(Level.SEVERE, String.format("%s: %s", getRootCause(e).getClass().getSimpleName(), getRootCauseMessage(e)), getRootCause(e)); CLILogger.finest("Failure (°_°)"); return -1; } diff --git a/source/net/sourceforge/filebot/cli/CLILogging.java b/source/net/sourceforge/filebot/cli/CLILogging.java index 5c271680..8970f57c 100644 --- a/source/net/sourceforge/filebot/cli/CLILogging.java +++ b/source/net/sourceforge/filebot/cli/CLILogging.java @@ -4,6 +4,7 @@ package net.sourceforge.filebot.cli; import static java.lang.System.*; +import java.io.PrintStream; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.LogRecord; @@ -14,7 +15,7 @@ class CLILogging extends Handler { public static final Logger CLILogger = createCommandlineLogger("net.sourceforge.filebot.cli"); - + private static Logger createCommandlineLogger(String name) { Logger log = Logger.getLogger(name); log.setLevel(Level.ALL); @@ -28,13 +29,16 @@ class CLILogging extends Handler { return log; } - + @Override public void publish(LogRecord record) { if (record.getLevel().intValue() <= getLevel().intValue()) return; - // print messages to stdout + // use either System.out or System.err depending on the severity of the error + PrintStream out = record.getLevel().intValue() < Level.WARNING.intValue() ? System.out : System.err; + + // print messages out.println(record.getMessage()); if (record.getThrown() != null) { record.getThrown().printStackTrace(out); @@ -44,13 +48,13 @@ class CLILogging extends Handler { out.flush(); } - + @Override public void close() throws SecurityException { } - + @Override public void flush() { out.flush(); diff --git a/source/net/sourceforge/filebot/cli/ScriptShell.java b/source/net/sourceforge/filebot/cli/ScriptShell.java index 0d5f9b4b..ba7a8034 100644 --- a/source/net/sourceforge/filebot/cli/ScriptShell.java +++ b/source/net/sourceforge/filebot/cli/ScriptShell.java @@ -29,6 +29,7 @@ import javax.script.SimpleBindings; import javax.script.SimpleScriptContext; import org.codehaus.groovy.jsr223.GroovyScriptEngineFactory; +import org.codehaus.groovy.runtime.StackTraceUtils; import net.sourceforge.filebot.MediaTypes; import net.sourceforge.filebot.WebServices; @@ -92,7 +93,7 @@ class ScriptShell { } - public Object run(URL scriptLocation, Bindings bindings) throws Exception { + public Object run(URL scriptLocation, Bindings bindings) throws Throwable { if (scriptLocation.getProtocol().equals("file")) { return run(new File(scriptLocation.toURI()), bindings); } @@ -109,27 +110,31 @@ class ScriptShell { } - public Object run(File scriptFile, Bindings bindings) throws Exception { + public Object run(File scriptFile, Bindings bindings) throws Throwable { String script = readAll(new InputStreamReader(new FileInputStream(scriptFile), "UTF-8")); return evaluate(script, bindings); } - public Object evaluate(final String script, final Bindings bindings) throws Exception { - if (trustScript) { - return engine.eval(script, bindings); - } - + public Object evaluate(final String script, final Bindings bindings) throws Throwable { try { - return AccessController.doPrivileged(new PrivilegedExceptionAction() { - - @Override - public Object run() throws ScriptException { - return engine.eval(script, bindings); - } - }, getSandboxAccessControlContext()); - } catch (PrivilegedActionException e) { - throw e.getException(); + if (trustScript) { + return engine.eval(script, bindings); + } + + try { + return AccessController.doPrivileged(new PrivilegedExceptionAction() { + + @Override + public Object run() throws ScriptException { + return engine.eval(script, bindings); + } + }, getSandboxAccessControlContext()); + } catch (PrivilegedActionException e) { + throw e.getException(); + } + } catch (Throwable e) { + throw StackTraceUtils.deepSanitize(e); // make Groovy stack human-readable } } diff --git a/source/net/sourceforge/filebot/web/TheTVDBClient.java b/source/net/sourceforge/filebot/web/TheTVDBClient.java index ef5cd305..634fd406 100644 --- a/source/net/sourceforge/filebot/web/TheTVDBClient.java +++ b/source/net/sourceforge/filebot/web/TheTVDBClient.java @@ -19,6 +19,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Map.Entry; import java.util.Random; import java.util.logging.Level; import java.util.logging.Logger; @@ -638,15 +639,18 @@ public class TheTVDBClient extends AbstractEpisodeListProvider { * * @see http://thetvdb.com/wiki/index.php/API:banners.xml */ - public BannerDescriptor getBanner(TheTVDBSearchResult series, String bannerType, String bannerType2, Integer season, Locale locale, int index) throws Exception { + public BannerDescriptor getBanner(TheTVDBSearchResult series, Map filterDescriptor) throws Exception { + EnumMap filter = new EnumMap(BannerProperty.class); + for (Entry it : filterDescriptor.entrySet()) { + if (it.getValue() != null) { + filter.put(BannerProperty.valueOf(it.getKey().toString()), it.getValue().toString()); + } + } + // search for a banner matching the selector - int n = 0; for (BannerDescriptor it : getBannerList(series)) { - if ((bannerType == null || it.getBannerType().equalsIgnoreCase(bannerType)) && (bannerType2 == null || it.getBannerType2().equalsIgnoreCase(bannerType2)) && (season == null || it.getSeason().equals(season)) - && ((locale == null && it.getLocale().getLanguage().equals("en")) || it.getLocale().getLanguage().equals(locale.getLanguage()))) { - if (index == n++) { - return it; - } + if (it.fields.entrySet().containsAll(filter.entrySet())) { + return it; } } @@ -736,12 +740,20 @@ public class TheTVDBClient extends AbstractEpisodeListProvider { public URL getBannerMirrorUrl() throws MalformedURLException { - return new URL(get(BannerProperty.BannerMirror)); + try { + return new URL(get(BannerProperty.BannerMirror)); + } catch (Exception e) { + return null; + } } public URL getUrl() throws MalformedURLException { - return new URL(getBannerMirrorUrl(), get(BannerProperty.BannerPath)); + try { + return new URL(getBannerMirrorUrl(), get(BannerProperty.BannerPath)); + } catch (Exception e) { + return null; + } } @@ -750,8 +762,12 @@ public class TheTVDBClient extends AbstractEpisodeListProvider { } - public int getId() { - return Integer.parseInt(get(BannerProperty.id)); + public Integer getId() { + try { + return new Integer(get(BannerProperty.id)); + } catch (Exception e) { + return null; + } } @@ -780,17 +796,29 @@ public class TheTVDBClient extends AbstractEpisodeListProvider { public Locale getLocale() { - return new Locale(get(BannerProperty.Language)); + try { + return new Locale(get(BannerProperty.Language)); + } catch (Exception e) { + return null; + } } - public double getRating() { - return Double.parseDouble(get(BannerProperty.Rating)); + public Double getRating() { + try { + return new Double(get(BannerProperty.Rating)); + } catch (Exception e) { + return null; + } } - public int getRatingCount() { - return Integer.parseInt(get(BannerProperty.RatingCount)); + public Integer getRatingCount() { + try { + return new Integer(get(BannerProperty.RatingCount)); + } catch (Exception e) { + return null; + } } @@ -800,12 +828,20 @@ public class TheTVDBClient extends AbstractEpisodeListProvider { public URL getThumbnailUrl() throws MalformedURLException { - return new URL(getBannerMirrorUrl(), get(BannerProperty.ThumbnailPath)); + try { + return new URL(getBannerMirrorUrl(), get(BannerProperty.ThumbnailPath)); + } catch (Exception e) { + return null; + } } public URL getVignetteUrl() throws MalformedURLException { - return new URL(getBannerMirrorUrl(), get(BannerProperty.VignettePath)); + try { + return new URL(getBannerMirrorUrl(), get(BannerProperty.VignettePath)); + } catch (Exception e) { + return null; + } } diff --git a/website/scripts/artwork.tvdb.groovy b/website/scripts/artwork.tvdb.groovy index 6a5befb2..d098e7d0 100644 --- a/website/scripts/artwork.tvdb.groovy +++ b/website/scripts/artwork.tvdb.groovy @@ -1,8 +1,7 @@ // filebot -script "http://filebot.sf.net/scripts/artwork.tvdb.groovy" -trust-script /path/to/media/ // EXPERIMENTAL // HERE THERE BE DRAGONS -if (net.sourceforge.filebot.Settings.applicationRevisionNumber < 812) throw new Exception("Application revision too old") - +if (net.sourceforge.filebot.Settings.applicationRevisionNumber < 815) throw new Exception("Application revision too old") /* * Fetch series and season banners for all tv shows. Series name is auto-detected if possible or the folder name is used. @@ -10,7 +9,7 @@ if (net.sourceforge.filebot.Settings.applicationRevisionNumber < 812) throw new def fetchBanner(outputFile, series, bannerType, bannerType2 = null, season = null) { // select and fetch banner - def banner = TheTVDB.getBanner(series, bannerType, bannerType2, season, Locale.ENGLISH, 0) + def banner = ['en', null].findResult { TheTVDB.getBanner(series, [BannerType:bannerType, BannerType2:bannerType2, Season:season, Language:it]) } if (banner == null) { println "Banner not found: $outputFile / $bannerType:$bannerType2" return null