Merge branch 'master' into subtree
authorNiki Roo <niki@nikiroo.be>
Fri, 10 Apr 2020 17:12:41 +0000 (19:12 +0200)
committerNiki Roo <niki@nikiroo.be>
Fri, 10 Apr 2020 17:12:41 +0000 (19:12 +0200)
49 files changed:
DataLoader.java
Instance.java
Main.java
VersionCheck.java
bundles/resources_core.properties
bundles/resources_core_fr.properties
library/BasicLibrary.java
library/CacheLibrary.java
library/LocalLibrary.java
library/MetaResultList.java [new file with mode: 0644]
library/RemoteLibrary.java
library/RemoteLibraryServer.java
output/BasicOutput.java
output/Cbz.java
output/Epub.java
output/Html.java
output/InfoCover.java
output/InfoText.java
output/LaTeX.java
output/Text.java
reader/BasicReader.java
searchable/BasicSearchable.java
searchable/Fanfiction.java
searchable/MangaLel.java
supported/BasicSupport.java
supported/BasicSupportHelper.java
supported/BasicSupportImages.java
supported/BasicSupportPara.java
supported/BasicSupport_Deprecated.java
supported/Cbz.java
supported/E621.java
supported/EHentai.java
supported/Epub.java
supported/Fanfiction.java
supported/Fimfiction.java
supported/FimfictionApi.java
supported/Html.java
supported/InfoReader.java
supported/MangaFox.java [deleted file]
supported/MangaHub.java [new file with mode: 0644]
supported/MangaLel.java
supported/SupportType.java
supported/Text.java
supported/YiffStar.java
test/BasicSupportDeprecatedTest.java
test/BasicSupportUtilitiesTest.java
test/ConversionTest.java
test/LibraryTest.java
test/Test.java

index 3e0e7704e8e93068d93b7454a25e7f5fffb311f1..901e8da4c13d8a338cccf2945be17a52adef5abd 100644 (file)
@@ -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);
        }
index 561e2f685218442c05f98187df6738afc779ced2..f48d05b7d4cd84994eeb7e5e238018e99317afbd 100644 (file)
@@ -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.
         * <p>
-        * 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 <tt>force</tt>.
+        * Initialise the instance -- if already initialised, nothing will happen unless
+        * you pass TRUE to <tt>force</tt>.
         * <p>
-        * 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.
         * <p>
-        * 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
-        * <tt>force</tt> 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 <tt>force</tt> 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.
+        * <p>
+        * 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.
+        * <p>
+        * 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.
         * <p>
         * 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;
                        }
index 2ed276b1ea335dce6be6ed116b8e7973edd9f0ec..961816a3f63e96afc4611489e5d83d85c9e2898a 100644 (file)
--- 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;
                }
        }
index 2c9a0328aca615aa982f58f68262b636e9758086..f64159abb97c3fe3236bc272710402a1e32631f7 100644 (file)
@@ -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<Version> newer = new ArrayList<Version>();
                Map<Version, List<String>> changes = new HashMap<Version, List<String>>();
 
-               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));
                        }
                }
 
index d656ed6626204c6c68bffd1511b579a7faded50e..dc7881ad2e42f83a129c0b210e877a60f86d2c02 100644 (file)
@@ -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
index 9bf3626304733e61586946b13762507dbb871842..a64a5a093920dcb38bc7f9d056eb5c62f1a2472c 100644 (file)
@@ -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
index 099859dcfaffed075f30b3d716b790f644a43a09..c2ab12b7b735d8349b51ea1beaaeab3ca7bac8e8 100644 (file)
@@ -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.
         * <p>
@@ -142,7 +149,7 @@ abstract public class BasicLibrary {
                        return custom;
                }
 
-               List<MetaData> metas = getListBySource(source);
+               List<MetaData> 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<MetaData> metas = getListByAuthor(author);
+               List<MetaData> 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
         * <b>MAY</b> not have the cover included).
+        * <p>
+        * The returned list <b>MUST</b> 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 </t>true</tt>).
+        * 
+        * @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.
+        * <p>
+        * 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<MetaData> 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.
-        * <p>
-        * 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<MetaData> getListBySource(String type)
-                       throws IOException {
-               List<MetaData> list = new ArrayList<MetaData>();
-               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.
-        * <p>
-        * 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<MetaData> getListByAuthor(String author)
-                       throws IOException {
-               List<MetaData> list = new ArrayList<MetaData>();
-               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);
        }
 
        /**
index e8743b63cd9d18ca0ef0ba3316aa204433b4bf34..694f9ec267501d546ba8b44413cfeb346ef8963d 100644 (file)
@@ -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<MetaData> metas;
+       private List<MetaData> metasReal;
+       private List<MetaData> metasMixed;
        private BasicLibrary lib;
        private LocalLibrary cacheLib;
 
        /**
         * Create a cache library around the given one.
         * <p>
-        * 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<MetaData> getMetas(Progress pg) throws IOException {
+       protected synchronized List<MetaData> 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<MetaData>();
+                       TreeSet<String> cachedLuids = new TreeSet<String>();
+                       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<MetaData>(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.
+        * <p>
+        * <b>Make sure to always use {@link MetaData} from the cached library 
+        * in priority, here.</b>
+        * 
+        * @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<MetaData> 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<MetaData> 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.
-        * <p>
-        * 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;
        }
index ffcd8af99d0a482b27e939435fbbd6548f32550d..80d216b84c216fd32a5dc8cf26f9e4dc2a28353c 100644 (file)
@@ -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<MetaData> getMetas(Progress pg) {
+       protected synchronized List<MetaData> getMetas(Progress pg) {
                return new ArrayList<MetaData>(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 (file)
index 0000000..886defe
--- /dev/null
@@ -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<MetaData> metas;
+
+       // Lazy lists:
+       // TODO: sync-protect them?
+       private List<String> sources;
+       private List<String> authors;
+       private List<String> tags;
+
+       // can be null (will consider it empty)
+       public MetaResultList(List<MetaData> metas) {
+               if (metas == null) {
+                       metas = new ArrayList<MetaData>();
+               }
+
+               Collections.sort(metas);
+               this.metas = metas;
+       }
+
+       // not NULL
+       // sorted
+       public List<MetaData> getMetas() {
+               return metas;
+       }
+
+       public List<String> getSources() {
+               if (sources == null) {
+                       sources = new ArrayList<String>();
+                       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<String> getSources(String source) {
+               List<String> linked = new ArrayList<String>();
+               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<String> getAuthors() {
+               if (authors == null) {
+                       authors = new ArrayList<String>();
+                       for (MetaData meta : metas) {
+                               if (!authors.contains(meta.getAuthor()))
+                                       authors.add(meta.getAuthor());
+                       }
+               }
+
+               return authors;
+       }
+
+       public List<String> getTags() {
+               if (tags == null) {
+                       tags = new ArrayList<String>();
+                       for (MetaData meta : metas) {
+                               for (String tag : meta.getTags()) {
+                                       if (!tags.contains(tag))
+                                               tags.add(tag);
+                               }
+                       }
+               }
+
+               return authors;
+       }
+
+       // helper
+       public List<MetaData> filter(String source, String author, String tag) {
+               List<String> sources = source == null ? null : Arrays.asList(source);
+               List<String> authors = author == null ? null : Arrays.asList(author);
+               List<String> 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<MetaData> filter(List<String> sources, List<String> authors, List<String> 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<String> folders = new ArrayList<String>();
+                       List<String> leaves = new ArrayList<String>();
+                       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<MetaData> result = new ArrayList<MetaData>();
+               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;
+       }
+}
index ce4305aadad96bfe9446817d467234545ccfce7a..65be7b1759e4893b2412f2c74cc00c0b3a95a2a7 100644 (file)
@@ -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<MetaData> getMetas(Progress pg) throws IOException {
+       protected synchronized List<MetaData> 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;
                                        }
 
index dc9688c4de69c0348a1ee7dbac4665ec581d905a..4f89a1fa19263c9d4bedf513274442660d3a023f 100644 (file)
@@ -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<String> whitelist = Instance.getConfig().getList(
-                               Config.SERVER_WHITELIST);
+               List<String> whitelist = Instance.getInstance().getConfig().getList(Config.SERVER_WHITELIST);
                if (whitelist == null) {
                        whitelist = new ArrayList<String>();
                }
@@ -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<String> allowed = Instance.getConfig().getList(
-                                       Config.SERVER_ALLOWED_SUBKEYS);
+                       List<String> 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;
index 15d8cc1c7c88c4b454c90c97a51f77e1740dcb5f..41634faaddbceabc89b4ad1be016c88bbaedc0de 100644 (file)
@@ -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()) {
index 3d9008299052451539d1e99db77c426d8e1bebd0..ee671e779668483bc0efd82038afa898905c3cee 100644 (file)
@@ -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
index b7401d3922b2c182fd2ff1840ff1182986bd54cc..fc2dc8c982127210c308d6a9dc70a20b667162eb 100644 (file)
@@ -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("                  <img alt='page image' class='page-image' src='images/"
                                        + getCurrentImageBestName(false) + "'/>");
                        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      <!-- Images -->");
 
                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      <item id=\"cover\" href=\"images/cover."
@@ -487,7 +484,7 @@ class Epub extends BasicOutput {
                        author = meta.getAuthor();
                }
 
-               String format = Instance.getConfig()
+               String format = Instance.getInstance().getConfig()
                                .getString(Config.FILE_FORMAT_IMAGE_FORMAT_COVER).toLowerCase();
 
                builder.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
index ca802a50b60770c73d1ceef3388037a2222c1482..da79466a40d9cc2fcf80872d77ef6e588398e732 100644 (file)
@@ -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");
index 6bfa4dd0ac504c8d74bcfb4a78b54ce5b75d5ae5..d8ca49a6876bcb1a759845d117b26cdd302bdfe6 100644 (file)
@@ -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));
                        }
                }
        }
index cce715dcca8d228d36b51776a5d6cc4f44166e3f..935da8704d1a9ff5a02dd15dd6cef0c50705de5c 100644 (file)
@@ -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");
index 321556feed92054f0b134d19ad1a8bfcf5401340..a15e67c900c7fe59dbbde4aa901c7bc246255e61 100644 (file)
@@ -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));
                                }
                        }
                }
index 4a45e5430fba9465b1e92a590bcae9cc18b28360..f0516dc629ebca9bf65b7bf86fa559028004f622 100644 (file)
@@ -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));
                        }
                }
 
index 61769c01f87951c5546ae59cc12948e88c1ebe9e..7f79da3a8ec62b854b7bcdba62838a23779fcaf4 100644 (file)
@@ -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() });
                }
index d38505e7660fb9f0348394ac23390fa3cdb4aa65..b943abd25401f426bad456140eea004be06437fb 100644 (file)
@@ -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:
index c2dfd5d5714a8f4c5e388aeccf7a8cd51053f303..e2fba1ff404f17d2a23bc18defbc2b03d7a425e3 100644 (file)
@@ -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?
index 3e2924f31d5d84a5082fec20b0058a7091c86f5d..5ba21a0e1ce25b799dc0b9a6d14d3a447135ef01 100644 (file)
@@ -89,9 +89,8 @@ class MangaLel extends BasicSearchable {
        private List<MetaData> getResults(String sourceUrl) throws IOException {
                List<MetaData> metas = new ArrayList<MetaData>();
 
-               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());
                                        }
                                }
 
index d3c0ebb9a379a52047f554622bf56fa892af2d20..bc91e8b40d0688e96b8ae8698f9e252ae2fe3bec 100644 (file)
@@ -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();
index 41716df4e4d17952cd0e77aeac28eee20e837aca..b5c7bb9cdee9ccaf96c1de6c38eeb4aaa76a9537 100644 (file)
@@ -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();
index 69a7c86720002b18c36bd2a4a79ee72353984429..576cb17e78bb3abfe845a1b053df47618636e5c6 100644 (file)
@@ -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;
index ef4d7d778f192ed10335366886768517399d9f3a..58c363af59b77e1b4f4d1c323fefe2af350ad31b 100644 (file)
@@ -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();
index 1faac03eba405657f6861f53660f2150357a4387..4a7b65b93d66c1899853888a759842e49e92ff9f 100644 (file)
@@ -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);
        }
 
        /**
index 22e436a22188b6e0442ba5f21c977ca0ddaed90c..76b66aba7c75fa24317eb4daca6ff75854658326 100644 (file)
@@ -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<String, Image> images = new HashMap<String, Image>();
@@ -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);
                                        }
                                }
                        }
index dfa9e5ed6a60e4694fc8494dcf196b4328259ee6..f1660e18cb34a9da6373ac03e6918ccc630ff25f 100644 (file)
@@ -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 <a href="http://e621.net/">e621.net</a> and <a
- * href="http://e926.net/">e926.net</a>, a Furry website supporting comics,
+ * Support class for <a href="http://e621.net/">e621.net</a> and
+ * <a href="http://e926.net/">e926.net</a>, a Furry website supporting comics,
  * including some of MLP.
  * <p>
  * <a href="http://e926.net/">e926.net</a> 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<String> getTags(URL source, InputStream in, boolean authors) {
-               List<String> tags = new ArrayList<String>();
-
-               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("<br/>");
-                       if (pos >= 0) {
-                               images = images.substring(1, pos - 1);
-                               return getImage(this, null, images);
-                       }
+       protected List<Entry<String, URL>> 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<Entry<String, URL>>();
        }
 
-       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<Entry<String, URL>> getChapters(URL source, Progress pg, String baseUrl, String parameters)
+                       throws IOException {
+               List<Entry<String, URL>> urls = new ArrayList<Entry<String, URL>>();
 
-                       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("<a href=\"");
-                                                               if (pos >= 0) {
-                                                                       author = author.substring(pos);
-                                                                       pos = author.indexOf("</a>");
-                                                                       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<String, URL>("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, "<title>", 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);
        }
 }
index 67585cd477f90a257acd94c9d28c67bac07575f7..03c1557432194187cb54e2b43e9f4239d42c1668 100644 (file)
@@ -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()) {
index 82af11855fdc299226fe2f52ca536f17a07d1d00..f8e467831381185244eae24b15d3a96a6cb0f6cb 100644 (file)
@@ -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")) {
index fcf773bd78b787693cd3afa28febd8502f997fc6..282192e065bb82fd238c06b863d0e9a3647f4917 100644 (file)
@@ -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;
index e96ac4f5766eb601886e3b6574c27044fb33b81a..77267c1188a24438bec7f46c1097219f0d20e58c 100644 (file)
@@ -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);
                                        }
                                }
                        }
index c97ecf7d3e9ea2ff8a7cc782eea5bca660f9f265..6c6d7ba31caf2197356b68168447c7871b257a52 100644 (file)
@@ -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();
index c27dd32f181651186446bbe597c09b6f6b7d8c5b..900fa0a1772f0ffd5ecfcaf2fecfbd8b248168a0 100644 (file)
@@ -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));
                        }
                }
 
index c22dbd711bedca99d1bde9f08400ba8e83b069b7..220350e6dc904495de7de918e4843cf3d15dda01 100644 (file)
@@ -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 (file)
index dae2d31..0000000
+++ /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 (file)
index 0000000..706a591
--- /dev/null
@@ -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());
+       }
+}
index 1ba51bc0f5d8a5c32a0341526a5aac142ae3fff6..9929699cc43839b93e1b98752d205d562a08a845 100644 (file)
@@ -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");
index ba18949e504f76f72c6a444608dad05f98063523..7ace7269397ca5f679b0ee85cff8a6e094fb4a67 100644 (file)
@@ -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;
index 8af4a4084b2a2c91ca3bc0aea7f726c7781bc821..c54b6a5d44ce0a328d63451420c6a9c00a82bd3c 100644 (file)
@@ -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)) {
index aad01a68d06f515999c4557b902136603ffa13ad..6974e9ae98a52bfde44f703cb585a63a26810033 100644 (file)
@@ -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;
index 9f40a8040d63b3bda175a4af1b531ccbf3aa0cdb..c8c4b401727e7927af3ccca210ed158e4902c97b 100644 (file)
@@ -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;
index 4e348913ca9ee29a81cc1c06c36c8a059758979c..9cec2208c28a03a189adc10b31b4a97ac0b4b722 100644 (file)
@@ -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;
index 607f49ba744b955eba4bf21796ee54b03b9ba9a4..d730b3b5efecc85f8a1b581c0ae16dc719e66187 100644 (file)
@@ -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);
                }
        }
 
index cf85b71e9f9b96d9e5c732122eaff202d013530d..da44438d02027f0b30f219d428bd1c466d21ea54 100644 (file)
@@ -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());
                                        }
                                });
index d772561ad6ff008069ccecb6e98d894475ca6977..5ec24a43b1b6a0eee8ba68991c9b2fe9d86c2c7b 100644 (file)
@@ -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);