From: Niki Roo Date: Fri, 10 Apr 2020 17:12:41 +0000 (+0200) Subject: Merge branch 'master' into subtree X-Git-Url: http://git.nikiroo.be/?p=fanfix.git;a=commitdiff_plain;h=2e1300b9580ae1b6dded5a734c617a66a116c16d;hp=669a62833b4458bad0772debdd06921080500221 Merge branch 'master' into subtree --- diff --git a/DataLoader.java b/DataLoader.java index 3e0e770..901e8da 100644 --- a/DataLoader.java +++ b/DataLoader.java @@ -314,11 +314,10 @@ public class DataLoader { throws IOException { String format; if (cover) { - format = Instance.getConfig().getString(Config.FILE_FORMAT_IMAGE_FORMAT_COVER) - .toLowerCase(); + format = Instance.getInstance().getConfig().getString(Config.FILE_FORMAT_IMAGE_FORMAT_COVER).toLowerCase(); } else { - format = Instance.getConfig() - .getString(Config.FILE_FORMAT_IMAGE_FORMAT_CONTENT).toLowerCase(); + format = Instance.getInstance().getConfig().getString(Config.FILE_FORMAT_IMAGE_FORMAT_CONTENT) + .toLowerCase(); } saveAsImage(img, new File(target.toString() + "." + format), format); } diff --git a/Instance.java b/Instance.java index 561e2f6..f48d05b 100644 --- a/Instance.java +++ b/Instance.java @@ -29,55 +29,83 @@ import be.nikiroo.utils.resources.Bundles; * @author niki */ public class Instance { - private static ConfigBundle config; - private static UiConfigBundle uiconfig; - private static StringIdBundle trans; - private static DataLoader cache; - private static StringIdGuiBundle transGui; - private static BasicLibrary lib; - private static File coverDir; - private static File readerTmp; - private static File remoteDir; - private static String configDir; - private static TraceHandler tracer; - private static TempFiles tempFiles; - - private static boolean init; + static private Instance instance; + static private Object instancelock = new Object(); + + private ConfigBundle config; + private UiConfigBundle uiconfig; + private StringIdBundle trans; + private DataLoader cache; + private StringIdGuiBundle transGui; + private BasicLibrary lib; + private File coverDir; + private File readerTmp; + private File remoteDir; + private String configDir; + private TraceHandler tracer; + private TempFiles tempFiles; /** * Initialise the instance -- if already initialised, nothing will happen. *

- * Before calling this method, you may call - * {@link Bundles#setDirectory(String)} if wanted. + * Before calling this method, you may call {@link Bundles#setDirectory(String)} + * if wanted. */ static public void init() { init(false); } /** - * Initialise the instance -- if already initialised, nothing will happen - * unless you pass TRUE to force. + * Initialise the instance -- if already initialised, nothing will happen unless + * you pass TRUE to force. *

- * Before calling this method, you may call - * {@link Bundles#setDirectory(String)} if wanted. + * Before calling this method, you may call {@link Bundles#setDirectory(String)} + * if wanted. *

- * Note: forcing the initialisation can be dangerous, so make sure to only - * make it under controlled circumstances -- for instance, at the start of - * the program, you could call {@link Instance#init()}, change some settings - * because you want to force those settings (it will also forbid users to - * change them!) and then call {@link Instance#init(boolean)} with - * force set to TRUE. + * Note: forcing the initialisation can be dangerous, so make sure to only make + * it under controlled circumstances -- for instance, at the start of the + * program, you could call {@link Instance#init()}, change some settings because + * you want to force those settings (it will also forbid users to change them!) + * and then call {@link Instance#init(boolean)} with force set to TRUE. * - * @param force - * force the initialisation even if already initialised + * @param force force the initialisation even if already initialised */ static public void init(boolean force) { - if (init && !force) { - return; + synchronized (instancelock) { + if (instance == null || force) { + instance = new Instance(); + } } - init = true; + } + + /** + * Force-initialise the {@link Instance} to a known value. + *

+ * Usually for DEBUG/Test purposes. + * + * @param instance the actual Instance to use + */ + static public void init(Instance instance) { + Instance.instance = instance; + } + + /** + * The (mostly unique) instance of this {@link Instance}. + * + * @return the (mostly unique) instance + */ + public static Instance getInstance() { + return instance; + } + /** + * Actually initialise the instance. + *

+ * Before calling this method, you may call {@link Bundles#setDirectory(String)} + * if wanted. + */ + protected Instance() { // Before we can configure it: Boolean debug = checkEnv("DEBUG"); boolean trace = debug != null && debug; @@ -93,12 +121,12 @@ public class Instance { createConfigs(configDir, false); // Proxy support - Proxy.use(Instance.getConfig().getString(Config.NETWORK_PROXY)); + Proxy.use(config.getString(Config.NETWORK_PROXY)); // update tracer: if (debug == null) { - debug = Instance.getConfig().getBoolean(Config.DEBUG_ERR, false); - trace = Instance.getConfig().getBoolean(Config.DEBUG_TRACE, false); + debug = config.getBoolean(Config.DEBUG_ERR, false); + trace = config.getBoolean(Config.DEBUG_TRACE, false); } tracer = new TraceHandler(true, debug, trace); @@ -120,19 +148,16 @@ public class Instance { int hoursLarge = config.getInteger(Config.CACHE_MAX_TIME_STABLE, 0); cache = new DataLoader(tmp, ua, hours, hoursLarge); } catch (IOException e) { - tracer.error(new IOException( - "Cannot create cache (will continue without cache)", e)); + tracer.error(new IOException("Cannot create cache (will continue without cache)", e)); cache = new DataLoader(ua); } cache.setTraceHandler(tracer); // readerTmp / coverDir - readerTmp = getFile(UiConfig.CACHE_DIR_LOCAL_READER, new File( - configDir, "tmp-reader")); + readerTmp = getFile(UiConfig.CACHE_DIR_LOCAL_READER, new File(configDir, "tmp-reader")); - coverDir = getFile(Config.DEFAULT_COVERS_DIR, new File(configDir, - "covers")); + coverDir = getFile(Config.DEFAULT_COVERS_DIR, new File(configDir, "covers")); coverDir.mkdirs(); try { @@ -149,22 +174,21 @@ public class Instance { * * @return the traces handler (never NULL) */ - public static TraceHandler getTraceHandler() { + public TraceHandler getTraceHandler() { return tracer; } /** * The traces handler for this {@link Cache}. * - * @param tracer - * the new traces handler or NULL + * @param tracer the new traces handler or NULL */ - public static void setTraceHandler(TraceHandler tracer) { + public void setTraceHandler(TraceHandler tracer) { if (tracer == null) { tracer = new TraceHandler(false, false, false); } - Instance.tracer = tracer; + this.tracer = tracer; cache.setTraceHandler(tracer); } @@ -173,7 +197,7 @@ public class Instance { * * @return the configuration service */ - public static ConfigBundle getConfig() { + public ConfigBundle getConfig() { return config; } @@ -182,17 +206,16 @@ public class Instance { * * @return the configuration service */ - public static UiConfigBundle getUiConfig() { + public UiConfigBundle getUiConfig() { return uiconfig; } /** * Reset the configuration. * - * @param resetTrans - * also reset the translation files + * @param resetTrans also reset the translation files */ - public static void resetConfig(boolean resetTrans) { + public void resetConfig(boolean resetTrans) { String dir = Bundles.getDirectory(); Bundles.setDirectory(null); try { @@ -227,7 +250,7 @@ public class Instance { * * @return the {@link DataLoader} */ - public static DataLoader getCache() { + public DataLoader getCache() { return cache; } @@ -238,7 +261,7 @@ public class Instance { * * @return the {link StringIdBundle} */ - public static StringIdBundle getTrans() { + public StringIdBundle getTrans() { return trans; } @@ -249,7 +272,7 @@ public class Instance { * * @return the {link StringIdGuiBundle} */ - public static StringIdGuiBundle getTransGui() { + public StringIdGuiBundle getTransGui() { return transGui; } @@ -258,7 +281,7 @@ public class Instance { * * @return the {@link LocalLibrary} */ - public static BasicLibrary getLibrary() { + public BasicLibrary getLibrary() { if (lib == null) { throw new NullPointerException("We don't have a library to return"); } @@ -271,7 +294,7 @@ public class Instance { * * @return the default covers directory */ - public static File getCoverDir() { + public File getCoverDir() { return coverDir; } @@ -280,7 +303,7 @@ public class Instance { * * @return the directory */ - public static File getReaderDir() { + public File getReaderDir() { return readerTmp; } @@ -288,12 +311,11 @@ public class Instance { * Return the directory where to store temporary files for the remote * {@link LocalLibrary}. * - * @param host - * the remote for this host + * @param host the remote for this host * * @return the directory */ - public static File getRemoteDir(String host) { + public File getRemoteDir(String host) { return getRemoteDir(remoteDir, host); } @@ -301,14 +323,12 @@ public class Instance { * Return the directory where to store temporary files for the remote * {@link LocalLibrary}. * - * @param remoteDir - * the base remote directory - * @param host - * the remote for this host + * @param remoteDir the base remote directory + * @param host the remote for this host * * @return the directory */ - private static File getRemoteDir(File remoteDir, String host) { + private File getRemoteDir(File remoteDir, String host) { remoteDir.mkdirs(); if (host != null) { @@ -323,15 +343,12 @@ public class Instance { * * @return TRUE if we need to */ - public static boolean isVersionCheckNeeded() { + public boolean isVersionCheckNeeded() { try { - long wait = config.getInteger(Config.NETWORK_UPDATE_INTERVAL, 0) - * 24 * 60 * 60 * 1000; + long wait = config.getInteger(Config.NETWORK_UPDATE_INTERVAL, 0) * 24 * 60 * 60 * 1000; if (wait >= 0) { - String lastUpString = IOUtils.readSmallFile(new File(configDir, - "LAST_UPDATE")); - long delay = new Date().getTime() - - Long.parseLong(lastUpString); + String lastUpString = IOUtils.readSmallFile(new File(configDir, "LAST_UPDATE")); + long delay = new Date().getTime() - Long.parseLong(lastUpString); if (delay > wait) { return true; } @@ -349,10 +366,9 @@ public class Instance { /** * Notify that we checked for a new version of Fanfix. */ - public static void setVersionChecked() { + public void setVersionChecked() { try { - IOUtils.writeSmallFile(new File(configDir), "LAST_UPDATE", - Long.toString(new Date().getTime())); + IOUtils.writeSmallFile(new File(configDir), "LAST_UPDATE", Long.toString(new Date().getTime())); } catch (IOException e) { tracer.error(e); } @@ -365,18 +381,18 @@ public class Instance { * * @return the facility */ - public static TempFiles getTempFiles() { + public TempFiles getTempFiles() { return tempFiles; } /** - * The configuration directory (will check, in order of preference, the - * system properties, the environment and then defaults to + * The configuration directory (will check, in order of preference, the system + * properties, the environment and then defaults to * {@link Instance#getHome()}/.fanfix). * * @return the config directory */ - private static String getConfigDir() { + private String getConfigDir() { String configDir = System.getProperty("CONFIG_DIR"); if (configDir == null) { @@ -395,13 +411,11 @@ public class Instance { * {@link Instance#uiconfig}, {@link Instance#trans} and * {@link Instance#transGui}). * - * @param configDir - * the directory where to find the configuration files - * @param refresh - * TRUE to reset the configuration files from the default - * included ones + * @param configDir the directory where to find the configuration files + * @param refresh TRUE to reset the configuration files from the default + * included ones */ - private static void createConfigs(String configDir, boolean refresh) { + private void createConfigs(String configDir, boolean refresh) { if (!refresh) { Bundles.setDirectory(configDir); } @@ -443,16 +457,14 @@ public class Instance { /** * Create the default library as specified by the config. * - * @param remoteDir - * the base remote directory if needed + * @param remoteDir the base remote directory if needed * * @return the default {@link BasicLibrary} */ - private static BasicLibrary createDefaultLibrary(File remoteDir) { + private BasicLibrary createDefaultLibrary(File remoteDir) { BasicLibrary lib = null; - boolean useRemote = config.getBoolean(Config.REMOTE_LIBRARY_ENABLED, - false); + boolean useRemote = config.getBoolean(Config.REMOTE_LIBRARY_ENABLED, false); if (useRemote) { String host = null; @@ -464,11 +476,9 @@ public class Instance { tracer.trace("Selecting remote library " + host + ":" + port); lib = new RemoteLibrary(key, host, port); - lib = new CacheLibrary(getRemoteDir(remoteDir, host), lib); + lib = new CacheLibrary(getRemoteDir(remoteDir, host), lib, uiconfig); } catch (Exception e) { - tracer.error(new IOException( - "Cannot create remote library for: " + host + ":" - + port, e)); + tracer.error(new IOException("Cannot create remote library for: " + host + ":" + port, e)); } } else { String libDir = System.getenv("BOOKS_DIR"); @@ -479,11 +489,9 @@ public class Instance { } } try { - lib = new LocalLibrary(getFile(libDir)); + lib = new LocalLibrary(getFile(libDir), config); } catch (Exception e) { - tracer.error(new IOException( - "Cannot create library for directory: " - + getFile(libDir), e)); + tracer.error(new IOException("Cannot create library for directory: " + getFile(libDir), e)); } } @@ -493,9 +501,11 @@ public class Instance { /** * Return a path, but support the special $HOME variable. * - * @return the path + * @param id the key for the path, which may contain "$HOME" + * @param def the default value if none + * @return the path, with expanded "$HOME" if needed */ - private static File getFile(Config id, File def) { + protected File getFile(Config id, File def) { String path = config.getString(id, def.getPath()); return getFile(path); } @@ -503,9 +513,11 @@ public class Instance { /** * Return a path, but support the special $HOME variable. * - * @return the path + * @param id the key for the path, which may contain "$HOME" + * @param def the default value if none + * @return the path, with expanded "$HOME" if needed */ - private static File getFile(UiConfig id, File def) { + protected File getFile(UiConfig id, File def) { String path = uiconfig.getString(id, def.getPath()); return getFile(path); } @@ -513,9 +525,10 @@ public class Instance { /** * Return a path, but support the special $HOME variable. * - * @return the path + * @param path the path, which may contain "$HOME" + * @return the path, with expanded "$HOME" if needed */ - private static File getFile(String path) { + protected File getFile(String path) { File file = null; if (path != null && !path.isEmpty()) { path = path.replace('/', File.separatorChar); @@ -534,12 +547,12 @@ public class Instance { * properties. *

* The environment variable is tested first. Then, the custom property - * "fanfix.home" is tried, followed by the usual "user.home" then - * "java.io.tmp" if nothing else is found. + * "fanfix.home" is tried, followed by the usual "user.home" then "java.io.tmp" + * if nothing else is found. * * @return the home */ - private static String getHome() { + protected String getHome() { String home = System.getenv("FANFIX_DIR"); if (home != null && new File(home).isFile()) { home = null; @@ -578,12 +591,11 @@ public class Instance { * * @return the language */ - private static String getLang() { + protected String getLang() { String lang = config.getString(Config.LANG); if (lang == null || lang.isEmpty()) { - if (System.getenv("LANG") != null - && !System.getenv("LANG").isEmpty()) { + if (System.getenv("LANG") != null && !System.getenv("LANG").isEmpty()) { lang = System.getenv("LANG"); } } @@ -598,17 +610,15 @@ public class Instance { /** * Check that the given environment variable is "enabled". * - * @param key - * the variable to check + * @param key the variable to check * * @return TRUE if it is */ - private static Boolean checkEnv(String key) { + protected Boolean checkEnv(String key) { String value = System.getenv(key); if (value != null) { value = value.trim().toLowerCase(); - if ("yes".equals(value) || "true".equals(value) - || "on".equals(value) || "1".equals(value) + if ("yes".equals(value) || "true".equals(value) || "on".equals(value) || "1".equals(value) || "y".equals(value)) { return true; } diff --git a/Main.java b/Main.java index 2ed276b..961816a 100644 --- a/Main.java +++ b/Main.java @@ -10,9 +10,7 @@ import java.util.List; import javax.net.ssl.SSLException; import be.nikiroo.fanfix.bundles.Config; -import be.nikiroo.fanfix.bundles.ConfigBundle; import be.nikiroo.fanfix.bundles.StringId; -import be.nikiroo.fanfix.bundles.StringIdBundle; import be.nikiroo.fanfix.data.Chapter; import be.nikiroo.fanfix.data.MetaData; import be.nikiroo.fanfix.data.Story; @@ -31,8 +29,6 @@ import be.nikiroo.fanfix.supported.BasicSupport; import be.nikiroo.fanfix.supported.SupportType; import be.nikiroo.utils.Progress; import be.nikiroo.utils.Version; -import be.nikiroo.utils.resources.Bundles; -import be.nikiroo.utils.resources.TransBundle; import be.nikiroo.utils.serial.server.ServerObject; /** @@ -126,9 +122,8 @@ public class Main { action = MainAction.valueOf(args[i].substring(2) .toUpperCase().replace("-", "_")); } catch (Exception e) { - Instance.getTraceHandler().error( - new IllegalArgumentException("Unknown action: " - + args[i], e)); + Instance.getInstance().getTraceHandler() + .error(new IllegalArgumentException("Unknown action: " + args[i], e)); exitCode = 255; } } @@ -229,15 +224,13 @@ public class Main { searchOn = SupportType.valueOfAllOkUC(args[i]); if (searchOn == null) { - Instance.getTraceHandler().error( - "Website not known: <" + args[i] + ">"); + Instance.getInstance().getTraceHandler().error("Website not known: <" + args[i] + ">"); exitCode = 41; break; } if (BasicSearchable.getSearchable(searchOn) == null) { - Instance.getTraceHandler().error( - "Website not supported: " + searchOn); + Instance.getInstance().getTraceHandler().error("Website not supported: " + searchOn); exitCode = 42; break; } @@ -272,14 +265,12 @@ public class Main { searchOn = SupportType.valueOfAllOkUC(args[i]); if (searchOn == null) { - Instance.getTraceHandler().error( - "Website not known: <" + args[i] + ">"); + Instance.getInstance().getTraceHandler().error("Website not known: <" + args[i] + ">"); exitCode = 255; } if (BasicSearchable.getSearchable(searchOn) == null) { - Instance.getTraceHandler().error( - "Website not supported: " + searchOn); + Instance.getInstance().getTraceHandler().error("Website not supported: " + searchOn); exitCode = 255; } } else if (page == null && item == null) { @@ -292,8 +283,7 @@ public class Main { int index = Integer.parseInt(args[i]); tags.add(index); } catch (NumberFormatException e) { - Instance.getTraceHandler().error( - "Invalid tag index: " + args[i]); + Instance.getInstance().getTraceHandler().error("Invalid tag index: " + args[i]); exitCode = 255; } } @@ -349,7 +339,8 @@ public class Main { port = Integer.parseInt(args[i]); BasicLibrary lib = new RemoteLibrary(key, host, port); - lib = new CacheLibrary(Instance.getRemoteDir(host), lib); + lib = new CacheLibrary(Instance.getInstance().getRemoteDir(host), lib, + Instance.getInstance().getUiConfig()); BasicReader.setDefaultLibrary(lib); @@ -423,9 +414,7 @@ public class Main { break; case LIST: if (BasicReader.getReader() == null) { - Instance.getTraceHandler() - .error(new Exception( - "No reader type has been configured")); + Instance.getInstance().getTraceHandler().error(new Exception("No reader type has been configured")); exitCode = 10; break; } @@ -433,33 +422,31 @@ public class Main { break; case SET_SOURCE: try { - Instance.getLibrary().changeSource(luid, sourceString, pg); + Instance.getInstance().getLibrary().changeSource(luid, sourceString, pg); } catch (IOException e1) { - Instance.getTraceHandler().error(e1); + Instance.getInstance().getTraceHandler().error(e1); exitCode = 21; } break; case SET_TITLE: try { - Instance.getLibrary().changeTitle(luid, titleString, pg); + Instance.getInstance().getLibrary().changeTitle(luid, titleString, pg); } catch (IOException e1) { - Instance.getTraceHandler().error(e1); + Instance.getInstance().getTraceHandler().error(e1); exitCode = 22; } break; case SET_AUTHOR: try { - Instance.getLibrary().changeAuthor(luid, authorString, pg); + Instance.getInstance().getLibrary().changeAuthor(luid, authorString, pg); } catch (IOException e1) { - Instance.getTraceHandler().error(e1); + Instance.getInstance().getTraceHandler().error(e1); exitCode = 23; } break; case READ: if (BasicReader.getReader() == null) { - Instance.getTraceHandler() - .error(new Exception( - "No reader type has been configured")); + Instance.getInstance().getTraceHandler().error(new Exception("No reader type has been configured")); exitCode = 10; break; } @@ -467,9 +454,7 @@ public class Main { break; case READ_URL: if (BasicReader.getReader() == null) { - Instance.getTraceHandler() - .error(new Exception( - "No reader type has been configured")); + Instance.getInstance().getTraceHandler().error(new Exception("No reader type has been configured")); exitCode = 10; break; } @@ -478,22 +463,20 @@ public class Main { case SEARCH: page = page == null ? 1 : page; if (page < 0) { - Instance.getTraceHandler().error("Incorrect page number"); + Instance.getInstance().getTraceHandler().error("Incorrect page number"); exitCode = 255; break; } item = item == null ? 0 : item; if (item < 0) { - Instance.getTraceHandler().error("Incorrect item number"); + Instance.getInstance().getTraceHandler().error("Incorrect item number"); exitCode = 255; break; } if (BasicReader.getReader() == null) { - Instance.getTraceHandler() - .error(new Exception( - "No reader type has been configured")); + Instance.getInstance().getTraceHandler().error(new Exception("No reader type has been configured")); exitCode = 10; break; } @@ -509,7 +492,7 @@ public class Main { exitCode = 255; } } catch (IOException e1) { - Instance.getTraceHandler().error(e1); + Instance.getInstance().getTraceHandler().error(e1); exitCode = 20; } @@ -522,22 +505,20 @@ public class Main { page = page == null ? 1 : page; if (page < 0) { - Instance.getTraceHandler().error("Incorrect page number"); + Instance.getInstance().getTraceHandler().error("Incorrect page number"); exitCode = 255; break; } item = item == null ? 0 : item; if (item < 0) { - Instance.getTraceHandler().error("Incorrect item number"); + Instance.getInstance().getTraceHandler().error("Incorrect item number"); exitCode = 255; break; } if (BasicReader.getReader() == null) { - Instance.getTraceHandler() - .error(new Exception( - "No reader type has been configured")); + Instance.getInstance().getTraceHandler().error(new Exception("No reader type has been configured")); exitCode = 10; break; } @@ -546,7 +527,7 @@ public class Main { BasicReader.getReader().searchTag(searchOn, page, item, true, tags.toArray(new Integer[] {})); } catch (IOException e1) { - Instance.getTraceHandler().error(e1); + Instance.getInstance().getTraceHandler().error(e1); } break; @@ -567,22 +548,20 @@ public class Main { break; case START: if (BasicReader.getReader() == null) { - Instance.getTraceHandler() - .error(new Exception( - "No reader type has been configured")); + Instance.getInstance().getTraceHandler().error(new Exception("No reader type has been configured")); exitCode = 10; break; } try { BasicReader.getReader().browse(null); } catch (IOException e) { - Instance.getTraceHandler().error(e); + Instance.getInstance().getTraceHandler().error(e); exitCode = 66; } break; case SERVER: - key = Instance.getConfig().getString(Config.SERVER_KEY); - port = Instance.getConfig().getInteger(Config.SERVER_PORT); + key = Instance.getInstance().getConfig().getString(Config.SERVER_KEY); + port = Instance.getInstance().getConfig().getInteger(Config.SERVER_PORT); if (port == null) { System.err.println("No port configured in the config file"); exitCode = 15; @@ -590,28 +569,32 @@ public class Main { } try { ServerObject server = new RemoteLibraryServer(key, port); - server.setTraceHandler(Instance.getTraceHandler()); + server.setTraceHandler(Instance.getInstance().getTraceHandler()); server.run(); } catch (IOException e) { - Instance.getTraceHandler().error(e); + Instance.getInstance().getTraceHandler().error(e); } return; case STOP_SERVER: - key = Instance.getConfig().getString(Config.SERVER_KEY); - port = Instance.getConfig().getInteger(Config.SERVER_PORT); + // Can be given via "--remote XX XX XX" + if (key == null) + key = Instance.getInstance().getConfig().getString(Config.SERVER_KEY); + if (port == null) + port = Instance.getInstance().getConfig().getInteger(Config.SERVER_PORT); + if (port == null) { - System.err.println("No port configured in the config file"); + System.err.println("No port given nor configured in the config file"); exitCode = 15; break; } try { new RemoteLibrary(key, host, port).exit(); } catch (SSLException e) { - Instance.getTraceHandler().error( + Instance.getInstance().getTraceHandler().error( "Bad access key for remote library"); exitCode = 43; } catch (IOException e) { - Instance.getTraceHandler().error(e); + Instance.getInstance().getTraceHandler().error(e); exitCode = 44; } @@ -623,11 +606,9 @@ public class Main { } try { - Instance.getTempFiles().close(); + Instance.getInstance().getTempFiles().close(); } catch (IOException e) { - Instance.getTraceHandler() - .error(new IOException( - "Cannot dispose of the temporary files", e)); + Instance.getInstance().getTraceHandler().error(new IOException("Cannot dispose of the temporary files", e)); } if (exitCode == 255) { @@ -649,12 +630,10 @@ public class Main { */ public static int imprt(String urlString, Progress pg) { try { - MetaData meta = Instance.getLibrary().imprt( - BasicReader.getUrl(urlString), pg); - System.out.println(meta.getLuid() + ": \"" + meta.getTitle() - + "\" imported."); + MetaData meta = Instance.getInstance().getLibrary().imprt(BasicReader.getUrl(urlString), pg); + System.out.println(meta.getLuid() + ": \"" + meta.getTitle() + "\" imported."); } catch (IOException e) { - Instance.getTraceHandler().error(e); + Instance.getInstance().getTraceHandler().error(e); return 1; } @@ -680,15 +659,14 @@ public class Main { Progress pg) { OutputType type = OutputType.valueOfNullOkUC(typeString, null); if (type == null) { - Instance.getTraceHandler().error( - new Exception(trans(StringId.OUTPUT_DESC, typeString))); + Instance.getInstance().getTraceHandler().error(new Exception(trans(StringId.OUTPUT_DESC, typeString))); return 1; } try { - Instance.getLibrary().export(luid, type, target, pg); + Instance.getInstance().getLibrary().export(luid, type, target, pg); } catch (IOException e) { - Instance.getTraceHandler().error(e); + Instance.getInstance().getTraceHandler().error(e); return 4; } @@ -710,7 +688,7 @@ public class Main { try { BasicReader.getReader().browse(source); } catch (IOException e) { - Instance.getTraceHandler().error(e); + Instance.getInstance().getTraceHandler().error(e); return 66; } @@ -746,16 +724,15 @@ public class Main { reader.setChapter(Integer.parseInt(chapString)); reader.read(true); } catch (NumberFormatException e) { - Instance.getTraceHandler().error( - new IOException("Chapter number cannot be parsed: " - + chapString, e)); + Instance.getInstance().getTraceHandler() + .error(new IOException("Chapter number cannot be parsed: " + chapString, e)); return 2; } } else { reader.read(true); } } catch (IOException e) { - Instance.getTraceHandler().error(e); + Instance.getInstance().getTraceHandler().error(e); return 1; } @@ -783,7 +760,7 @@ public class Main { String target, boolean infoCover, Progress pg) { int exitCode = 0; - Instance.getTraceHandler().trace("Convert: " + urlString); + Instance.getInstance().getTraceHandler().trace("Convert: " + urlString); String sourceName = urlString; try { URL source = BasicReader.getUrl(urlString); @@ -794,9 +771,8 @@ public class Main { OutputType type = OutputType.valueOfAllOkUC(typeString, null); if (type == null) { - Instance.getTraceHandler().error( - new IOException(trans(StringId.ERR_BAD_OUTPUT_TYPE, - typeString))); + Instance.getInstance().getTraceHandler() + .error(new IOException(trans(StringId.ERR_BAD_OUTPUT_TYPE, typeString))); exitCode = 2; } else { @@ -804,8 +780,7 @@ public class Main { BasicSupport support = BasicSupport.getSupport(source); if (support != null) { - Instance.getTraceHandler().trace( - "Support found: " + support.getClass()); + Instance.getInstance().getTraceHandler().trace("Support found: " + support.getClass()); Progress pgIn = new Progress(); Progress pgOut = new Progress(); if (pg != null) { @@ -817,32 +792,26 @@ public class Main { Story story = support.process(pgIn); try { target = new File(target).getAbsolutePath(); - BasicOutput.getOutput(type, infoCover, infoCover) - .process(story, target, pgOut); + BasicOutput.getOutput(type, infoCover, infoCover).process(story, target, pgOut); } catch (IOException e) { - Instance.getTraceHandler().error( - new IOException(trans(StringId.ERR_SAVING, - target), e)); + Instance.getInstance().getTraceHandler() + .error(new IOException(trans(StringId.ERR_SAVING, target), e)); exitCode = 5; } } else { - Instance.getTraceHandler().error( - new IOException(trans( - StringId.ERR_NOT_SUPPORTED, source))); + Instance.getInstance().getTraceHandler() + .error(new IOException(trans( StringId.ERR_NOT_SUPPORTED, source))); exitCode = 4; } } catch (IOException e) { - Instance.getTraceHandler().error( - new IOException(trans(StringId.ERR_LOADING, - sourceName), e)); + Instance.getInstance().getTraceHandler() + .error(new IOException(trans(StringId.ERR_LOADING, sourceName), e)); exitCode = 3; } } } catch (MalformedURLException e) { - Instance.getTraceHandler() - .error(new IOException(trans(StringId.ERR_BAD_URL, - sourceName), e)); + Instance.getInstance().getTraceHandler().error(new IOException(trans(StringId.ERR_BAD_URL, sourceName), e)); exitCode = 1; } @@ -858,7 +827,7 @@ public class Main { * @return the translated result */ private static String trans(StringId id, Object... params) { - return Instance.getTrans().getString(id, params); + return Instance.getInstance().getTrans().getString(id, params); } /** @@ -908,9 +877,8 @@ public class Main { BasicReader.setDefaultReaderType(readerType); return 0; } catch (IllegalArgumentException e) { - Instance.getTraceHandler().error( - new IOException("Unknown reader type: " + readerTypeString, - e)); + Instance.getInstance().getTraceHandler() + .error(new IOException("Unknown reader type: " + readerTypeString, e)); return 1; } } diff --git a/VersionCheck.java b/VersionCheck.java index 2c9a032..f64159a 100644 --- a/VersionCheck.java +++ b/VersionCheck.java @@ -93,7 +93,7 @@ public class VersionCheck { * time has elapsed. */ public void ok() { - Instance.setVersionChecked(); + Instance.getInstance().setVersionChecked(); } /** @@ -107,10 +107,10 @@ public class VersionCheck { List newer = new ArrayList(); Map> changes = new HashMap>(); - if (Instance.isVersionCheckNeeded()) { + if (Instance.getInstance().isVersionCheckNeeded()) { try { // Prepare the URLs according to the user's language - Locale lang = Instance.getTrans().getLocale(); + Locale lang = Instance.getInstance().getTrans().getLocale(); String fr = lang.getLanguage(); String BE = lang.getCountry().replace(".UTF8", ""); String urlFrBE = base.replace("${LANG}", "-" + fr + "_" + BE); @@ -120,8 +120,7 @@ public class VersionCheck { InputStream in = null; for (String url : new String[] { urlFrBE, urlFr, urlDefault }) { try { - in = Instance.getCache() - .open(new URL(url), null, false); + in = Instance.getInstance().getCache().open(new URL(url), null, false); break; } catch (IOException e) { } @@ -162,10 +161,8 @@ public class VersionCheck { reader.close(); } } catch (IOException e) { - Instance.getTraceHandler() - .error(new IOException( - "Cannot download latest changelist on github.com", - e)); + Instance.getInstance().getTraceHandler() + .error(new IOException("Cannot download latest changelist on github.com", e)); } } diff --git a/bundles/resources_core.properties b/bundles/resources_core.properties index d656ed6..dc7881a 100644 --- a/bundles/resources_core.properties +++ b/bundles/resources_core.properties @@ -124,9 +124,7 @@ INPUT_DESC_FANFICTION = Fanfictions of many, many different universes, from TV s INPUT_DESC_FIMFICTION = Fanfictions devoted to the My Little Pony show # Description of this input type # (FORMAT: STRING) -INPUT_DESC_MANGAFOX = A well filled repository of mangas, or, as their website states: \n\ -\tMost popular manga scanlations read online for free at mangafox, \n\ -\tas well as a close-knit community to chat and make friends. +INPUT_DESC_MANGAHUB = A well filled repository of mangas, in English # Description of this input type # (FORMAT: STRING) INPUT_DESC_E621 = Furry website supporting comics, including MLP diff --git a/bundles/resources_core_fr.properties b/bundles/resources_core_fr.properties index 9bf3626..a64a5a0 100644 --- a/bundles/resources_core_fr.properties +++ b/bundles/resources_core_fr.properties @@ -109,7 +109,7 @@ INPUT_DESC_FANFICTION = Fanfictions venant d'une multitude d'univers différents INPUT_DESC_FIMFICTION = Fanfictions dévouées à la série My Little Pony # Description of this input type # (FORMAT: STRING) -INPUT_DESC_MANGAFOX = Un site répertoriant une quantité non négligeable de mangas +INPUT_DESC_MANGAHUB = Un site répertoriant une quantité non négligeable de mangas, en anglais # Description of this input type # (FORMAT: STRING) INPUT_DESC_E621 = Un site Furry proposant des comics, y compris de MLP diff --git a/library/BasicLibrary.java b/library/BasicLibrary.java index 099859d..c2ab12b 100644 --- a/library/BasicLibrary.java +++ b/library/BasicLibrary.java @@ -122,6 +122,13 @@ abstract public class BasicLibrary { */ public abstract Image getCover(String luid) throws IOException; + // TODO: ensure it is the main used interface + public synchronized MetaResultList getList(Progress pg) throws IOException { + return new MetaResultList(getMetas(pg)); + } + + //TODO: make something for (normal and custom) not-story covers + /** * Return the cover image associated to this source. *

@@ -142,7 +149,7 @@ abstract public class BasicLibrary { return custom; } - List metas = getListBySource(source); + List metas = getList().filter(source, null, null); if (metas.size() > 0) { return getCover(metas.get(0).getLuid()); } @@ -170,7 +177,7 @@ abstract public class BasicLibrary { return custom; } - List metas = getListByAuthor(author); + List metas = getList().filter(null, author, null); if (metas.size() > 0) { return getCover(metas.get(0).getLuid()); } @@ -245,6 +252,8 @@ abstract public class BasicLibrary { /** * Return the list of stories (represented by their {@link MetaData}, which * MAY not have the cover included). + *

+ * The returned list MUST be a copy, not the original one. * * @param pg * the optional {@link Progress} @@ -329,13 +338,43 @@ abstract public class BasicLibrary { * @param pg * the optional progress reporter */ - public void refresh(Progress pg) { + public synchronized void refresh(Progress pg) { try { getMetas(pg); } catch (IOException e) { // We will let it fail later } } + + /** + * Check if the {@link Story} denoted by this Library UID is present in the + * cache (if we have no cache, we default to true). + * + * @param luid + * the Library UID + * + * @return TRUE if it is + */ + public boolean isCached(String luid) { + // By default, everything is cached + return true; + } + + /** + * Clear the {@link Story} from the cache, if needed. + *

+ * The next time we try to retrieve the {@link Story}, it may be required to + * cache it again. + * + * @param luid + * the story to clear + * + * @throws IOException + * in case of I/O error + */ + public void clearFromCache(String luid) throws IOException { + // By default, this is a noop. + } /** * List all the known types (sources) of stories. @@ -558,64 +597,8 @@ abstract public class BasicLibrary { * @throws IOException * in case of IOException */ - public synchronized List getList() throws IOException { - return getMetas(null); - } - - /** - * List all the stories of the given source type in the {@link BasicLibrary} - * , or all the stories if NULL is passed as a type. - *

- * Cover images not included. - * - * @param type - * the type of story to retrieve, or NULL for all - * - * @return the stories - * - * @throws IOException - * in case of IOException - */ - public synchronized List getListBySource(String type) - throws IOException { - List list = new ArrayList(); - for (MetaData meta : getMetas(null)) { - String storyType = meta.getSource(); - if (type == null || type.equalsIgnoreCase(storyType)) { - list.add(meta); - } - } - - Collections.sort(list); - return list; - } - - /** - * List all the stories of the given author in the {@link BasicLibrary}, or - * all the stories if NULL is passed as an author. - *

- * Cover images not included. - * - * @param author - * the author of the stories to retrieve, or NULL for all - * - * @return the stories - * - * @throws IOException - * in case of IOException - */ - public synchronized List getListByAuthor(String author) - throws IOException { - List list = new ArrayList(); - for (MetaData meta : getMetas(null)) { - String storyAuthor = meta.getAuthor(); - if (author == null || author.equalsIgnoreCase(storyAuthor)) { - list.add(meta); - } - } - - Collections.sort(list); - return list; + public MetaResultList getList() throws IOException { + return getList(null); } /** @@ -730,10 +713,8 @@ abstract public class BasicLibrary { } catch (IOException e) { // We should not have not-supported files in the // library - Instance.getTraceHandler().error( - new IOException(String.format( - "Cannot load file of type '%s' from library: %s", - meta.getType(), file), e)); + Instance.getInstance().getTraceHandler().error(new IOException( + String.format("Cannot load file of type '%s' from library: %s", meta.getType(), file), e)); } finally { pgProcess.done(); pg.done(); @@ -892,8 +873,7 @@ abstract public class BasicLibrary { public synchronized Story save(Story story, String luid, Progress pg) throws IOException { - Instance.getTraceHandler().trace( - this.getClass().getSimpleName() + ": saving story " + luid); + Instance.getInstance().getTraceHandler().trace(this.getClass().getSimpleName() + ": saving story " + luid); // Do not change the original metadata, but change the original story MetaData meta = story.getMeta().clone(); @@ -913,9 +893,8 @@ abstract public class BasicLibrary { updateInfo(story.getMeta()); - Instance.getTraceHandler().trace( - this.getClass().getSimpleName() + ": story saved (" + luid - + ")"); + Instance.getInstance().getTraceHandler() + .trace(this.getClass().getSimpleName() + ": story saved (" + luid + ")"); return story; } @@ -930,14 +909,13 @@ abstract public class BasicLibrary { * in case of I/O error */ public synchronized void delete(String luid) throws IOException { - Instance.getTraceHandler().trace( - this.getClass().getSimpleName() + ": deleting story " + luid); + Instance.getInstance().getTraceHandler().trace(this.getClass().getSimpleName() + ": deleting story " + luid); doDelete(luid); invalidateInfo(luid); - Instance.getTraceHandler().trace( - this.getClass().getSimpleName() + ": story deleted (" + luid + Instance.getInstance().getTraceHandler() + .trace(this.getClass().getSimpleName() + ": story deleted (" + luid + ")"); } @@ -1039,8 +1017,6 @@ abstract public class BasicLibrary { meta.setTitle(newTitle); meta.setAuthor(newAuthor); saveMeta(meta, pg); - - invalidateInfo(luid); } /** diff --git a/library/CacheLibrary.java b/library/CacheLibrary.java index e8743b6..694f9ec 100644 --- a/library/CacheLibrary.java +++ b/library/CacheLibrary.java @@ -3,12 +3,16 @@ package be.nikiroo.fanfix.library; import java.io.File; import java.io.IOException; import java.net.URL; +import java.util.ArrayList; import java.util.List; +import java.util.TreeSet; import be.nikiroo.fanfix.Instance; import be.nikiroo.fanfix.bundles.UiConfig; +import be.nikiroo.fanfix.bundles.UiConfigBundle; import be.nikiroo.fanfix.data.MetaData; import be.nikiroo.fanfix.data.Story; +import be.nikiroo.fanfix.output.BasicOutput.OutputType; import be.nikiroo.utils.Image; import be.nikiroo.utils.Progress; @@ -18,26 +22,26 @@ import be.nikiroo.utils.Progress; * @author niki */ public class CacheLibrary extends BasicLibrary { - private List metas; + private List metasReal; + private List metasMixed; private BasicLibrary lib; private LocalLibrary cacheLib; /** * Create a cache library around the given one. *

- * It will return the same result, but those will be saved to disk at the - * same time to be fetched quicker the next time. + * It will return the same result, but those will be saved to disk at the same + * time to be fetched quicker the next time. * - * @param cacheDir - * the cache directory where to save the files to disk - * @param lib - * the original library to wrap + * @param cacheDir the cache directory where to save the files to disk + * @param lib the original library to wrap + * @param config the configuration used to know which kind of default + * {@link OutputType} to use for images and non-images stories */ - public CacheLibrary(File cacheDir, BasicLibrary lib) { - this.cacheLib = new LocalLibrary(cacheDir, Instance.getUiConfig() - .getString(UiConfig.GUI_NON_IMAGES_DOCUMENT_TYPE), Instance - .getUiConfig().getString(UiConfig.GUI_IMAGES_DOCUMENT_TYPE), - true); + public CacheLibrary(File cacheDir, BasicLibrary lib, UiConfigBundle config) { + this.cacheLib = new LocalLibrary(cacheDir, // + config.getString(UiConfig.GUI_NON_IMAGES_DOCUMENT_TYPE), + config.getString(UiConfig.GUI_IMAGES_DOCUMENT_TYPE), true); this.lib = lib; } @@ -52,32 +56,37 @@ public class CacheLibrary extends BasicLibrary { } @Override - protected List getMetas(Progress pg) throws IOException { + protected synchronized List getMetas(Progress pg) throws IOException { + // We make sure that cached metas have precedence + if (pg == null) { pg = new Progress(); } - if (metas == null) { - metas = lib.getMetas(pg); + if (metasMixed == null) { + if (metasReal == null) { + metasReal = lib.getMetas(pg); + } + + metasMixed = new ArrayList(); + TreeSet cachedLuids = new TreeSet(); + for (MetaData cachedMeta : cacheLib.getMetas(null)) { + metasMixed.add(cachedMeta); + cachedLuids.add(cachedMeta.getLuid()); + } + for (MetaData realMeta : metasReal) { + if (!cachedLuids.contains(realMeta.getLuid())) { + metasMixed.add(realMeta); + } + } } pg.done(); - return metas; + return new ArrayList(metasMixed); } @Override - public synchronized MetaData getInfo(String luid) throws IOException { - MetaData info = cacheLib.getInfo(luid); - if (info == null) { - info = lib.getInfo(luid); - } - - return info; - } - - @Override - public synchronized Story getStory(String luid, MetaData meta, Progress pg) - throws IOException { + public synchronized Story getStory(String luid, MetaData meta, Progress pg) throws IOException { if (pg == null) { pg = new Progress(); } @@ -92,10 +101,10 @@ public class CacheLibrary extends BasicLibrary { if (!isCached(luid)) { try { cacheLib.imprt(lib, luid, pgImport); - updateInfo(cacheLib.getInfo(luid)); + updateMetaCache(metasMixed, cacheLib.getInfo(luid)); pgImport.done(); } catch (IOException e) { - Instance.getTraceHandler().error(e); + Instance.getInstance().getTraceHandler().error(e); } pgImport.done(); @@ -110,8 +119,7 @@ public class CacheLibrary extends BasicLibrary { } @Override - public synchronized File getFile(final String luid, Progress pg) - throws IOException { + public synchronized File getFile(final String luid, Progress pg) throws IOException { if (pg == null) { pg = new Progress(); } @@ -213,8 +221,29 @@ public class CacheLibrary extends BasicLibrary { cacheLib.setAuthorCover(author, getCover(luid)); } + /** + * Invalidate the {@link Story} cache (when the content has changed, but we + * already have it) with the new given meta. + *

+ * Make sure to always use {@link MetaData} from the cached library + * in priority, here. + * + * @param meta + * the {@link Story} to clear from the cache + * + * @throws IOException + * in case of IOException + */ @Override + @Deprecated protected void updateInfo(MetaData meta) throws IOException { + throw new IOException( + "This method is not supported in a CacheLibrary, please use updateMetaCache"); + } + + // relplace the meta in Metas by Meta, add it if needed + // return TRUE = added + private boolean updateMetaCache(List metas, MetaData meta) { if (meta != null && metas != null) { boolean changed = false; for (int i = 0; i < metas.size(); i++) { @@ -226,32 +255,40 @@ public class CacheLibrary extends BasicLibrary { if (!changed) { metas.add(meta); + return true; } } - - cacheLib.updateInfo(meta); - lib.updateInfo(meta); + + return false; } @Override protected void invalidateInfo(String luid) { if (luid == null) { - metas = null; - } else if (metas != null) { + metasReal = null; + metasMixed = null; + } else { + invalidateInfo(metasReal, luid); + invalidateInfo(metasMixed, luid); + } + + cacheLib.invalidateInfo(luid); + lib.invalidateInfo(luid); + } + + // luid cannot be null + private void invalidateInfo(List metas, String luid) { + if (metas != null) { for (int i = 0; i < metas.size(); i++) { if (metas.get(i).getLuid().equals(luid)) { metas.remove(i--); } } } - - cacheLib.invalidateInfo(luid); - lib.invalidateInfo(luid); } @Override - public synchronized Story save(Story story, String luid, Progress pg) - throws IOException { + public synchronized Story save(Story story, String luid, Progress pg) throws IOException { Progress pgLib = new Progress(); Progress pgCacheLib = new Progress(); @@ -264,9 +301,10 @@ public class CacheLibrary extends BasicLibrary { pg.addProgress(pgCacheLib, 1); story = lib.save(story, luid, pgLib); + updateMetaCache(metasReal, story.getMeta()); + story = cacheLib.save(story, story.getMeta().getLuid(), pgCacheLib); - - updateInfo(story.getMeta()); + updateMetaCache(metasMixed, story.getMeta()); return story; } @@ -282,8 +320,8 @@ public class CacheLibrary extends BasicLibrary { } @Override - protected synchronized void changeSTA(String luid, String newSource, - String newTitle, String newAuthor, Progress pg) throws IOException { + protected synchronized void changeSTA(String luid, String newSource, String newTitle, String newAuthor, Progress pg) + throws IOException { if (pg == null) { pg = new Progress(); } @@ -312,18 +350,15 @@ public class CacheLibrary extends BasicLibrary { meta.setAuthor(newAuthor); pg.done(); - invalidateInfo(luid); + if (isCached(luid)) { + updateMetaCache(metasMixed, meta); + updateMetaCache(metasReal, lib.getInfo(luid)); + } else { + updateMetaCache(metasReal, meta); + } } - /** - * Check if the {@link Story} denoted by this Library UID is present in the - * cache. - * - * @param luid - * the Library UID - * - * @return TRUE if it is - */ + @Override public boolean isCached(String luid) { try { return cacheLib.getInfo(luid) != null; @@ -332,18 +367,7 @@ public class CacheLibrary extends BasicLibrary { } } - /** - * Clear the {@link Story} from the cache. - *

- * The next time we try to retrieve the {@link Story}, it may be required to - * cache it again. - * - * @param luid - * the story to clear - * - * @throws IOException - * in case of I/O error - */ + @Override public void clearFromCache(String luid) throws IOException { if (isCached(luid)) { cacheLib.delete(luid); @@ -351,7 +375,7 @@ public class CacheLibrary extends BasicLibrary { } @Override - public MetaData imprt(URL url, Progress pg) throws IOException { + public synchronized MetaData imprt(URL url, Progress pg) throws IOException { if (pg == null) { pg = new Progress(); } @@ -363,10 +387,10 @@ public class CacheLibrary extends BasicLibrary { pg.addProgress(pgCache, 3); MetaData meta = lib.imprt(url, pgImprt); - updateInfo(meta); - + updateMetaCache(metasReal, meta); + metasMixed = null; clearFromCache(meta.getLuid()); - + pg.done(); return meta; } diff --git a/library/LocalLibrary.java b/library/LocalLibrary.java index ffcd8af..80d216b 100644 --- a/library/LocalLibrary.java +++ b/library/LocalLibrary.java @@ -13,6 +13,8 @@ import java.util.Map; import be.nikiroo.fanfix.Instance; import be.nikiroo.fanfix.bundles.Config; +import be.nikiroo.fanfix.bundles.ConfigBundle; +import be.nikiroo.fanfix.bundles.UiConfigBundle; import be.nikiroo.fanfix.data.MetaData; import be.nikiroo.fanfix.data.Story; import be.nikiroo.fanfix.output.BasicOutput; @@ -42,13 +44,14 @@ public class LocalLibrary extends BasicLibrary { /** * Create a new {@link LocalLibrary} with the given back-end directory. * - * @param baseDir - * the directory where to find the {@link Story} objects + * @param baseDir the directory where to find the {@link Story} objects + * @param config the configuration used to know which kind of default + * {@link OutputType} to use for images and non-images stories */ - public LocalLibrary(File baseDir) { - this(baseDir, Instance.getConfig().getString( - Config.FILE_FORMAT_NON_IMAGES_DOCUMENT_TYPE), Instance.getConfig() - .getString(Config.FILE_FORMAT_IMAGES_DOCUMENT_TYPE), false); + public LocalLibrary(File baseDir, ConfigBundle config) { + this(baseDir, // + config.getString(Config.FILE_FORMAT_NON_IMAGES_DOCUMENT_TYPE), + config.getString(Config.FILE_FORMAT_IMAGES_DOCUMENT_TYPE), false); } /** @@ -95,14 +98,13 @@ public class LocalLibrary extends BasicLibrary { } @Override - protected List getMetas(Progress pg) { + protected synchronized List getMetas(Progress pg) { return new ArrayList(getStories(pg).keySet()); } @Override public File getFile(String luid, Progress pg) throws IOException { - Instance.getTraceHandler().trace( - this.getClass().getSimpleName() + ": get file for " + luid); + Instance.getInstance().getTraceHandler().trace(this.getClass().getSimpleName() + ": get file for " + luid); File file = null; String mess = "no file found for "; @@ -114,9 +116,8 @@ public class LocalLibrary extends BasicLibrary { file = files[1]; } - Instance.getTraceHandler().trace( - this.getClass().getSimpleName() + ": " + mess + luid + " (" - + meta.getTitle() + ")"); + Instance.getInstance().getTraceHandler() + .trace(this.getClass().getSimpleName() + ": " + mess + luid + " (" + meta.getTitle() + ")"); return file; } @@ -137,7 +138,7 @@ public class LocalLibrary extends BasicLibrary { meta = InfoReader.readMeta(infoFile, true); return meta.getCover(); } catch (IOException e) { - Instance.getTraceHandler().error(e); + Instance.getInstance().getTraceHandler().error(e); } } } @@ -205,7 +206,7 @@ public class LocalLibrary extends BasicLibrary { InfoCover.writeInfo(newDir, name, meta); relatedFile.getParentFile().delete(); } catch (IOException e) { - Instance.getTraceHandler().error(e); + Instance.getInstance().getTraceHandler().error(e); } } else { relatedFile.renameTo(new File(newDir, relatedFile.getName())); @@ -213,7 +214,7 @@ public class LocalLibrary extends BasicLibrary { } } - invalidateInfo(); + updateInfo(meta); } @Override @@ -242,10 +243,8 @@ public class LocalLibrary extends BasicLibrary { } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { - Instance.getTraceHandler().error( - new IOException( - "Cannot load the existing custom source cover: " - + cover, e)); + Instance.getInstance().getTraceHandler() + .error(new IOException("Cannot load the existing custom source cover: " + cover, e)); } } } @@ -277,10 +276,8 @@ public class LocalLibrary extends BasicLibrary { } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { - Instance.getTraceHandler().error( - new IOException( - "Cannot load the existing custom author cover: " - + cover, e)); + Instance.getInstance().getTraceHandler() + .error(new IOException("Cannot load the existing custom author cover: " + cover, e)); } } @@ -310,12 +307,12 @@ public class LocalLibrary extends BasicLibrary { dir.mkdirs(); File cover = new File(dir, ".cover"); try { - Instance.getCache().saveAsImage(coverImage, cover, true); + Instance.getInstance().getCache().saveAsImage(coverImage, cover, true); if (sourceCovers != null) { sourceCovers.put(source, coverImage); } } catch (IOException e) { - Instance.getTraceHandler().error(e); + Instance.getInstance().getTraceHandler().error(e); } } @@ -331,12 +328,12 @@ public class LocalLibrary extends BasicLibrary { File cover = getAuthorCoverFile(author); cover.getParentFile().mkdirs(); try { - Instance.getCache().saveAsImage(coverImage, cover, true); + Instance.getInstance().getCache().saveAsImage(coverImage, cover, true); if (authorCovers != null) { authorCovers.put(author, coverImage); } } catch (IOException e) { - Instance.getTraceHandler().error(e); + Instance.getInstance().getTraceHandler().error(e); } } @@ -516,7 +513,7 @@ public class LocalLibrary extends BasicLibrary { private File getAuthorCoverFile(String author) { File aDir = new File(baseDir, "_AUTHORS"); String hash = StringUtils.getMd5Hash(author); - String ext = Instance.getConfig().getString(Config.FILE_FORMAT_IMAGE_FORMAT_COVER); + String ext = Instance.getInstance().getConfig().getString(Config.FILE_FORMAT_IMAGE_FORMAT_COVER); return new File(aDir, hash + "." + ext.toLowerCase()); } @@ -562,8 +559,7 @@ public class LocalLibrary extends BasicLibrary { } String coverExt = "." - + Instance.getConfig().getString(Config.FILE_FORMAT_IMAGE_FORMAT_COVER) - .toLowerCase(); + + Instance.getInstance().getConfig().getString(Config.FILE_FORMAT_IMAGE_FORMAT_COVER).toLowerCase(); File coverFile = new File(path + coverExt); if (!coverFile.exists()) { coverFile = new File(path.substring(0, @@ -675,9 +671,8 @@ public class LocalLibrary extends BasicLibrary { } catch (IOException e) { // We should not have not-supported files in the // library - Instance.getTraceHandler().error( - new IOException("Cannot load file from library: " - + infoFileOrSubdir, e)); + Instance.getInstance().getTraceHandler() + .error(new IOException("Cannot load file from library: " + infoFileOrSubdir, e)); } } diff --git a/library/MetaResultList.java b/library/MetaResultList.java new file mode 100644 index 0000000..886defe --- /dev/null +++ b/library/MetaResultList.java @@ -0,0 +1,168 @@ +package be.nikiroo.fanfix.library; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import be.nikiroo.fanfix.data.MetaData; + +public class MetaResultList { + private List metas; + + // Lazy lists: + // TODO: sync-protect them? + private List sources; + private List authors; + private List tags; + + // can be null (will consider it empty) + public MetaResultList(List metas) { + if (metas == null) { + metas = new ArrayList(); + } + + Collections.sort(metas); + this.metas = metas; + } + + // not NULL + // sorted + public List getMetas() { + return metas; + } + + public List getSources() { + if (sources == null) { + sources = new ArrayList(); + for (MetaData meta : metas) { + if (!sources.contains(meta.getSource())) + sources.add(meta.getSource()); + } + } + + return sources; + } + + // A -> (A), A/ -> (A, A/*) if we can find something for "*" + public List getSources(String source) { + List linked = new ArrayList(); + if (source != null && !source.isEmpty()) { + if (!source.endsWith("/")) { + linked.add(source); + } else { + linked.add(source.substring(0, source.length() - 1)); + for (String src : getSources()) { + if (src.startsWith(source)) { + linked.add(src); + } + } + } + } + + return linked; + } + + public List getAuthors() { + if (authors == null) { + authors = new ArrayList(); + for (MetaData meta : metas) { + if (!authors.contains(meta.getAuthor())) + authors.add(meta.getAuthor()); + } + } + + return authors; + } + + public List getTags() { + if (tags == null) { + tags = new ArrayList(); + for (MetaData meta : metas) { + for (String tag : meta.getTags()) { + if (!tags.contains(tag)) + tags.add(tag); + } + } + } + + return authors; + } + + // helper + public List filter(String source, String author, String tag) { + List sources = source == null ? null : Arrays.asList(source); + List authors = author == null ? null : Arrays.asList(author); + List tags = tag == null ? null : Arrays.asList(tag); + + return filter(sources, authors, tags); + } + + // null or empty -> no check, rest = must be included + // source: a source ending in "/" means "this or any source starting with this", + // i;e., to enable source hierarchy + // + sorted + public List filter(List sources, List authors, List tags) { + if (sources != null && sources.isEmpty()) + sources = null; + if (authors != null && authors.isEmpty()) + authors = null; + if (tags != null && tags.isEmpty()) + tags = null; + + // Quick check + if (sources == null && authors == null && tags == null) { + return metas; + } + + // allow "sources/" hierarchy + if (sources != null) { + List folders = new ArrayList(); + List leaves = new ArrayList(); + for (String source : sources) { + if (source.endsWith("/")) { + if (!folders.contains(source)) + folders.add(source); + } else { + if (!leaves.contains(source)) + leaves.add(source); + } + } + + sources = leaves; + for (String folder : folders) { + for (String otherLeaf : getSources(folder)) { + if (!sources.contains(otherLeaf)) { + sources.add(otherLeaf); + } + } + } + } + + List result = new ArrayList(); + for (MetaData meta : metas) { + if (sources != null && !sources.contains(meta.getSource())) { + continue; + } + if (authors != null && !authors.contains(meta.getAuthor())) { + continue; + } + + if (tags != null) { + boolean keep = false; + for (String thisTag : meta.getTags()) { + if (tags.contains(thisTag)) + keep = true; + } + + if (!keep) + continue; + } + + result.add(meta); + } + + Collections.sort(result); + return result; + } +} diff --git a/library/RemoteLibrary.java b/library/RemoteLibrary.java index ce4305a..65be7b1 100644 --- a/library/RemoteLibrary.java +++ b/library/RemoteLibrary.java @@ -124,9 +124,9 @@ public class RemoteLibrary extends BasicLibrary { @Override public Status getStatus() { - Instance.getTraceHandler().trace("Getting remote lib status..."); + Instance.getInstance().getTraceHandler().trace("Getting remote lib status..."); Status status = getStatusDo(); - Instance.getTraceHandler().trace("Remote lib status: " + status); + Instance.getInstance().getTraceHandler().trace("Remote lib status: " + status); return status; } @@ -443,6 +443,7 @@ public class RemoteLibrary extends BasicLibrary { public void action(ConnectActionClientObject action) throws Exception { action.send(new Object[] { subkey, "EXIT" }); + Thread.sleep(100); } }); } @@ -458,7 +459,7 @@ public class RemoteLibrary extends BasicLibrary { } @Override - protected List getMetas(Progress pg) throws IOException { + protected synchronized List getMetas(Progress pg) throws IOException { return getMetasList("*", pg); } @@ -559,7 +560,7 @@ public class RemoteLibrary extends BasicLibrary { @Override protected void onError(Exception e) { if (!(e instanceof IOException)) { - Instance.getTraceHandler().error(e); + Instance.getInstance().getTraceHandler().error(e); return; } diff --git a/library/RemoteLibraryServer.java b/library/RemoteLibraryServer.java index dc9688c..4f89a1f 100644 --- a/library/RemoteLibraryServer.java +++ b/library/RemoteLibraryServer.java @@ -80,7 +80,7 @@ public class RemoteLibraryServer extends ServerObject { */ public RemoteLibraryServer(String key, int port) throws IOException { super("Fanfix remote library", port, key); - setTraceHandler(Instance.getTraceHandler()); + setTraceHandler(Instance.getInstance().getTraceHandler()); } @Override @@ -110,8 +110,7 @@ public class RemoteLibraryServer extends ServerObject { } } - List whitelist = Instance.getConfig().getList( - Config.SERVER_WHITELIST); + List whitelist = Instance.getInstance().getConfig().getList(Config.SERVER_WHITELIST); if (whitelist == null) { whitelist = new ArrayList(); } @@ -120,10 +119,9 @@ public class RemoteLibraryServer extends ServerObject { wl = false; } - rw = Instance.getConfig().getBoolean(Config.SERVER_RW, rw); + rw = Instance.getInstance().getConfig().getBoolean(Config.SERVER_RW, rw); if (!subkey.isEmpty()) { - List allowed = Instance.getConfig().getList( - Config.SERVER_ALLOWED_SUBKEYS); + List allowed = Instance.getInstance().getConfig().getList(Config.SERVER_ALLOWED_SUBKEYS); if (allowed.contains(subkey)) { if ((subkey + "|").contains("|rw|")) { rw = true; @@ -203,7 +201,7 @@ public class RemoteLibraryServer extends ServerObject { if ("*".equals(args[0])) { Progress pg = createPgForwarder(action); - for (MetaData meta : Instance.getLibrary().getMetas(pg)) { + for (MetaData meta : Instance.getInstance().getLibrary().getMetas(pg)) { MetaData light; if (meta.getCover() == null) { light = meta; @@ -217,7 +215,7 @@ public class RemoteLibraryServer extends ServerObject { forcePgDoneSent(pg); } else { - MetaData meta = Instance.getLibrary().getInfo((String) args[0]); + MetaData meta = Instance.getInstance().getLibrary().getInfo((String) args[0]); MetaData light; if (meta.getCover() == null) { light = meta; @@ -240,7 +238,7 @@ public class RemoteLibraryServer extends ServerObject { return metas.toArray(new MetaData[0]); } else if ("GET_STORY".equals(command)) { - MetaData meta = Instance.getLibrary().getInfo((String) args[0]); + MetaData meta = Instance.getInstance().getLibrary().getInfo((String) args[0]); if (meta == null) { return null; } @@ -257,8 +255,7 @@ public class RemoteLibraryServer extends ServerObject { action.send(meta); action.rec(); - Story story = Instance.getLibrary() - .getStory((String) args[0], null); + Story story = Instance.getInstance().getLibrary().getStory((String) args[0], null); for (Object obj : breakStory(story)) { action.send(obj); action.rec(); @@ -280,7 +277,7 @@ public class RemoteLibraryServer extends ServerObject { } Story story = rebuildStory(list); - Instance.getLibrary().save(story, (String) args[0], null); + Instance.getInstance().getLibrary().save(story, (String) args[0], null); return story.getMeta().getLuid(); } else if ("IMPORT".equals(command)) { if (!rw) { @@ -289,8 +286,7 @@ public class RemoteLibraryServer extends ServerObject { } Progress pg = createPgForwarder(action); - MetaData meta = Instance.getLibrary().imprt( - new URL((String) args[0]), pg); + MetaData meta = Instance.getInstance().getLibrary().imprt(new URL((String) args[0]), pg); forcePgDoneSent(pg); return meta.getLuid(); } else if ("DELETE_STORY".equals(command)) { @@ -299,16 +295,14 @@ public class RemoteLibraryServer extends ServerObject { + args[0], false); } - Instance.getLibrary().delete((String) args[0]); + Instance.getInstance().getLibrary().delete((String) args[0]); } else if ("GET_COVER".equals(command)) { - return Instance.getLibrary().getCover((String) args[0]); + return Instance.getInstance().getLibrary().getCover((String) args[0]); } else if ("GET_CUSTOM_COVER".equals(command)) { if ("SOURCE".equals(args[0])) { - return Instance.getLibrary().getCustomSourceCover( - (String) args[1]); + return Instance.getInstance().getLibrary().getCustomSourceCover((String) args[1]); } else if ("AUTHOR".equals(args[0])) { - return Instance.getLibrary().getCustomAuthorCover( - (String) args[1]); + return Instance.getInstance().getLibrary().getCustomAuthorCover((String) args[1]); } else { return null; } @@ -319,21 +313,18 @@ public class RemoteLibraryServer extends ServerObject { } if ("SOURCE".equals(args[0])) { - Instance.getLibrary().setSourceCover((String) args[1], - (String) args[2]); + Instance.getInstance().getLibrary().setSourceCover((String) args[1], (String) args[2]); } else if ("AUTHOR".equals(args[0])) { - Instance.getLibrary().setAuthorCover((String) args[1], - (String) args[2]); + Instance.getInstance().getLibrary().setAuthorCover((String) args[1], (String) args[2]); } } else if ("CHANGE_STA".equals(command)) { if (!rw) { - throw new RemoteLibraryException("Read-Only remote library: " - + args[0] + ", " + args[1], false); + throw new RemoteLibraryException("Read-Only remote library: " + args[0] + ", " + args[1], false); } Progress pg = createPgForwarder(action); - Instance.getLibrary().changeSTA((String) args[0], (String) args[1], - (String) args[2], (String) args[3], pg); + Instance.getInstance().getLibrary().changeSTA((String) args[0], (String) args[1], (String) args[2], + (String) args[3], pg); forcePgDoneSent(pg); } else if ("EXIT".equals(command)) { if (!rw) { @@ -341,7 +332,7 @@ public class RemoteLibraryServer extends ServerObject { "Read-Only remote library: EXIT", false); } - stop(0, false); + stop(10000, false); } return null; diff --git a/output/BasicOutput.java b/output/BasicOutput.java index 15d8cc1..41634fa 100644 --- a/output/BasicOutput.java +++ b/output/BasicOutput.java @@ -63,10 +63,10 @@ public abstract class BasicOutput { StringId id = longDesc ? StringId.OUTPUT_DESC : StringId.OUTPUT_DESC_SHORT; - String desc = Instance.getTrans().getStringX(id, this.name()); + String desc = Instance.getInstance().getTrans().getStringX(id, this.name()); if (desc == null) { - desc = Instance.getTrans().getString(id, this.toString()); + desc = Instance.getInstance().getTrans().getString(id, this.toString()); } if (desc == null || desc.isEmpty()) { diff --git a/output/Cbz.java b/output/Cbz.java index 3d90082..ee671e7 100644 --- a/output/Cbz.java +++ b/output/Cbz.java @@ -23,7 +23,7 @@ class Cbz extends BasicOutput { File target = new File(targetDir, targetName); - dir = Instance.getTempFiles().createTempDir("fanfic-reader-cbz-dir"); + dir = Instance.getInstance().getTempFiles().createTempDir("fanfic-reader-cbz-dir"); try { // will also save the images! (except the cover -> false) BasicOutput diff --git a/output/Epub.java b/output/Epub.java index b7401d3..fc2dc8c 100644 --- a/output/Epub.java +++ b/output/Epub.java @@ -36,7 +36,7 @@ class Epub extends BasicOutput { String targetNameOrig = targetName; targetName += getDefaultExtension(false); - tmpDir = Instance.getTempFiles().createTempDir("fanfic-reader-epub"); + tmpDir = Instance.getInstance().getTempFiles().createTempDir("fanfic-reader-epub"); tmpDir.delete(); if (!tmpDir.mkdir()) { @@ -137,10 +137,9 @@ class Epub extends BasicOutput { if (story.getMeta() != null && story.getMeta().getCover() != null) { File file = new File(images, "cover"); try { - Instance.getCache().saveAsImage(story.getMeta().getCover(), - file, true); + Instance.getInstance().getCache().saveAsImage(story.getMeta().getCover(), file, true); } catch (Exception e) { - Instance.getTraceHandler().error(e); + Instance.getInstance().getTraceHandler().error(e); } } @@ -246,8 +245,7 @@ class Epub extends BasicOutput { break; case IMAGE: File file = new File(images, getCurrentImageBestName(false)); - Instance.getCache().saveAsImage(para.getContentImage(), file, - nextParaIsCover); + Instance.getInstance().getCache().saveAsImage(para.getContentImage(), file, nextParaIsCover); writer.write(" page image"); break; @@ -358,11 +356,10 @@ class Epub extends BasicOutput { private void generateNcx(Chapter chap, StringBuilder builder, int navPoint) { String name; if (chap.getName() != null && !chap.getName().isEmpty()) { - name = Instance.getTrans().getString(StringId.CHAPTER_NAMED, - chap.getNumber(), chap.getName()); + name = Instance.getInstance().getTrans().getString(StringId.CHAPTER_NAMED, chap.getNumber(), + chap.getName()); } else { - name = Instance.getTrans().getString(StringId.CHAPTER_UNNAMED, - chap.getNumber()); + name = Instance.getInstance().getTrans().getString(StringId.CHAPTER_UNNAMED, chap.getNumber()); } String nnn = String.format("%03d", (navPoint - 2)); @@ -440,7 +437,7 @@ class Epub extends BasicOutput { builder.append("\n "); if (story.getMeta() != null && story.getMeta().getCover() != null) { - String format = Instance.getConfig() + String format = Instance.getInstance().getConfig() .getString(Config.FILE_FORMAT_IMAGE_FORMAT_COVER) .toLowerCase(); builder.append("\n "); diff --git a/output/Html.java b/output/Html.java index ca802a5..da79466 100644 --- a/output/Html.java +++ b/output/Html.java @@ -50,8 +50,7 @@ class Html extends BasicOutput { .process(story, dir, targetNameOrig); if (story.getMeta().getCover() != null) { - Instance.getCache().saveAsImage(story.getMeta().getCover(), - new File(dir, "cover"), true); + Instance.getInstance().getCache().saveAsImage(story.getMeta().getCover(), new File(dir, "cover"), true); } return target; @@ -91,7 +90,7 @@ class Html extends BasicOutput { author = meta.getAuthor(); } - String format = Instance.getConfig() + String format = Instance.getInstance().getConfig() .getString(Config.FILE_FORMAT_IMAGE_FORMAT_COVER).toLowerCase(); InputStream inStyle = getClass().getResourceAsStream("html.style.css"); diff --git a/output/InfoCover.java b/output/InfoCover.java index 6bfa4dd..d8ca49a 100644 --- a/output/InfoCover.java +++ b/output/InfoCover.java @@ -46,7 +46,7 @@ public class InfoCover { meta.isImageDocument() ? "true" : "false"); writeMeta(infoWriter, "TYPE", meta.getType()); if (meta.getCover() != null) { - String format = Instance.getConfig() + String format = Instance.getInstance().getConfig() .getString(Config.FILE_FORMAT_IMAGE_FORMAT_COVER).toLowerCase(); writeMeta(infoWriter, "COVER", targetName + "." + format); } else { @@ -71,12 +71,10 @@ public class InfoCover { MetaData meta) { if (meta != null && meta.getCover() != null) { try { - Instance.getCache().saveAsImage(meta.getCover(), - new File(targetDir, targetName), true); + Instance.getInstance().getCache().saveAsImage(meta.getCover(), new File(targetDir, targetName), true); } catch (IOException e) { // Allow to continue without cover - Instance.getTraceHandler().error( - new IOException("Failed to save the cover image", e)); + Instance.getInstance().getTraceHandler().error(new IOException("Failed to save the cover image", e)); } } } diff --git a/output/InfoText.java b/output/InfoText.java index cce715d..935da87 100644 --- a/output/InfoText.java +++ b/output/InfoText.java @@ -9,14 +9,10 @@ import be.nikiroo.fanfix.data.Paragraph.ParagraphType; class InfoText extends Text { // quote chars - private char openQuote = Instance.getTrans().getCharacter( - StringId.OPEN_SINGLE_QUOTE); - private char closeQuote = Instance.getTrans().getCharacter( - StringId.CLOSE_SINGLE_QUOTE); - private char openDoubleQuote = Instance.getTrans().getCharacter( - StringId.OPEN_DOUBLE_QUOTE); - private char closeDoubleQuote = Instance.getTrans().getCharacter( - StringId.CLOSE_DOUBLE_QUOTE); + private char openQuote = Instance.getInstance().getTrans().getCharacter(StringId.OPEN_SINGLE_QUOTE); + private char closeQuote = Instance.getInstance().getTrans().getCharacter(StringId.CLOSE_SINGLE_QUOTE); + private char openDoubleQuote = Instance.getInstance().getTrans().getCharacter(StringId.OPEN_DOUBLE_QUOTE); + private char closeDoubleQuote = Instance.getInstance().getTrans().getCharacter(StringId.CLOSE_DOUBLE_QUOTE); @Override public String getDefaultExtension(boolean readerTarget) { @@ -28,11 +24,10 @@ class InfoText extends Text { writer.write("\n"); if (chap.getName() != null && !chap.getName().isEmpty()) { - writer.write(Instance.getTrans().getString(StringId.CHAPTER_NAMED, - chap.getNumber(), chap.getName())); + writer.write(Instance.getInstance().getTrans().getString(StringId.CHAPTER_NAMED, chap.getNumber(), + chap.getName())); } else { - writer.write(Instance.getTrans().getString( - StringId.CHAPTER_UNNAMED, chap.getNumber())); + writer.write(Instance.getInstance().getTrans().getString(StringId.CHAPTER_UNNAMED, chap.getNumber())); } writer.write("\n\n"); diff --git a/output/LaTeX.java b/output/LaTeX.java index 321556f..a15e67c 100644 --- a/output/LaTeX.java +++ b/output/LaTeX.java @@ -19,14 +19,10 @@ class LaTeX extends BasicOutput { private boolean lastWasQuote = false; // quote chars - private char openQuote = Instance.getTrans().getCharacter( - StringId.OPEN_SINGLE_QUOTE); - private char closeQuote = Instance.getTrans().getCharacter( - StringId.CLOSE_SINGLE_QUOTE); - private char openDoubleQuote = Instance.getTrans().getCharacter( - StringId.OPEN_DOUBLE_QUOTE); - private char closeDoubleQuote = Instance.getTrans().getCharacter( - StringId.CLOSE_DOUBLE_QUOTE); + private char openQuote = Instance.getInstance().getTrans().getCharacter(StringId.OPEN_SINGLE_QUOTE); + private char closeQuote = Instance.getInstance().getTrans().getCharacter(StringId.CLOSE_SINGLE_QUOTE); + private char openDoubleQuote = Instance.getInstance().getTrans().getCharacter(StringId.OPEN_DOUBLE_QUOTE); + private char closeDoubleQuote = Instance.getInstance().getTrans().getCharacter(StringId.CLOSE_DOUBLE_QUOTE); @Override public File process(Story story, File targetDir, String targetName) @@ -66,10 +62,9 @@ class LaTeX extends BasicOutput { author = "\\author{" + latexEncode(meta.getAuthor()) + "}"; lang = meta.getLang().toLowerCase(); if (lang != null && !lang.isEmpty()) { - lang = Instance.getConfig().getStringX(Config.CONF_LATEX_LANG, lang); + lang = Instance.getInstance().getConfig().getStringX(Config.CONF_LATEX_LANG, lang); if (lang == null) { - System.err.println(Instance.getTrans().getString( - StringId.LATEX_LANG_UNKNOWN, lang)); + System.err.println(Instance.getInstance().getTrans().getString(StringId.LATEX_LANG_UNKNOWN, lang)); } } } diff --git a/output/Text.java b/output/Text.java index 4a45e54..f0516dc 100644 --- a/output/Text.java +++ b/output/Text.java @@ -62,8 +62,7 @@ class Text extends BasicOutput { writer.write(title); writer.write("\n"); if (author != null && !author.isEmpty()) { - writer.write(Instance.getTrans().getString(StringId.BY) + " " - + author); + writer.write(Instance.getInstance().getTrans().getString(StringId.BY) + " " + author); } if (date != null && !date.isEmpty()) { writer.write(" ("); @@ -82,11 +81,9 @@ class Text extends BasicOutput { protected void writeChapterHeader(Chapter chap) throws IOException { String txt; if (chap.getName() != null && !chap.getName().isEmpty()) { - txt = Instance.getTrans().getString(StringId.CHAPTER_NAMED, - chap.getNumber(), chap.getName()); + txt = Instance.getInstance().getTrans().getString(StringId.CHAPTER_NAMED, chap.getNumber(), chap.getName()); } else { - txt = Instance.getTrans().getString(StringId.CHAPTER_UNNAMED, - chap.getNumber()); + txt = Instance.getInstance().getTrans().getString(StringId.CHAPTER_UNNAMED, chap.getNumber()); } writer.write("\n" + txt + "\n"); @@ -106,11 +103,9 @@ class Text extends BasicOutput { if (para.getType() == ParagraphType.IMAGE) { File file = new File(targetDir, getCurrentImageBestName(true)); try { - Instance.getCache().saveAsImage(para.getContentImage(), file, - nextParaIsCover); + Instance.getInstance().getCache().saveAsImage(para.getContentImage(), file, nextParaIsCover); } catch (IOException e) { - Instance.getTraceHandler().error( - new IOException("Cannot save an image", e)); + Instance.getInstance().getTraceHandler().error(new IOException("Cannot save an image", e)); } } diff --git a/reader/BasicReader.java b/reader/BasicReader.java index 61769c0..7f79da3 100644 --- a/reader/BasicReader.java +++ b/reader/BasicReader.java @@ -30,7 +30,7 @@ import be.nikiroo.utils.serial.SerialUtils; * @author niki */ public abstract class BasicReader implements Reader { - private static BasicLibrary defaultLibrary = Instance.getLibrary(); + private static BasicLibrary defaultLibrary = Instance.getInstance().getLibrary(); private static ReaderType defaultType = ReaderType.GUI; private BasicLibrary lib; @@ -42,7 +42,7 @@ public abstract class BasicReader implements Reader { * Take the default reader type configuration from the config file. */ static { - String typeString = Instance.getConfig().getString(Config.READER_TYPE); + String typeString = Instance.getInstance().getConfig().getString(Config.READER_TYPE); if (typeString != null && !typeString.isEmpty()) { try { ReaderType type = ReaderType.valueOf(typeString.toUpperCase()); @@ -137,9 +137,8 @@ public abstract class BasicReader implements Reader { .getTypeName()); } } catch (Exception e) { - Instance.getTraceHandler().error( - new Exception("Cannot create a reader of type: " - + defaultType + " (Not compiled in?)", e)); + Instance.getInstance().getTraceHandler() + .error(new Exception("Cannot create a reader of type: " + defaultType + " (Not compiled in?)", e)); } return null; @@ -292,11 +291,9 @@ public abstract class BasicReader implements Reader { throws IOException { String program = null; if (meta.isImageDocument()) { - program = Instance.getUiConfig().getString( - UiConfig.IMAGES_DOCUMENT_READER); + program = Instance.getInstance().getUiConfig().getString(UiConfig.IMAGES_DOCUMENT_READER); } else { - program = Instance.getUiConfig().getString( - UiConfig.NON_IMAGES_DOCUMENT_READER); + program = Instance.getInstance().getUiConfig().getString(UiConfig.NON_IMAGES_DOCUMENT_READER); } if (program != null && program.trim().isEmpty()) { @@ -330,10 +327,8 @@ public abstract class BasicReader implements Reader { for (String starter : new String[] { "xdg-open", "open", "see", "start", "run" }) { try { - Instance.getTraceHandler().trace( - "starting external program"); - proc = Runtime.getRuntime().exec( - new String[] { starter, target.getAbsolutePath() }); + Instance.getInstance().getTraceHandler().trace("starting external program"); + proc = Runtime.getRuntime().exec(new String[] { starter, target.getAbsolutePath() }); ok = true; break; } catch (IOException e) { @@ -343,7 +338,7 @@ public abstract class BasicReader implements Reader { throw new IOException("Cannot find a program to start the file"); } } else { - Instance.getTraceHandler().trace("starting external program"); + Instance.getInstance().getTraceHandler().trace("starting external program"); proc = Runtime.getRuntime().exec( new String[] { program, target.getAbsolutePath() }); } diff --git a/searchable/BasicSearchable.java b/searchable/BasicSearchable.java index d38505e..b943abd 100644 --- a/searchable/BasicSearchable.java +++ b/searchable/BasicSearchable.java @@ -222,8 +222,7 @@ public abstract class BasicSearchable { * in case of I/O error */ protected Document load(URL url, boolean stable) throws IOException { - return DataUtil.load(Instance.getCache().open(url, support, stable), - "UTF-8", url.toString()); + return DataUtil.load(Instance.getInstance().getCache().open(url, support, stable), "UTF-8", url.toString()); } /** @@ -247,7 +246,7 @@ public abstract class BasicSearchable { case FANFICTION: support = new Fanfiction(type); break; - case MANGAFOX: + case MANGAHUB: // TODO break; case E621: diff --git a/searchable/Fanfiction.java b/searchable/Fanfiction.java index c2dfd5d..e2fba1f 100644 --- a/searchable/Fanfiction.java +++ b/searchable/Fanfiction.java @@ -285,8 +285,7 @@ class Fanfiction extends BasicSearchable { String coverUrl = cover.absUrl("src"); try { - InputStream in = Instance.getCache().open( - new URL(coverUrl), getSupport(), true); + InputStream in = Instance.getInstance().getCache().open(new URL(coverUrl), getSupport(), true); try { meta.setCover(new Image(in)); } finally { @@ -294,10 +293,8 @@ class Fanfiction extends BasicSearchable { } } catch (Exception e) { // Should not happen on Fanfiction.net - Instance.getTraceHandler().error( - new Exception( - "Cannot download cover for Fanfiction story in search mode: " - + meta.getTitle(), e)); + Instance.getInstance().getTraceHandler().error(new Exception( + "Cannot download cover for Fanfiction story in search mode: " + meta.getTitle(), e)); } } } @@ -337,8 +334,7 @@ class Fanfiction extends BasicSearchable { } meta.setResume(getSupport().makeChapter(new URL(sourceUrl), 0, - Instance.getTrans().getString(StringId.DESCRIPTION), - resume)); + Instance.getInstance().getTrans().getString(StringId.DESCRIPTION), resume)); } // How are the tags ordered? diff --git a/searchable/MangaLel.java b/searchable/MangaLel.java index 3e2924f..5ba21a0 100644 --- a/searchable/MangaLel.java +++ b/searchable/MangaLel.java @@ -89,9 +89,8 @@ class MangaLel extends BasicSearchable { private List getResults(String sourceUrl) throws IOException { List metas = new ArrayList(); - Document doc = DataUtil.load( - Instance.getCache().open(new URL(sourceUrl), getSupport(), - false), "UTF-8", sourceUrl); + Document doc = DataUtil.load(Instance.getInstance().getCache().open(new URL(sourceUrl), getSupport(), false), + "UTF-8", sourceUrl); for (Element result : doc.getElementsByClass("rechercheAffichage")) { Element a = result.getElementsByTag("a").first(); @@ -123,13 +122,8 @@ class MangaLel extends BasicSearchable { meta.setAuthor(getVal(tab, 1)); meta.setTags(Arrays.asList(getVal(tab, 2).split(" "))); - meta.setResume(getSupport() - .makeChapter( - new URL(sourceUrl), - 0, - Instance.getTrans().getString( - StringId.DESCRIPTION), - getVal(tab, 5))); + meta.setResume(getSupport().makeChapter(new URL(sourceUrl), 0, + Instance.getInstance().getTrans().getString(StringId.DESCRIPTION), getVal(tab, 5))); } Element img = result.getElementsByTag("img").first(); @@ -143,8 +137,8 @@ class MangaLel extends BasicSearchable { String coverUrl = img.absUrl("src"); try { - InputStream in = Instance.getCache().open( - new URL(coverUrl), getSupport(), true); + InputStream in = Instance.getInstance().getCache().open(new URL(coverUrl), getSupport(), + true); try { meta.setCover(new Image(in)); } finally { @@ -152,15 +146,13 @@ class MangaLel extends BasicSearchable { } } catch (Exception e) { // Happen often on MangaLEL... - Instance.getTraceHandler().trace( - "Cannot download cover for MangaLEL story in search mode: " - + meta.getTitle()); + Instance.getInstance().getTraceHandler().trace( + "Cannot download cover for MangaLEL story in search mode: " + meta.getTitle()); } } catch (Exception e) { // no project id... cannot use the story :( - Instance.getTraceHandler().error( - "Cannot find ProjectId for MangaLEL story in search mode: " - + meta.getTitle()); + Instance.getInstance().getTraceHandler() + .error("Cannot find ProjectId for MangaLEL story in search mode: " + meta.getTitle()); } } diff --git a/supported/BasicSupport.java b/supported/BasicSupport.java index d3c0ebb..bc91e8b 100644 --- a/supported/BasicSupport.java +++ b/supported/BasicSupport.java @@ -224,8 +224,7 @@ public abstract class BasicSupport { */ protected Document loadDocument(URL source) throws IOException { String url = getCanonicalUrl(source).toString(); - return DataUtil.load(Instance.getCache().open(source, this, false), - "UTF-8", url.toString()); + return DataUtil.load(Instance.getInstance().getCache().open(source, this, false), "UTF-8", url.toString()); } /** @@ -284,12 +283,9 @@ public abstract class BasicSupport { pg.setProgress(60); if (getDesc) { - String descChapterName = Instance.getTrans().getString( - StringId.DESCRIPTION); - story.getMeta().setResume( - bsPara.makeChapter(this, source, 0, - descChapterName, // - getDesc(), isHtml(), null)); + String descChapterName = Instance.getInstance().getTrans().getString(StringId.DESCRIPTION); + story.getMeta().setResume(bsPara.makeChapter(this, source, 0, descChapterName, // + getDesc(), isHtml(), null)); } pg.done(); @@ -493,8 +489,8 @@ public abstract class BasicSupport { case TEXT: support = new Text(); break; - case MANGAFOX: - support = new MangaFox(); + case MANGAHUB: + support = new MangaHub(); break; case E621: support = new E621(); diff --git a/supported/BasicSupportHelper.java b/supported/BasicSupportHelper.java index 41716df..b5c7bb9 100644 --- a/supported/BasicSupportHelper.java +++ b/supported/BasicSupportHelper.java @@ -26,10 +26,9 @@ public class BasicSupportHelper { * @return the cover if any, or NULL */ public Image getDefaultCover(String subject) { - if (subject != null && !subject.isEmpty() - && Instance.getCoverDir() != null) { + if (subject != null && !subject.isEmpty() && Instance.getInstance().getCoverDir() != null) { try { - File fileCover = new File(Instance.getCoverDir(), subject); + File fileCover = new File(Instance.getInstance().getCoverDir(), subject); return getImage(null, fileCover.toURI().toURL(), subject); } catch (MalformedURLException e) { } @@ -81,7 +80,7 @@ public class BasicSupportHelper { } InputStream in = null; try { - in = Instance.getCache().open(url, support, true); + in = Instance.getInstance().getCache().open(url, support, true); return new Image(in); } catch (IOException e) { } finally { @@ -156,8 +155,7 @@ public class BasicSupportHelper { // try for URLs try { for (String ext : getImageExt(true)) { - if (Instance.getCache() - .check(new URL(line + ext), true)) { + if (Instance.getInstance().getCache().check(new URL(line + ext), true)) { url = new URL(line + ext); break; } @@ -168,7 +166,7 @@ public class BasicSupportHelper { for (String ext : getImageExt(true)) { try { url = new URL(line + ext); - Instance.getCache().refresh(url, support, true); + Instance.getInstance().getCache().refresh(url, support, true); break; } catch (IOException e) { // no image with this ext @@ -184,7 +182,7 @@ public class BasicSupportHelper { // refresh the cached file if (url != null) { try { - Instance.getCache().refresh(url, support, true); + Instance.getInstance().getCache().refresh(url, support, true); } catch (IOException e) { // woops, broken image url = null; @@ -206,7 +204,7 @@ public class BasicSupportHelper { public String fixAuthor(String author) { if (author != null) { for (String suffix : new String[] { " ", ":" }) { - for (String byString : Instance.getConfig().getList(Config.CONF_BYS)) { + for (String byString : Instance.getInstance().getConfig().getList(Config.CONF_BYS)) { byString += suffix; if (author.toUpperCase().startsWith(byString.toUpperCase())) { author = author.substring(byString.length()).trim(); diff --git a/supported/BasicSupportImages.java b/supported/BasicSupportImages.java index 69a7c86..576cb17 100644 --- a/supported/BasicSupportImages.java +++ b/supported/BasicSupportImages.java @@ -20,16 +20,32 @@ public class BasicSupportImages { * Check if the given resource can be a local image or a remote image, then * refresh the cache with it if it is. * + * @param support + * the support to use to download the resource (can be NULL) * @param dir * the local directory to search, if any * @param line * the resource to check * * @return the image if found, or NULL - * */ public Image getImage(BasicSupport support, File dir, String line) { URL url = getImageUrl(support, dir, line); + return getImage(support,url); + } + + /** + * Check if the given resource can be a local image or a remote image, then + * refresh the cache with it if it is. + * + * @param support + * the support to use to download the resource (can be NULL) + * @param url + * the actual URL to check (file or remote, can be NULL) + * + * @return the image if found, or NULL + */ + public Image getImage(BasicSupport support, URL url) { if (url != null) { if ("file".equals(url.getProtocol())) { if (new File(url.getPath()).isDirectory()) { @@ -38,7 +54,7 @@ public class BasicSupportImages { } InputStream in = null; try { - in = Instance.getCache().open(url, support, true); + in = Instance.getInstance().getCache().open(url, support, true); return new Image(in); } catch (IOException e) { } finally { @@ -58,6 +74,8 @@ public class BasicSupportImages { * Check if the given resource can be a local image or a remote image, then * refresh the cache with it if it is. * + * @param support + * the support to use to download the resource (can be NULL) * @param dir * the local directory to search, if any * @param line @@ -108,7 +126,7 @@ public class BasicSupportImages { // try for URLs try { for (String ext : getImageExt(true)) { - if (Instance.getCache() + if (Instance.getInstance().getCache() .check(new URL(line + ext), true)) { url = new URL(line + ext); break; @@ -120,7 +138,7 @@ public class BasicSupportImages { for (String ext : getImageExt(true)) { try { url = new URL(line + ext); - Instance.getCache().refresh(url, support, true); + Instance.getInstance().getCache().refresh(url, support, true); break; } catch (IOException e) { // no image with this ext @@ -136,7 +154,7 @@ public class BasicSupportImages { // refresh the cached file if (url != null) { try { - Instance.getCache().refresh(url, support, true); + Instance.getInstance().getCache().refresh(url, support, true); } catch (IOException e) { // woops, broken image url = null; diff --git a/supported/BasicSupportPara.java b/supported/BasicSupportPara.java index ef4d7d7..58c363a 100644 --- a/supported/BasicSupportPara.java +++ b/supported/BasicSupportPara.java @@ -26,14 +26,10 @@ import be.nikiroo.utils.StringUtils; */ public class BasicSupportPara { // quote chars - private static char openQuote = Instance.getTrans().getCharacter( - StringId.OPEN_SINGLE_QUOTE); - private static char closeQuote = Instance.getTrans().getCharacter( - StringId.CLOSE_SINGLE_QUOTE); - private static char openDoubleQuote = Instance.getTrans().getCharacter( - StringId.OPEN_DOUBLE_QUOTE); - private static char closeDoubleQuote = Instance.getTrans().getCharacter( - StringId.CLOSE_DOUBLE_QUOTE); + private static char openQuote = Instance.getInstance().getTrans().getCharacter(StringId.OPEN_SINGLE_QUOTE); + private static char closeQuote = Instance.getInstance().getTrans().getCharacter(StringId.CLOSE_SINGLE_QUOTE); + private static char openDoubleQuote = Instance.getInstance().getTrans().getCharacter(StringId.OPEN_DOUBLE_QUOTE); + private static char closeDoubleQuote = Instance.getInstance().getTrans().getCharacter(StringId.CLOSE_DOUBLE_QUOTE); // used by this class: BasicSupportHelper bsHelper; @@ -77,9 +73,8 @@ public class BasicSupportPara { // "Chapter 5: - Fun!" after the ": " was automatically added) String chapterName = processPara(name, false) .getContent().trim(); - for (String lang : Instance.getConfig().getList(Config.CONF_CHAPTER)) { - String chapterWord = Instance.getConfig().getStringX( - Config.CONF_CHAPTER, lang); + for (String lang : Instance.getInstance().getConfig().getList(Config.CONF_CHAPTER)) { + String chapterWord = Instance.getInstance().getConfig().getStringX(Config.CONF_CHAPTER, lang); if (chapterName.startsWith(chapterWord)) { chapterName = chapterName.substring(chapterWord.length()) .trim(); diff --git a/supported/BasicSupport_Deprecated.java b/supported/BasicSupport_Deprecated.java index 1faac03..4a7b65b 100644 --- a/supported/BasicSupport_Deprecated.java +++ b/supported/BasicSupport_Deprecated.java @@ -42,14 +42,10 @@ public abstract class BasicSupport_Deprecated extends BasicSupport { private InputStream in; // quote chars - private char openQuote = Instance.getTrans().getCharacter( - StringId.OPEN_SINGLE_QUOTE); - private char closeQuote = Instance.getTrans().getCharacter( - StringId.CLOSE_SINGLE_QUOTE); - private char openDoubleQuote = Instance.getTrans().getCharacter( - StringId.OPEN_DOUBLE_QUOTE); - private char closeDoubleQuote = Instance.getTrans().getCharacter( - StringId.CLOSE_DOUBLE_QUOTE); + private char openQuote = Instance.getInstance().getTrans().getCharacter(StringId.OPEN_SINGLE_QUOTE); + private char closeQuote = Instance.getInstance().getTrans().getCharacter(StringId.CLOSE_SINGLE_QUOTE); + private char openDoubleQuote = Instance.getInstance().getTrans().getCharacter(StringId.OPEN_DOUBLE_QUOTE); + private char closeDoubleQuote = Instance.getInstance().getTrans().getCharacter(StringId.CLOSE_DOUBLE_QUOTE); // New methods not used in Deprecated mode @Override @@ -223,11 +219,8 @@ public abstract class BasicSupport_Deprecated extends BasicSupport { pg.setProgress(60); if (getDesc) { - String descChapterName = Instance.getTrans().getString( - StringId.DESCRIPTION); - story.getMeta().setResume( - makeChapter(url, 0, descChapterName, - getDesc(url, getInput()), null)); + String descChapterName = Instance.getInstance().getTrans().getString(StringId.DESCRIPTION); + story.getMeta().setResume(makeChapter(url, 0, descChapterName, getDesc(url, getInput()), null)); } pg.setProgress(100); @@ -299,8 +292,7 @@ public abstract class BasicSupport_Deprecated extends BasicSupport { InputStream chapIn = null; if (chap.getValue() != null) { setCurrentReferer(chap.getValue()); - chapIn = Instance.getCache().open(chap.getValue(), - this, false); + chapIn = Instance.getInstance().getCache().open(chap.getValue(), this, false); } pgChaps.setProgress(i * 100); try { @@ -391,9 +383,8 @@ public abstract class BasicSupport_Deprecated extends BasicSupport { // redundant "Chapter x: " in front of it, or "-" (as in // "Chapter 5: - Fun!" after the ": " was automatically added) String chapterName = processPara(name).getContent().trim(); - for (String lang : Instance.getConfig().getList(Config.CONF_CHAPTER)) { - String chapterWord = Instance.getConfig().getStringX( - Config.CONF_CHAPTER, lang); + for (String lang : Instance.getInstance().getConfig().getList(Config.CONF_CHAPTER)) { + String chapterWord = Instance.getInstance().getConfig().getStringX(Config.CONF_CHAPTER, lang); if (chapterName.startsWith(chapterWord)) { chapterName = chapterName.substring(chapterWord.length()) .trim(); @@ -591,10 +582,9 @@ public abstract class BasicSupport_Deprecated extends BasicSupport { * @return the cover if any, or NULL */ static Image getDefaultCover(String subject) { - if (subject != null && !subject.isEmpty() - && Instance.getCoverDir() != null) { + if (subject != null && !subject.isEmpty() && Instance.getInstance().getCoverDir() != null) { try { - File fileCover = new File(Instance.getCoverDir(), subject); + File fileCover = new File(Instance.getInstance().getCoverDir(), subject); return getImage(null, fileCover.toURI().toURL(), subject); } catch (MalformedURLException e) { } @@ -644,7 +634,7 @@ public abstract class BasicSupport_Deprecated extends BasicSupport { } InputStream in = null; try { - in = Instance.getCache().open(url, getSupport(url), true); + in = Instance.getInstance().getCache().open(url, getSupport(url), true); return new Image(in); } catch (IOException e) { } finally { @@ -716,8 +706,7 @@ public abstract class BasicSupport_Deprecated extends BasicSupport { // try for URLs try { for (String ext : getImageExt(true)) { - if (Instance.getCache() - .check(new URL(line + ext), true)) { + if (Instance.getInstance().getCache().check(new URL(line + ext), true)) { url = new URL(line + ext); break; } @@ -728,7 +717,7 @@ public abstract class BasicSupport_Deprecated extends BasicSupport { for (String ext : getImageExt(true)) { try { url = new URL(line + ext); - Instance.getCache().refresh(url, support, true); + Instance.getInstance().getCache().refresh(url, support, true); break; } catch (IOException e) { // no image with this ext @@ -744,7 +733,7 @@ public abstract class BasicSupport_Deprecated extends BasicSupport { // refresh the cached file if (url != null) { try { - Instance.getCache().refresh(url, support, true); + Instance.getInstance().getCache().refresh(url, support, true); } catch (IOException e) { // woops, broken image url = null; @@ -770,7 +759,7 @@ public abstract class BasicSupport_Deprecated extends BasicSupport { * in case of I/O error */ protected InputStream openInput(URL source) throws IOException { - return Instance.getCache().open(source, this, false); + return Instance.getInstance().getCache().open(source, this, false); } /** diff --git a/supported/Cbz.java b/supported/Cbz.java index 22e436a..76b66ab 100644 --- a/supported/Cbz.java +++ b/supported/Cbz.java @@ -71,7 +71,7 @@ class Cbz extends Epub { pgMeta.done(); // 10% - File tmpDir = Instance.getTempFiles().createTempDir("info-text"); + File tmpDir = Instance.getInstance().getTempFiles().createTempDir("info-text"); String basename = null; Map images = new HashMap(); @@ -97,7 +97,7 @@ class Cbz extends Epub { try { images.put(uuid, new Image(zipIn)); } catch (Exception e) { - Instance.getTraceHandler().error(e); + Instance.getInstance().getTraceHandler().error(e); } if (pg.getProgress() < 85) { @@ -114,9 +114,7 @@ class Cbz extends Epub { } String ext = "." - + Instance.getConfig() - .getString(Config.FILE_FORMAT_IMAGE_FORMAT_COVER) - .toLowerCase(); + + Instance.getInstance().getConfig().getString(Config.FILE_FORMAT_IMAGE_FORMAT_COVER).toLowerCase(); String coverName = meta.getUuid() + "_" + basename + ext; Image cover = images.get(coverName); images.remove(coverName); @@ -176,7 +174,7 @@ class Cbz extends Epub { chap.getParagraphs().add( new Paragraph(images.get(uuid))); } catch (Exception e) { - Instance.getTraceHandler().error(e); + Instance.getInstance().getTraceHandler().error(e); } } } diff --git a/supported/E621.java b/supported/E621.java index dfa9e5e..f1660e1 100644 --- a/supported/E621.java +++ b/supported/E621.java @@ -9,22 +9,25 @@ import java.net.URLDecoder; import java.util.AbstractMap; import java.util.ArrayList; import java.util.Collections; +import java.util.Date; import java.util.LinkedList; import java.util.List; import java.util.Map.Entry; -import java.util.Scanner; + +import org.jsoup.helper.DataUtil; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; import be.nikiroo.fanfix.Instance; -import be.nikiroo.fanfix.data.Chapter; import be.nikiroo.fanfix.data.MetaData; -import be.nikiroo.fanfix.data.Story; +import be.nikiroo.utils.IOUtils; import be.nikiroo.utils.Image; import be.nikiroo.utils.Progress; import be.nikiroo.utils.StringUtils; /** - * Support class for e621.net and e926.net, a Furry website supporting comics, + * Support class for e621.net and + * e926.net, a Furry website supporting comics, * including some of MLP. *

* e926.net only shows the "clean" images and @@ -32,335 +35,226 @@ import be.nikiroo.utils.StringUtils; * * @author niki */ -class E621 extends BasicSupport_Deprecated { +class E621 extends BasicSupport { + @Override + protected boolean supports(URL url) { + String host = url.getHost(); + if (host.startsWith("www.")) { + host = host.substring("www.".length()); + } + + return ("e621.net".equals(host) || "e926.net".equals(host)) && (isPool(url) || isSearchOrSet(url)); + } + @Override - protected MetaData getMeta(URL source, InputStream in) throws IOException { + protected boolean isHtml() { + return true; + } + + @Override + protected MetaData getMeta() throws IOException { MetaData meta = new MetaData(); - meta.setTitle(getTitle(reset(in))); - meta.setAuthor(getAuthor(source, reset(in))); + meta.setTitle(getTitle()); + meta.setAuthor(getAuthor()); meta.setDate(""); - meta.setTags(getTags(source, reset(in), false)); + meta.setTags(getTags()); meta.setSource(getType().getSourceName()); - meta.setUrl(source.toString()); + meta.setUrl(getSource().toString()); meta.setPublisher(getType().getSourceName()); - meta.setUuid(source.toString()); + meta.setUuid(getSource().toString()); meta.setLuid(""); meta.setLang("en"); meta.setSubject("Furry"); meta.setType(getType().toString()); meta.setImageDocument(true); - meta.setCover(getCover(source, reset(in))); + meta.setCover(getCover()); meta.setFakeCover(true); return meta; } - private List getTags(URL source, InputStream in, boolean authors) { - List tags = new ArrayList(); - - if (isSearch(source)) { - String tagLine = getLine(in, "id=\"tag-sidebar\"", 1); - if (tagLine != null) { - String key = "href=\""; - for (int pos = tagLine.indexOf(key); pos >= 0; pos = tagLine - .indexOf(key, pos + 1)) { - int end = tagLine.indexOf("\"", pos + key.length()); - if (end >= 0) { - String href = tagLine.substring(pos, end); - String subkey; - if (authors) - subkey = "?name="; - else - subkey = "?title="; - if (href.contains(subkey)) { - String tag = href.substring(href.indexOf(subkey) - + subkey.length()); - try { - tags.add(URLDecoder.decode(tag, "UTF-8")); - } catch (UnsupportedEncodingException e) { - // supported JVMs must have UTF-8 support - e.printStackTrace(); - } - } - } - } - - } - } - - return tags; - } - @Override - public Story process(URL url, Progress pg) throws IOException { - // There is no chapters on e621, just pagination... - Story story = super.process(url, pg); + protected String getDesc() throws IOException { + if (isSearchOrSet(getSource())) { + StringBuilder builder = new StringBuilder(); + builder.append("A collection of images from ").append(getSource().getHost()).append("\n") // + .append("\tTime of creation: " + StringUtils.fromTime(new Date().getTime())).append("\n") // + .append("\tTags: ");// + for (String tag : getTags()) { + builder.append("\t\t").append(tag); + } - Chapter only = new Chapter(1, null); - for (Chapter chap : story) { - only.getParagraphs().addAll(chap.getParagraphs()); + return builder.toString(); } - story.getChapters().clear(); - story.getChapters().add(only); - - return story; - } - - @Override - protected boolean supports(URL url) { - String host = url.getHost(); - if (host.startsWith("www.")) { - host = host.substring("www.".length()); + if (isPool(getSource())) { + Element el = getSourceNode().getElementById("description"); + if (el != null) { + return el.text(); + } } - return ("e621.net".equals(host) || "e926.net".equals(host)) - && (isPool(url) || isSearch(url)); + return null; } @Override - protected boolean isHtml() { - return true; - } - - private Image getCover(URL source, InputStream in) throws IOException { - URL urlForCover = source; - if (isPool(source)) { - urlForCover = new URL(source.toString() + "?page=1"); - } - - String images = getChapterContent(urlForCover, in, 1, null); - if (!images.isEmpty()) { - int pos = images.indexOf("
"); - if (pos >= 0) { - images = images.substring(1, pos - 1); - return getImage(this, null, images); - } + protected List> getChapters(Progress pg) throws IOException { + if (isPool(getSource())) { + String baseUrl = "https://e621.net/" + getSource().getPath() + "?page="; + return getChapters(getSource(), pg, baseUrl, ""); + } else if (isSearchOrSet(getSource())) { + String baseUrl = "https://e621.net/posts/?page="; + String search = "&tags=" + getTagsFromUrl(getSource()); + return getChapters(getSource(), pg, baseUrl, search); } - return null; + return new LinkedList>(); } - private String getAuthor(URL source, InputStream in) { - if (isSearch(source)) { - StringBuilder builder = new StringBuilder(); - for (String author : getTags(source, in, true)) { - if (builder.length() > 0) - builder.append(", "); - builder.append(author); - } + private List> getChapters(URL source, Progress pg, String baseUrl, String parameters) + throws IOException { + List> urls = new ArrayList>(); - return builder.toString(); + if (source.getHost().contains("e926")) { + baseUrl = baseUrl.replace("e621", "e926"); } - String author = getLine(in, "href=\"/post/show/", 0); - if (author != null) { - String key = "href=\""; - int pos = author.indexOf(key); - if (pos >= 0) { - author = author.substring(pos + key.length()); - pos = author.indexOf("\""); - if (pos >= 0) { - author = author.substring(0, pos - 1); - String page = source.getProtocol() + "://" - + source.getHost() + author; - try { - InputStream pageIn = Instance.getCache().open( - new URL(page), this, false); - try { - key = "class=\"tag-type-artist\""; - author = getLine(pageIn, key, 0); - if (author != null) { - pos = author.indexOf("= 0) { - author = author.substring(pos); - pos = author.indexOf(""); - if (pos >= 0) { - author = author.substring(0, pos); - return StringUtils.unhtml(author); - } - } - } - } finally { - pageIn.close(); - } - } catch (Exception e) { - // No author found + for (int i = 1; true; i++) { + URL url = new URL(baseUrl + i + parameters); + try { + InputStream pageI = Instance.getInstance().getCache().open(url, this, false); + try { + if (IOUtils.readSmallStream(pageI).contains("Nobody here but us chickens!")) { + break; } + urls.add(new AbstractMap.SimpleEntry("Page " + Integer.toString(i), url)); + } finally { + pageI.close(); } + } catch (Exception e) { + break; } } - return null; + // They are sorted in reverse order on the website + Collections.reverse(urls); + return urls; } - private String getTitle(InputStream in) { - String title = getLine(in, "", 0); - if (title != null) { - int pos = title.indexOf('>'); - if (pos >= 0) { - title = title.substring(pos + 1); - pos = title.indexOf('<'); - if (pos >= 0) { - title = title.substring(0, pos); - } - } - - if (title.startsWith("Pool:")) { - title = title.substring("Pool:".length()); - } - - title = StringUtils.unhtml(title).trim(); + @Override + protected String getChapterContent(URL chapUrl, int number, Progress pg) throws IOException { + StringBuilder builder = new StringBuilder(); + Document chapterNode = loadDocument(chapUrl); + for (Element el : chapterNode.getElementsByTag("article")) { + builder.append("["); + builder.append(el.attr("data-file-url")); + builder.append("]<br/>"); } - return title; + return builder.toString(); } @Override - protected String getDesc(URL source, InputStream in) throws IOException { - String desc = getLine(in, "margin-bottom: 2em;", 0); - - if (desc != null) { - StringBuilder builder = new StringBuilder(); - - boolean inTags = false; - for (char car : desc.toCharArray()) { - if ((inTags && car == '>') || (!inTags && car == '<')) { - inTags = !inTags; - } - - if (inTags) { - builder.append(car); + protected URL getCanonicalUrl(URL source) { + if (isSetOriginalUrl(source)) { + try { + Document doc = DataUtil.load(Instance.getInstance().getCache().open(source, this, false), "UTF-8", source.toString()); + for (Element shortname : doc.getElementsByClass("set-shortname")) { + for (Element el : shortname.getElementsByTag("a")) { + if (!el.attr("href").isEmpty()) + return new URL(el.absUrl("href")); + } } + } catch (IOException e) { + Instance.getInstance().getTraceHandler().error(e); } - - return builder.toString().trim(); } - return null; - } - - @Override - protected List<Entry<String, URL>> getChapters(URL source, InputStream in, - Progress pg) throws IOException { if (isPool(source)) { - return getChaptersPool(source, in, pg); - } else if (isSearch(source)) { - return getChaptersSearch(source, in, pg); + try { + return new URL(source.toString().replace("/pool/show/", "/pools/")); + } catch (MalformedURLException e) { + } } - return new LinkedList<Entry<String, URL>>(); + return super.getCanonicalUrl(source); } - private List<Entry<String, URL>> getChaptersSearch(URL source, - InputStream in, Progress pg) throws IOException { - List<Entry<String, URL>> urls = new ArrayList<Entry<String, URL>>(); + // returns "xxx+ddd+ggg" if "tags=xxx+ddd+ggg" was present in the query + private String getTagsFromUrl(URL url) { + String tags = url == null ? "" : url.getQuery(); + int pos = tags.indexOf("tags="); - String search = source.getPath(); - if (search.endsWith("/")) { - search = search.substring(0, search.length() - 1); + if (pos >= 0) { + tags = tags.substring(pos).substring("tags=".length()); + } else { + return ""; } - int pos = search.lastIndexOf('/'); - if (pos >= 0) { - search = search.substring(pos + 1); + pos = tags.indexOf('&'); + if (pos > 0) { + tags = tags.substring(0, pos); + } + pos = tags.indexOf('/'); + if (pos > 0) { + tags = tags.substring(0, pos); } - String baseUrl = "https://e621.net/post/index/"; - if (source.getHost().contains("e926")) { - baseUrl = baseUrl.replace("e621", "e926"); + return tags; + } + + private String getTitle() { + String title = ""; + + Element el = getSourceNode().getElementsByTag("title").first(); + if (el != null) { + title = el.text().trim(); } - for (int i = 1; true; i++) { - URL url = new URL(baseUrl + i + "/" + search + "/"); - try { - InputStream pageI = Instance.getCache().open(url, this, false); - try { - if (getLine(pageI, "No posts matched your search.", 0) != null) - break; - urls.add(new AbstractMap.SimpleEntry<String, URL>("Page " - + Integer.toString(i), url)); - } finally { - pageI.close(); - } - } catch (Exception e) { - break; + for (String s : new String[] { "e621", "-", "e621" }) { + if (title.startsWith(s)) { + title = title.substring(s.length()).trim(); + } + if (title.endsWith(s)) { + title = title.substring(0, title.length() - s.length()).trim(); } + } - // They are sorted in reverse order on the website - Collections.reverse(urls); - return urls; + if (isSearchOrSet(getSource())) { + title = title.isEmpty() ? "e621" : "[e621] " + title; + } + return title; } - private List<Entry<String, URL>> getChaptersPool(URL source, - InputStream in, Progress pg) throws IOException { - List<Entry<String, URL>> urls = new ArrayList<Entry<String, URL>>(); - int last = 1; // no pool/show when only one page - - @SuppressWarnings("resource") - Scanner scan = new Scanner(in, "UTF-8"); - scan.useDelimiter("\\n"); - while (scan.hasNext()) { - String line = scan.next(); - for (int pos = line.indexOf(source.getPath()); pos >= 0; pos = line - .indexOf(source.getPath(), pos + source.getPath().length())) { - int equalPos = line.indexOf("=", pos); - int quotePos = line.indexOf("\"", pos); - if (equalPos >= 0 && quotePos > equalPos) { - String snum = line.substring(equalPos + 1, quotePos); - try { - int num = Integer.parseInt(snum); - if (num > last) { - last = num; - } - } catch (NumberFormatException e) { + private String getAuthor() throws IOException { + StringBuilder builder = new StringBuilder(); + + if (isSearchOrSet(getSource())) { + for (Element el : getSourceNode().getElementsByClass("search-tag")) { + if (el.attr("itemprop").equals("author")) { + if (builder.length() > 0) { + builder.append(", "); } + builder.append(el.text().trim()); } } } - for (int i = 1; i <= last; i++) { - urls.add(new AbstractMap.SimpleEntry<String, URL>(Integer - .toString(i), new URL(source.toString() + "?page=" + i))); - } + if (isPool(getSource())) { + String desc = getDesc(); + String descL = desc.toLowerCase(); - return urls; - } - - @Override - protected String getChapterContent(URL source, InputStream in, int number, - Progress pg) throws IOException { - StringBuilder builder = new StringBuilder(); - String staticSite = "https://static1.e621.net"; - if (source.getHost().contains("e926")) { - staticSite = staticSite.replace("e621", "e926"); - } + if (descL.startsWith("by:") || descL.startsWith("by ")) { + desc = desc.substring(3).trim(); + desc = desc.split("\n")[0]; - String key = staticSite + "/data/preview/"; - - @SuppressWarnings("resource") - Scanner scan = new Scanner(in, "UTF-8"); - scan.useDelimiter("\\n"); - while (scan.hasNext()) { - String line = scan.next(); - if (line.contains("class=\"preview")) { - for (int pos = line.indexOf(key); pos >= 0; pos = line.indexOf( - key, pos + key.length())) { - int endPos = line.indexOf("\"", pos); - if (endPos >= 0) { - String id = line.substring(pos + key.length(), endPos); - id = staticSite + "/data/" + id; - - int dotPos = id.lastIndexOf("."); - if (dotPos >= 0) { - id = id.substring(0, dotPos); - builder.append("["); - builder.append(id); - builder.append("]<br/>"); - } - } + String tab[] = desc.split(" "); + for (int i = 0; i < Math.min(tab.length, 5); i++) { + if (tab[i].startsWith("http")) + break; + builder.append(" ").append(tab[i]); } } } @@ -368,42 +262,52 @@ class E621 extends BasicSupport_Deprecated { return builder.toString(); } - @Override - protected URL getCanonicalUrl(URL source) { - if (isSearch(source)) { - // /post?tags=tag1+tag2 -> ../post/index/1/tag1%32tag2 - String key = "?tags="; - if (source.toString().contains(key)) { - int pos = source.toString().indexOf(key); - String tags = source.toString().substring(pos + key.length()); - tags = tags.replace("+", "%20"); - - String base = source.toString().substring(0, pos); - if (!base.endsWith("/")) { - base += "/"; - } - if (base.endsWith("/search/")) { - base = base.substring(0, base.indexOf("/search/") + 1); - } - + // no tags for pools + private List<String> getTags() { + List<String> tags = new ArrayList<String>(); + if (isSearchOrSet(getSource())) { + String str = getTagsFromUrl(getSource()); + for (String tag : str.split("\\+")) { try { - return new URL(base + "index/1/" + tags); - } catch (MalformedURLException e) { - Instance.getTraceHandler().error(e); + tags.add(URLDecoder.decode(tag.trim(), "UTF-8").trim()); + } catch (UnsupportedEncodingException e) { } } } - return super.getCanonicalUrl(source); + return tags; + } + + private Image getCover() throws IOException { + Image image = null; + List<Entry<String, URL>> chapters = getChapters(null); + if (!chapters.isEmpty()) { + URL chap1Url = chapters.get(0).getValue(); + String imgsChap1 = getChapterContent(chap1Url, 1, null); + if (!imgsChap1.isEmpty()) { + imgsChap1 = imgsChap1.split("]")[0].substring(1).trim(); + image = bsImages.getImage(this, new URL(imgsChap1)); + } + } + + return image; + } + + // note: will be removed at getCanonicalUrl() + private boolean isSetOriginalUrl(URL originalUrl) { + return originalUrl.getPath().startsWith("/post_sets/"); } private boolean isPool(URL url) { - return url.getPath().startsWith("/pool/"); + return url.getPath().startsWith("/pools/") || url.getPath().startsWith("/pool/show/"); } - private boolean isSearch(URL url) { - return url.getPath().startsWith("/post/index/") - || (url.getPath().equals("/post/search") && url.getQuery() - .startsWith("tags=")); + // set will be renamed into search by canonical url + private boolean isSearchOrSet(URL url) { + return + // search: + (url.getPath().equals("/posts") && url.getQuery().contains("tags=")) + // or set: + || isSetOriginalUrl(url); } } diff --git a/supported/EHentai.java b/supported/EHentai.java index 67585cd..03c1557 100644 --- a/supported/EHentai.java +++ b/supported/EHentai.java @@ -255,10 +255,8 @@ class EHentai extends BasicSupport_Deprecated { try { pages.add(new URL(line)); } catch (MalformedURLException e) { - Instance.getTraceHandler().error( - new IOException( - "Parsing error, a link is not correctly parsed: " - + line, e)); + Instance.getInstance().getTraceHandler() + .error(new IOException("Parsing error, a link is not correctly parsed: " + line, e)); } } } @@ -272,7 +270,7 @@ class EHentai extends BasicSupport_Deprecated { StringBuilder builder = new StringBuilder(); for (URL page : pages) { - InputStream pageIn = Instance.getCache().open(page, this, false); + InputStream pageIn = Instance.getInstance().getCache().open(page, this, false); try { String link = getKeyLine(pageIn, "id=\"img\"", "src=\"", "\""); if (link != null && !link.isEmpty()) { diff --git a/supported/Epub.java b/supported/Epub.java index 82af118..f8e4678 100644 --- a/supported/Epub.java +++ b/supported/Epub.java @@ -42,10 +42,8 @@ class Epub extends InfoText { try { return new File(fakeSource.toURI()); } catch (URISyntaxException e) { - Instance.getTraceHandler() - .error(new IOException( - "Cannot get the source file from the info-text URL", - e)); + Instance.getInstance().getTraceHandler() + .error(new IOException("Cannot get the source file from the info-text URL", e)); } return null; @@ -57,9 +55,7 @@ class Epub extends InfoText { try { fakeIn.reset(); } catch (IOException e) { - Instance.getTraceHandler() - .error(new IOException( - "Cannot reset the Epub Text stream", e)); + Instance.getInstance().getTraceHandler().error(new IOException("Cannot reset the Epub Text stream", e)); } return fakeIn; @@ -87,8 +83,7 @@ class Epub extends InfoText { ZipInputStream zipIn = null; try { zipIn = new ZipInputStream(in); - tmpDir = Instance.getTempFiles().createTempDir( - "fanfic-reader-parser"); + tmpDir = Instance.getInstance().getTempFiles().createTempDir("fanfic-reader-parser"); File tmp = new File(tmpDir, "file.txt"); File tmpInfo = new File(tmpDir, "file.info"); @@ -129,7 +124,7 @@ class Epub extends InfoText { try { cover = new Image(zipIn); } catch (Exception e) { - Instance.getTraceHandler().error(e); + Instance.getInstance().getTraceHandler().error(e); } } } else if (entry.getName().equals(getDataPrefix() + "URL")) { diff --git a/supported/Fanfiction.java b/supported/Fanfiction.java index fcf773b..282192e 100644 --- a/supported/Fanfiction.java +++ b/supported/Fanfiction.java @@ -157,10 +157,8 @@ class Fanfiction extends BasicSupport_Deprecated { return sdf .format(new Date(1000 * Long.parseLong(line))); } catch (NumberFormatException e) { - Instance.getTraceHandler().error( - new IOException( - "Cannot convert publication date: " - + line, e)); + Instance.getInstance().getTraceHandler() + .error(new IOException("Cannot convert publication date: " + line, e)); } } } @@ -243,11 +241,8 @@ class Fanfiction extends BasicSupport_Deprecated { urls.add(new AbstractMap.SimpleEntry<String, URL>( name.trim(), new URL(base + i + suffix))); } catch (MalformedURLException e) { - Instance.getTraceHandler() - .error(new IOException( - "Cannot parse chapter " + i - + " url: " - + (base + i + suffix), e)); + Instance.getInstance().getTraceHandler().error( + new IOException("Cannot parse chapter " + i + " url: " + (base + i + suffix), e)); } } } @@ -304,10 +299,9 @@ class Fanfiction extends BasicSupport_Deprecated { int pos = line.indexOf("<hr"); if (pos >= 0) { boolean chaptered = false; - for (String lang : Instance.getConfig().getList( - Config.CONF_CHAPTER)) { - String chapterWord = Instance.getConfig() - .getStringX(Config.CONF_CHAPTER, lang); + for (String lang : Instance.getInstance().getConfig().getList(Config.CONF_CHAPTER)) { + String chapterWord = Instance.getInstance().getConfig().getStringX(Config.CONF_CHAPTER, + lang); int posChap = line.indexOf(chapterWord + " "); if (posChap < pos) { chaptered = true; diff --git a/supported/Fimfiction.java b/supported/Fimfiction.java index e96ac4f..77267c1 100644 --- a/supported/Fimfiction.java +++ b/supported/Fimfiction.java @@ -230,7 +230,7 @@ class Fimfiction extends BasicSupport_Deprecated { urls.add(new AbstractMap.SimpleEntry<String, URL>(name, new URL("http://www.fimfiction.net" + line))); } catch (MalformedURLException e) { - Instance.getTraceHandler().error(e); + Instance.getInstance().getTraceHandler().error(e); } } } diff --git a/supported/FimfictionApi.java b/supported/FimfictionApi.java index c97ecf7..6c6d7ba 100644 --- a/supported/FimfictionApi.java +++ b/supported/FimfictionApi.java @@ -37,22 +37,17 @@ class FimfictionApi extends BasicSupport { private Map<Integer, String> chapterContents; public FimfictionApi() throws IOException { - if (Instance.getConfig().getBoolean( - Config.LOGIN_FIMFICTION_APIKEY_FORCE_HTML, false)) { - throw new IOException( - "Configuration is set to force HTML scrapping"); + if (Instance.getInstance().getConfig().getBoolean(Config.LOGIN_FIMFICTION_APIKEY_FORCE_HTML, false)) { + throw new IOException("Configuration is set to force HTML scrapping"); } - String oauth = Instance.getConfig().getString( - Config.LOGIN_FIMFICTION_APIKEY_TOKEN); + String oauth = Instance.getInstance().getConfig().getString(Config.LOGIN_FIMFICTION_APIKEY_TOKEN); if (oauth == null || oauth.isEmpty()) { - String clientId = Instance.getConfig().getString( - Config.LOGIN_FIMFICTION_APIKEY_CLIENT_ID) - + ""; - String clientSecret = Instance.getConfig().getString( - Config.LOGIN_FIMFICTION_APIKEY_CLIENT_SECRET) + String clientId = Instance.getInstance().getConfig().getString(Config.LOGIN_FIMFICTION_APIKEY_CLIENT_ID) + ""; + String clientSecret = Instance.getInstance().getConfig() + .getString(Config.LOGIN_FIMFICTION_APIKEY_CLIENT_SECRET) + ""; if (clientId.trim().isEmpty() || clientSecret.trim().isEmpty()) { throw new IOException("API key required for the beta API v2"); @@ -60,9 +55,8 @@ class FimfictionApi extends BasicSupport { oauth = generateOAuth(clientId, clientSecret); - Instance.getConfig().setString( - Config.LOGIN_FIMFICTION_APIKEY_TOKEN, oauth); - Instance.getConfig().updateFile(); + Instance.getInstance().getConfig().setString(Config.LOGIN_FIMFICTION_APIKEY_TOKEN, oauth); + Instance.getInstance().getConfig().updateFile(); } this.oauth = oauth; @@ -116,7 +110,7 @@ class FimfictionApi extends BasicSupport { urlString = urlString.replace("[", "%5B").replace("]", "%5D"); URL url = new URL(urlString); - InputStream jsonIn = Instance.getCache().open(url, this, false); + InputStream jsonIn = Instance.getInstance().getCache().open(url, this, false); try { return IOUtils.readSmallStream(jsonIn); } finally { @@ -150,17 +144,15 @@ class FimfictionApi extends BasicSupport { // No need to use the oauth, cookies... for the cover // Plus: it crashes on Android because of the referer try { - InputStream in = Instance.getCache().open(coverImageUrl, null, - true); + InputStream in = Instance.getInstance().getCache().open(coverImageUrl, null, true); try { meta.setCover(new Image(in)); } finally { in.close(); } } catch (IOException e) { - Instance.getTraceHandler().error( - new IOException( - "Cannot get the story cover, ignoring...", e)); + Instance.getInstance().getTraceHandler() + .error(new IOException("Cannot get the story cover, ignoring...", e)); } } @@ -258,8 +250,7 @@ class FimfictionApi extends BasicSupport { params.put("client_id", clientId); params.put("client_secret", clientSecret); params.put("grant_type", "client_credentials"); - InputStream in = Instance.getCache().openNoCache(url, null, params, - null, null); + InputStream in = Instance.getInstance().getCache().openNoCache(url, null, params, null, null); String jsonToken = IOUtils.readSmallStream(in); in.close(); diff --git a/supported/Html.java b/supported/Html.java index c27dd32..900fa0a 100644 --- a/supported/Html.java +++ b/supported/Html.java @@ -51,9 +51,8 @@ class Html extends InfoText { try { source = txt.toURI().toURL(); } catch (MalformedURLException e) { - Instance.getTraceHandler().error( - new IOException("Cannot convert the right URL for " - + source, e)); + Instance.getInstance().getTraceHandler() + .error(new IOException("Cannot convert the right URL for " + source, e)); } } diff --git a/supported/InfoReader.java b/supported/InfoReader.java index c22dbd7..220350e 100644 --- a/supported/InfoReader.java +++ b/supported/InfoReader.java @@ -98,8 +98,7 @@ public class InfoReader { File basefile = new File(sourceInfoFile.getFile()); String ext = "." - + Instance.getConfig().getString(Config.FILE_FORMAT_IMAGE_FORMAT_COVER) - .toLowerCase(); + + Instance.getInstance().getConfig().getString(Config.FILE_FORMAT_IMAGE_FORMAT_COVER).toLowerCase(); // Without removing ext cover = bsHelper.getImage(null, sourceInfoFile, diff --git a/supported/MangaFox.java b/supported/MangaFox.java deleted file mode 100644 index dae2d31..0000000 --- a/supported/MangaFox.java +++ /dev/null @@ -1,405 +0,0 @@ -package be.nikiroo.fanfix.supported; - -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.AbstractMap; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map.Entry; -import java.util.SortedMap; -import java.util.TreeMap; - -import org.jsoup.helper.DataUtil; -import org.jsoup.nodes.Element; -import org.jsoup.select.Elements; - -import be.nikiroo.fanfix.Instance; -import be.nikiroo.fanfix.data.MetaData; -import be.nikiroo.utils.Image; -import be.nikiroo.utils.Progress; -import be.nikiroo.utils.StringUtils; - -class MangaFox extends BasicSupport { - @Override - protected boolean isHtml() { - return true; - } - - @Override - protected MetaData getMeta() throws IOException { - MetaData meta = new MetaData(); - Element doc = getSourceNode(); - - Element title = doc.getElementById("title"); - Elements table = null; - if (title != null) { - table = title.getElementsByTag("table"); - } - if (table != null) { - // Rows: header, data - Elements rows = table.first().getElementsByTag("tr"); - if (rows.size() > 1) { - table = rows.get(1).getElementsByTag("td"); - // Columns: Realeased, Authors, Artists, Genres - if (table.size() < 4) { - table = null; - } - } - } - - meta.setTitle(getTitle()); - if (table != null) { - meta.setAuthor(getAuthors(table.get(1).text() + "," - + table.get(2).text())); - - meta.setDate(StringUtils.unhtml(table.get(0).text()).trim()); - meta.setTags(explode(table.get(3).text())); - } - meta.setSource(getType().getSourceName()); - meta.setUrl(getSource().toString()); - meta.setPublisher(getType().getSourceName()); - meta.setUuid(getSource().toString()); - meta.setLuid(""); - meta.setLang("en"); - meta.setSubject("manga"); - meta.setType(getType().toString()); - meta.setImageDocument(true); - meta.setCover(getCover()); - - return meta; - } - - private String getTitle() { - Element doc = getSourceNode(); - - Element title = doc.getElementById("title"); - Element h1 = title.getElementsByTag("h1").first(); - if (h1 != null) { - return StringUtils.unhtml(h1.text()).trim(); - } - - return null; - } - - private String getAuthors(String authorList) { - String author = ""; - for (String auth : explode(authorList)) { - if (!author.isEmpty()) { - author = author + ", "; - } - author += auth; - } - - return author; - } - - @Override - protected String getDesc() { - Element doc = getSourceNode(); - Element title = doc.getElementsByClass("summary").first(); - if (title != null) { - return StringUtils.unhtml(title.text()).trim(); - } - - return null; - } - - private Image getCover() { - Element doc = getSourceNode(); - Element cover = doc.getElementsByClass("cover").first(); - if (cover != null) { - cover = cover.getElementsByTag("img").first(); - } - - if (cover != null) { - String coverUrl = cover.absUrl("src"); - - InputStream coverIn; - try { - coverIn = openEx(coverUrl); - try { - return new Image(coverIn); - } finally { - coverIn.close(); - } - } catch (IOException e) { - Instance.getTraceHandler().error(e); - } - } - - return null; - } - - @Override - protected List<Entry<String, URL>> getChapters(Progress pg) { - List<Entry<String, URL>> urls = new ArrayList<Entry<String, URL>>(); - - String prefix = null; // each chapter starts with this prefix, then a - // chapter number (including "x.5"), then name - - Element doc = getSourceNode(); - for (Element li : doc.getElementsByTag("li")) { - Element el = li.getElementsByTag("h4").first(); - if (el == null) { - el = li.getElementsByTag("h3").first(); - } - if (el != null) { - Element a = el.getElementsByTag("a").first(); - if (a != null) { - String title = StringUtils.unhtml(el.text()).trim(); - try { - String url = a.absUrl("href"); - if (url.endsWith("1.html")) { - url = url.substring(0, - url.length() - "1.html".length()); - } - if (!url.endsWith("/")) { - url += "/"; - } - - if (prefix == null || !prefix.isEmpty()) { - StringBuilder possiblePrefix = new StringBuilder( - StringUtils.unhtml(a.text()).trim()); - while (possiblePrefix.length() > 0) { - char car = possiblePrefix.charAt(possiblePrefix - .length() - 1); - boolean punctuation = (car == '.' || car == ' '); - boolean digit = (car >= '0' && car <= '9'); - if (!punctuation && !digit) { - break; - } - - possiblePrefix.setLength(possiblePrefix - .length() - 1); - } - - if (prefix == null) { - prefix = possiblePrefix.toString(); - } - - if (!prefix.equalsIgnoreCase(possiblePrefix - .toString())) { - prefix = ""; // prefix not ok - } - } - - urls.add(new AbstractMap.SimpleEntry<String, URL>( - title, new URL(url))); - } catch (Exception e) { - Instance.getTraceHandler().error(e); - } - } - } - } - - if (prefix != null && !prefix.isEmpty()) { - try { - // We found a prefix, so everything should be sortable - SortedMap<Double, Entry<String, URL>> map = new TreeMap<Double, Entry<String, URL>>(); - for (Entry<String, URL> entry : urls) { - String num = entry.getKey().substring(prefix.length() + 1) - .trim(); - String name = ""; - int pos = num.indexOf(' '); - if (pos >= 0) { - name = num.substring(pos).trim(); - num = num.substring(0, pos).trim(); - } - - if (!name.isEmpty()) { - name = "Tome " + num + ": " + name; - } else { - name = "Tome " + num; - } - - double key = Double.parseDouble(num); - - map.put(key, new AbstractMap.SimpleEntry<String, URL>(name, - entry.getValue())); - } - urls = new ArrayList<Entry<String, URL>>(map.values()); - } catch (NumberFormatException e) { - Instance.getTraceHandler() - .error(new IOException( - "Cannot find a tome number, revert to default sorting", - e)); - // by default, the chapters are in reversed order - Collections.reverse(urls); - } - } else { - // by default, the chapters are in reversed order - Collections.reverse(urls); - } - - return urls; - } - - @Override - protected String getChapterContent(URL chapUrl, int number, Progress pg) - throws IOException { - if (pg == null) { - pg = new Progress(); - } - - StringBuilder builder = new StringBuilder(); - - String url = chapUrl.toString(); - InputStream imageIn = null; - Element imageDoc = null; - - // 1. find out how many images there are - int size; - try { - // note: when used, the base URL can be an ad-page - imageIn = openEx(url + "1.html"); - imageDoc = DataUtil.load(imageIn, "UTF-8", url + "1.html"); - } catch (IOException e) { - Instance.getTraceHandler().error( - new IOException("Cannot get image " + 1 + " of manga", e)); - } finally { - if (imageIn != null) { - imageIn.close(); - } - } - Element select = imageDoc.getElementsByClass("m").first(); - Elements options = select.getElementsByTag("option"); - size = options.size() - 1; // last is "Comments" - - pg.setMinMax(0, size); - - // 2. list them - for (int i = 1; i <= size; i++) { - if (i > 1) { // because first one was opened for size - try { - imageIn = openEx(url + i + ".html"); - imageDoc = DataUtil.load(imageIn, "UTF-8", url + i - + ".html"); - - String linkImage = imageDoc.getElementById("image").absUrl( - "src"); - if (linkImage != null) { - builder.append("["); - // to help with the retry and the originalUrl, part 1 - builder.append(withoutQuery(linkImage)); - builder.append("]<br/>"); - } - - // to help with the retry and the originalUrl, part 2 - refresh(linkImage); - } catch (IOException e) { - Instance.getTraceHandler().error( - new IOException("Cannot get image " + i - + " of manga", e)); - } finally { - if (imageIn != null) { - imageIn.close(); - } - } - } - } - - return builder.toString(); - } - - /** - * Refresh the {@link URL} by calling {@link MangaFox#openEx(String)}. - * - * @param url - * the URL to refresh - * - * @return TRUE if it was refreshed - */ - private boolean refresh(String url) { - try { - openEx(url).close(); - return true; - } catch (Exception e) { - return false; - } - } - - /** - * Open the URL through the cache, but: retry a second time after 100ms if - * it fails, remove the query part of the {@link URL} before saving it to - * the cache (so it can be recalled later). - * - * @param url - * the {@link URL} - * - * @return the resource - * - * @throws IOException - * in case of I/O error - */ - private InputStream openEx(String url) throws IOException { - try { - return Instance.getCache().open(new URL(url), withoutQuery(url), - this, true); - } catch (Exception e) { - // second chance - try { - Thread.sleep(100); - } catch (InterruptedException ee) { - } - - return Instance.getCache().open(new URL(url), withoutQuery(url), - this, true); - } - } - - /** - * Return the same input {@link URL} but without the query part. - * - * @param url - * the inpiut {@link URL} as a {@link String} - * - * @return the input {@link URL} without query - */ - private URL withoutQuery(String url) { - URL o = null; - try { - // Remove the query from o (originalUrl), so it can be cached - // correctly - o = new URL(url); - o = new URL(o.getProtocol() + "://" + o.getHost() + o.getPath()); - - return o; - } catch (MalformedURLException e) { - return null; - } - } - - /** - * Explode an HTML comma-separated list of values into a non-duplicate text - * {@link List} . - * - * @param values - * the comma-separated values in HTML format - * - * @return the full list with no duplicate in text format - */ - private List<String> explode(String values) { - List<String> list = new ArrayList<String>(); - if (values != null && !values.isEmpty()) { - for (String auth : values.split(",")) { - String a = StringUtils.unhtml(auth).trim(); - if (!a.isEmpty() && !list.contains(a.trim())) { - list.add(a); - } - } - } - - return list; - } - - @Override - protected boolean supports(URL url) { - return "mangafox.me".equals(url.getHost()) - || "www.mangafox.me".equals(url.getHost()) - || "fanfox.net".equals(url.getHost()) - || "www.fanfox.net".equals(url.getHost()); - } -} diff --git a/supported/MangaHub.java b/supported/MangaHub.java new file mode 100644 index 0000000..706a591 --- /dev/null +++ b/supported/MangaHub.java @@ -0,0 +1,214 @@ +package be.nikiroo.fanfix.supported; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map.Entry; + +import org.jsoup.nodes.Element; + +import be.nikiroo.fanfix.Instance; +import be.nikiroo.fanfix.bundles.Config; +import be.nikiroo.fanfix.data.MetaData; +import be.nikiroo.utils.Image; +import be.nikiroo.utils.Progress; +import be.nikiroo.utils.StringUtils; + +/** + * Support class for <a href="https://mangahub.io/">MangaHub</a>, a website + * dedicated to Manga. + * + * @author niki + */ +class MangaHub extends BasicSupport { + @Override + protected boolean isHtml() { + return true; + } + + @Override + protected MetaData getMeta() throws IOException { + MetaData meta = new MetaData(); + + meta.setTitle(getTitle()); + meta.setDate(""); + meta.setAuthor(getAuthor()); + meta.setTags(getTags()); + meta.setSource(getType().getSourceName()); + meta.setUrl(getSource().toString()); + meta.setPublisher(getType().getSourceName()); + meta.setUuid(getSource().toString()); + meta.setLuid(""); + meta.setLang("en"); + meta.setSubject("manga"); + meta.setType(getType().toString()); + meta.setImageDocument(true); + meta.setCover(getCover()); + + return meta; + } + + private String getTitle() { + Element doc = getSourceNode(); + + Element el = doc.getElementsByTag("h1").first(); + if (el != null) { + return StringUtils.unhtml(el.text()).trim(); + } + + return null; + } + + private String getAuthor() { + String author = ""; + + Element el = getSourceNode().select("h1+div span:not([class])").first(); + if (el != null) + author = StringUtils.unhtml(el.text()).trim(); + return author; + } + + private List<String> getTags() { + return getListA("genre-label"); + } + + private List<String> getListA(String uniqueClass) { + List<String> list = new ArrayList<String>(); + + Element doc = getSourceNode(); + Element el = doc.getElementsByClass(uniqueClass).first(); + if (el != null) { + for (Element valueA : el.getElementsByTag("a")) { + list.add(StringUtils.unhtml(valueA.text()).trim()); + } + } + + return list; + } + + @Override + protected String getDesc() { + Element doc = getSourceNode(); + Element title = doc.getElementsByClass("fullcontent").first(); + if (title != null) { + return StringUtils.unhtml(title.text()).trim(); + } + + return null; + } + + private Image getCover() { + Element doc = getSourceNode(); + Element cover = doc.getElementsByClass("manga-thumb").first(); + if (cover != null) { + try { + return bsImages.getImage(this, new URL(cover.absUrl("src"))); + } catch (MalformedURLException e) { + Instance.getInstance().getTraceHandler().error(e); + } + } + + return null; + } + + @Override + protected List<Entry<String, URL>> getChapters(Progress pg) { + List<Entry<String, URL>> urls = new ArrayList<Entry<String, URL>>(); + + Element doc = getSourceNode(); + for (Element el : doc.getElementsByClass("list-group-item")) { + Element urlEl = el.getElementsByTag("a").first(); + if (urlEl == null) + continue; + + String url = urlEl.absUrl("href"); + + String title = ""; + el = el.getElementsByClass("text-secondary").first(); + if (el != null) { + title = StringUtils.unhtml(el.text()).trim(); + } + + try { + urls.add(new AbstractMap.SimpleEntry<String, URL>(title, new URL(url))); + } catch (Exception e) { + Instance.getInstance().getTraceHandler().error(e); + } + } + + // by default, the chapters are in reversed order + Collections.reverse(urls); + + return urls; + } + + @Override + protected String getChapterContent(URL chapUrl, int number, Progress pg) throws IOException { + if (pg == null) { + pg = new Progress(); + } + + // 1. Get the title and chapter url part + String path = chapUrl.getPath(); + if (path.endsWith("/")) { + path = path.substring(0, path.length() - "/".length()); + } + String tab[] = path.split("/"); + String chap = tab[tab.length - 1]; + String title = tab[tab.length - 2]; + + if (chap.startsWith("chapter-")) { + chap = chap.substring("chapter-".length()); + } + + // 2. generate an image base + String base = "https://img.mghubcdn.com/file/imghub/" + title + "/" + chap + "/"; + + // 3. add each chapter + StringBuilder builder = new StringBuilder(); + + int i = 1; + String url = base + i + ".jpg"; + while (getHttpStatus(new URL(url)) != 404) { + builder.append("["); + builder.append(url); + builder.append("]<br/>"); + + i++; + url = base + i + ".jpg"; + } + + return builder.toString(); + } + + // HTTP response code, or -1 if other error + // TODO: move that to Downloader? + private int getHttpStatus(URL url) { + try { + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + try { + conn.setRequestMethod("HEAD"); + conn.setRequestProperty("User-Agent", Instance.getInstance().getConfig().getString(Config.NETWORK_USER_AGENT)); + conn.setRequestProperty("Accept-Encoding", "gzip"); + conn.setRequestProperty("Accept", "*/*"); + conn.setRequestProperty("Charset", "utf-8"); + + return conn.getResponseCode(); + } finally { + conn.disconnect(); + } + } catch (Exception e) { + return -1; + } + } + + @Override + protected boolean supports(URL url) { + return "mangahub.io".equals(url.getHost()) || "www.mangahub.io".equals(url.getHost()); + } +} diff --git a/supported/MangaLel.java b/supported/MangaLel.java index 1ba51bc..9929699 100644 --- a/supported/MangaLel.java +++ b/supported/MangaLel.java @@ -149,15 +149,14 @@ class MangaLel extends BasicSupport { InputStream coverIn; try { - coverIn = Instance.getCache().open(new URL(coverUrl), this, - true); + coverIn = Instance.getInstance().getCache().open(new URL(coverUrl), this, true); try { return new Image(coverIn); } finally { coverIn.close(); } } catch (IOException e) { - Instance.getTraceHandler().error(e); + Instance.getInstance().getTraceHandler().error(e); } } } @@ -209,7 +208,7 @@ class MangaLel extends BasicSupport { StringBuilder builder = new StringBuilder(); - InputStream in = Instance.getCache().open(chapUrl, this, false); + InputStream in = Instance.getInstance().getCache().open(chapUrl, this, false); try { Element pageDoc = DataUtil.load(in, "UTF-8", chapUrl.toString()); Element content = pageDoc.getElementById("content"); diff --git a/supported/SupportType.java b/supported/SupportType.java index ba18949..7ace726 100644 --- a/supported/SupportType.java +++ b/supported/SupportType.java @@ -20,7 +20,7 @@ public enum SupportType { /** Fanfictions from a lot of different universes */ FANFICTION, /** Website with lots of Mangas */ - MANGAFOX, + MANGAHUB, /** Furry website with comics support */ E621, /** Furry website with stories */ @@ -59,8 +59,8 @@ public enum SupportType { return "info-text"; case MANGA_LEL: return "MangaLEL"; - case MANGAFOX: - return "MangaFox.me"; + case MANGAHUB: + return "MangaHub.io"; case TEXT: return "text"; case YIFFSTAR: @@ -77,11 +77,10 @@ public enum SupportType { * @return the description */ public String getDesc() { - String desc = Instance.getTrans().getStringX(StringId.INPUT_DESC, - this.name()); + String desc = Instance.getInstance().getTrans().getStringX(StringId.INPUT_DESC, this.name()); if (desc == null) { - desc = Instance.getTrans().getString(StringId.INPUT_DESC, this); + desc = Instance.getInstance().getTrans().getString(StringId.INPUT_DESC, this); } return desc; diff --git a/supported/Text.java b/supported/Text.java index 8af4a40..c54b6a5 100644 --- a/supported/Text.java +++ b/supported/Text.java @@ -53,8 +53,7 @@ class Text extends BasicSupport { try { in.reset(); } catch (IOException e) { - Instance.getTraceHandler().error( - new IOException("Cannot reset the Text stream", e)); + Instance.getInstance().getTraceHandler().error(new IOException("Cannot reset the Text stream", e)); } return in; @@ -201,8 +200,7 @@ class Text extends BasicSupport { Image cover = bsImages.getImage(this, sourceFile.getParentFile(), path); if (cover != null) { try { - File tmp = Instance.getTempFiles().createTempFile( - "test_cover_image"); + File tmp = Instance.getInstance().getTempFiles().createTempFile("test_cover_image"); ImageUtils.getInstance().saveAsImage(cover, tmp, "png"); tmp.delete(); } catch (IOException e) { @@ -271,9 +269,8 @@ class Text extends BasicSupport { try { in.close(); } catch (IOException e) { - Instance.getTraceHandler().error( - new IOException( - "Cannot close the text source file input", e)); + Instance.getInstance().getTraceHandler() + .error(new IOException("Cannot close the text source file input", e)); } } @@ -310,7 +307,7 @@ class Text extends BasicSupport { file = assureNoTxt(file); file = new File(file.getPath() + ".info"); } catch (URISyntaxException e) { - Instance.getTraceHandler().error(e); + Instance.getInstance().getTraceHandler().error(e); file = null; } @@ -350,9 +347,8 @@ class Text extends BasicSupport { */ static private String detectChapter(String line, int number) { line = line.toUpperCase(); - for (String lang : Instance.getConfig().getList(Config.CONF_CHAPTER)) { - String chapter = Instance.getConfig().getStringX( - Config.CONF_CHAPTER, lang); + for (String lang : Instance.getInstance().getConfig().getList(Config.CONF_CHAPTER)) { + String chapter = Instance.getInstance().getConfig().getStringX(Config.CONF_CHAPTER, lang); if (chapter != null && !chapter.isEmpty()) { chapter = chapter.toUpperCase() + " "; if (line.startsWith(chapter)) { diff --git a/supported/YiffStar.java b/supported/YiffStar.java index aad01a6..6974e9a 100644 --- a/supported/YiffStar.java +++ b/supported/YiffStar.java @@ -67,10 +67,8 @@ class YiffStar extends BasicSupport_Deprecated { public void login() throws IOException { // Note: this should not be necessary anymore // (the "/guest" trick is enough) - String login = Instance.getConfig().getString( - Config.LOGIN_YIFFSTAR_USER); - String password = Instance.getConfig().getString( - Config.LOGIN_YIFFSTAR_PASS); + String login = Instance.getInstance().getConfig().getString(Config.LOGIN_YIFFSTAR_USER); + String password = Instance.getInstance().getConfig().getString(Config.LOGIN_YIFFSTAR_PASS); if (login != null && !login.isEmpty() && password != null && !password.isEmpty()) { @@ -84,9 +82,8 @@ class YiffStar extends BasicSupport_Deprecated { // Cookies will actually be retained by the cache manager once // logged in - Instance.getCache() - .openNoCache(new URL("https://www.sofurry.com/user/login"), - this, post, null, null).close(); + Instance.getInstance().getCache() + .openNoCache(new URL("https://www.sofurry.com/user/login"), this, post, null, null).close(); } } @@ -96,8 +93,7 @@ class YiffStar extends BasicSupport_Deprecated { if (source.getPath().startsWith("/view")) { source = guest(source.toString()); // NO CACHE because we don't want the NotLoggedIn message later - InputStream in = Instance.getCache().openNoCache(source, this, - null, null, null); + InputStream in = Instance.getInstance().getCache().openNoCache(source, this, null, null, null); String line = getLine(in, "/browse/folder/", 0); if (line != null) { String[] tab = line.split("\""); @@ -109,7 +105,7 @@ class YiffStar extends BasicSupport_Deprecated { } } } catch (Exception e) { - Instance.getTraceHandler().error(e); + Instance.getInstance().getTraceHandler().error(e); } return super.getCanonicalUrl(source); @@ -136,7 +132,7 @@ class YiffStar extends BasicSupport_Deprecated { List<Entry<String, URL>> chaps = getChapters(source, in, null); if (!chaps.isEmpty()) { - in = Instance.getCache().open(chaps.get(0).getValue(), this, true); + in = Instance.getInstance().getCache().open(chaps.get(0).getValue(), this, true); String line = getLine(in, " name=\"og:image\"", 0); if (line != null) { int pos = -1; diff --git a/test/BasicSupportDeprecatedTest.java b/test/BasicSupportDeprecatedTest.java index 9f40a80..c8c4b40 100644 --- a/test/BasicSupportDeprecatedTest.java +++ b/test/BasicSupportDeprecatedTest.java @@ -24,14 +24,10 @@ import be.nikiroo.utils.test.TestLauncher; class BasicSupportDeprecatedTest extends TestLauncher { // quote chars - private char openQuote = Instance.getTrans().getCharacter( - StringId.OPEN_SINGLE_QUOTE); - private char closeQuote = Instance.getTrans().getCharacter( - StringId.CLOSE_SINGLE_QUOTE); - private char openDoubleQuote = Instance.getTrans().getCharacter( - StringId.OPEN_DOUBLE_QUOTE); - private char closeDoubleQuote = Instance.getTrans().getCharacter( - StringId.CLOSE_DOUBLE_QUOTE); + private char openQuote = Instance.getInstance().getTrans().getCharacter(StringId.OPEN_SINGLE_QUOTE); + private char closeQuote = Instance.getInstance().getTrans().getCharacter(StringId.CLOSE_SINGLE_QUOTE); + private char openDoubleQuote = Instance.getInstance().getTrans().getCharacter(StringId.OPEN_DOUBLE_QUOTE); + private char closeDoubleQuote = Instance.getInstance().getTrans().getCharacter(StringId.CLOSE_DOUBLE_QUOTE); public BasicSupportDeprecatedTest(String[] args) { super("BasicSupportDeprecated", args); @@ -256,9 +252,9 @@ class BasicSupportDeprecatedTest extends TestLauncher { public void test() throws Exception { BasicSupportEmpty support = new BasicSupportEmpty(); - char openDoubleQuote = Instance.getTrans() + char openDoubleQuote = Instance.getInstance().getTrans() .getCharacter(StringId.OPEN_DOUBLE_QUOTE); - char closeDoubleQuote = Instance.getTrans() + char closeDoubleQuote = Instance.getInstance().getTrans() .getCharacter(StringId.CLOSE_DOUBLE_QUOTE); String content = null; diff --git a/test/BasicSupportUtilitiesTest.java b/test/BasicSupportUtilitiesTest.java index 4e34891..9cec220 100644 --- a/test/BasicSupportUtilitiesTest.java +++ b/test/BasicSupportUtilitiesTest.java @@ -23,14 +23,10 @@ import be.nikiroo.utils.test.TestLauncher; class BasicSupportUtilitiesTest extends TestLauncher { // quote chars - private char openQuote = Instance.getTrans().getCharacter( - StringId.OPEN_SINGLE_QUOTE); - private char closeQuote = Instance.getTrans().getCharacter( - StringId.CLOSE_SINGLE_QUOTE); - private char openDoubleQuote = Instance.getTrans().getCharacter( - StringId.OPEN_DOUBLE_QUOTE); - private char closeDoubleQuote = Instance.getTrans().getCharacter( - StringId.CLOSE_DOUBLE_QUOTE); + private char openQuote = Instance.getInstance().getTrans().getCharacter(StringId.OPEN_SINGLE_QUOTE); + private char closeQuote = Instance.getInstance().getTrans().getCharacter(StringId.CLOSE_SINGLE_QUOTE); + private char openDoubleQuote = Instance.getInstance().getTrans().getCharacter(StringId.OPEN_DOUBLE_QUOTE); + private char closeDoubleQuote = Instance.getInstance().getTrans().getCharacter(StringId.CLOSE_DOUBLE_QUOTE); public BasicSupportUtilitiesTest(String[] args) { super("BasicSupportUtilities", args); @@ -229,9 +225,9 @@ class BasicSupportUtilitiesTest extends TestLauncher { public void test() throws Exception { BasicSupportParaPublic support = new BasicSupportParaPublic(); - char openDoubleQuote = Instance.getTrans() + char openDoubleQuote = Instance.getInstance().getTrans() .getCharacter(StringId.OPEN_DOUBLE_QUOTE); - char closeDoubleQuote = Instance.getTrans() + char closeDoubleQuote = Instance.getInstance().getTrans() .getCharacter(StringId.CLOSE_DOUBLE_QUOTE); String content = null; diff --git a/test/ConversionTest.java b/test/ConversionTest.java index 607f49b..d730b3b 100644 --- a/test/ConversionTest.java +++ b/test/ConversionTest.java @@ -138,8 +138,8 @@ class ConversionTest extends TestLauncher { BasicOutput.OutputType type) throws Exception { final List<String> errors = new ArrayList<String>(); - TraceHandler previousTraceHandler = Instance.getTraceHandler(); - Instance.setTraceHandler(new TraceHandler(true, true, 0) { + TraceHandler previousTraceHandler = Instance.getInstance().getTraceHandler(); + Instance.getInstance().setTraceHandler(new TraceHandler(true, true, 0) { @Override public void error(String message) { errors.add(message); @@ -178,7 +178,7 @@ class ConversionTest extends TestLauncher { return target; } finally { - Instance.setTraceHandler(previousTraceHandler); + Instance.getInstance().setTraceHandler(previousTraceHandler); } } diff --git a/test/LibraryTest.java b/test/LibraryTest.java index cf85b71..da44438 100644 --- a/test/LibraryTest.java +++ b/test/LibraryTest.java @@ -43,7 +43,7 @@ class LibraryTest extends TestLauncher { addTest(new TestCase("getList") { @Override public void test() throws Exception { - List<MetaData> metas = lib.getList(); + List<MetaData> metas = lib.getList().getMetas(); assertEquals(errMess, Arrays.asList(), titlesAsList(metas)); } @@ -55,7 +55,7 @@ class LibraryTest extends TestLauncher { lib.save(story(luid1, name1, source1, author1), luid1, null); - List<MetaData> metas = lib.getList(); + List<MetaData> metas = lib.getList().getMetas(); assertEquals(errMess, Arrays.asList(name1), titlesAsList(metas)); } @@ -69,14 +69,14 @@ class LibraryTest extends TestLauncher { lib.save(story(luid2, name2, source2, author1), luid2, null); - metas = lib.getList(); + metas = lib.getList().getMetas(); assertEquals(errMess, Arrays.asList(name1, name2), titlesAsList(metas)); lib.save(story(luid3, name3, source2, author1), luid3, null); - metas = lib.getList(); + metas = lib.getList().getMetas(); assertEquals(errMess, Arrays.asList(name1, name2, name3), titlesAsList(metas)); @@ -90,7 +90,7 @@ class LibraryTest extends TestLauncher { lib.save(story(luid3, name3ex, source2, author2), luid3, null); - List<MetaData> metas = lib.getList(); + List<MetaData> metas = lib.getList().getMetas(); assertEquals(errMess, Arrays.asList(name1, name2, name3ex), titlesAsList(metas)); @@ -100,7 +100,7 @@ class LibraryTest extends TestLauncher { addTest(new TestCase("getList with results") { @Override public void test() throws Exception { - List<MetaData> metas = lib.getList(); + List<MetaData> metas = lib.getList().getMetas(); assertEquals(3, metas.size()); } }); @@ -110,13 +110,13 @@ class LibraryTest extends TestLauncher { public void test() throws Exception { List<MetaData> metas = null; - metas = lib.getListBySource(source1); + metas = lib.getList().filter(source1, null, null); assertEquals(1, metas.size()); - metas = lib.getListBySource(source2); + metas = lib.getList().filter(source2, null, null); assertEquals(2, metas.size()); - metas = lib.getListBySource(null); + metas = lib.getList().filter((String)null, null, null); assertEquals(3, metas.size()); } }); @@ -126,13 +126,13 @@ class LibraryTest extends TestLauncher { public void test() throws Exception { List<MetaData> metas = null; - metas = lib.getListByAuthor(author1); + metas = lib.getList().filter(null, author1, null); assertEquals(2, metas.size()); - metas = lib.getListByAuthor(author2); + metas = lib.getList().filter(null, author2, null); assertEquals(1, metas.size()); - metas = lib.getListByAuthor(null); + metas = lib.getList().filter((String)null, null, null); assertEquals(3, metas.size()); } }); @@ -144,13 +144,13 @@ class LibraryTest extends TestLauncher { lib.changeSource(luid3, source1, null); - metas = lib.getListBySource(source1); + metas = lib.getList().filter(source1, null, null); assertEquals(2, metas.size()); - metas = lib.getListBySource(source2); + metas = lib.getList().filter(source2, null, null); assertEquals(1, metas.size()); - metas = lib.getListBySource(null); + metas = lib.getList().filter((String)null, null, null); assertEquals(3, metas.size()); } }); @@ -164,13 +164,13 @@ class LibraryTest extends TestLauncher { lib.save(story(luid3, "My story 3", source2, author2), luid3, null); - metas = lib.getListBySource(source1); + metas = lib.getList().filter(source1, null, null); assertEquals(1, metas.size()); - metas = lib.getListBySource(source2); + metas = lib.getList().filter(source2, null, null); assertEquals(2, metas.size()); - metas = lib.getListBySource(null); + metas = lib.getList().filter((String)null, null, null); assertEquals(3, metas.size()); } }); diff --git a/test/Test.java b/test/Test.java index d772561..5ec24a4 100644 --- a/test/Test.java +++ b/test/Test.java @@ -51,7 +51,7 @@ public class Test extends TestLauncher { */ public Test(String[] args, boolean urlsAllowed) throws IOException { super("Fanfix", args); - Instance.setTraceHandler(null); + Instance.getInstance().setTraceHandler(null); addSeries(new BasicSupportUtilitiesTest(args)); addSeries(new BasicSupportDeprecatedTest(args)); addSeries(new LibraryTest(args)); @@ -106,7 +106,7 @@ public class Test extends TestLauncher { // Only download files if allowed: boolean offline = new File("test/OFFLINE").exists(); - Instance.getCache().setOffline(offline); + Instance.getInstance().getCache().setOffline(offline); @@ -126,7 +126,7 @@ public class Test extends TestLauncher { System.setProperty("CONFIG_DIR", tmpConfig.getAbsolutePath()); Instance.init(true); - Instance.getCache().setOffline(offline); + Instance.getInstance().getCache().setOffline(offline); TestLauncher tests = new Test(args, urlsAllowed); tests.setDetails(verbose); @@ -140,7 +140,7 @@ public class Test extends TestLauncher { tempFiles.close(); // This is usually done in Fanfix.Main: - Instance.getTempFiles().close(); + Instance.getInstance().getTempFiles().close(); } System.exit(result);