X-Git-Url: http://git.nikiroo.be/?p=fanfix.git;a=blobdiff_plain;f=src%2Fbe%2Fnikiroo%2Ffanfix%2FMain.java;h=35365444682489d81adf7b25ed864416d6c47abe;hp=6f77e443bebdab359bbf2589f2e89cb35c925f4d;hb=HEAD;hpb=aad0e5ae672189ac745a10d65e2d2d3d2b52899d diff --git a/src/be/nikiroo/fanfix/Main.java b/src/be/nikiroo/fanfix/Main.java index 6f77e44..3536544 100644 --- a/src/be/nikiroo/fanfix/Main.java +++ b/src/be/nikiroo/fanfix/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; @@ -21,19 +19,18 @@ import be.nikiroo.fanfix.library.CacheLibrary; import be.nikiroo.fanfix.library.LocalLibrary; import be.nikiroo.fanfix.library.RemoteLibrary; import be.nikiroo.fanfix.library.RemoteLibraryServer; +import be.nikiroo.fanfix.library.WebLibrary; +import be.nikiroo.fanfix.library.WebLibraryServer; import be.nikiroo.fanfix.output.BasicOutput; import be.nikiroo.fanfix.output.BasicOutput.OutputType; import be.nikiroo.fanfix.reader.BasicReader; -import be.nikiroo.fanfix.reader.Reader; -import be.nikiroo.fanfix.reader.Reader.ReaderType; +import be.nikiroo.fanfix.reader.CliReader; import be.nikiroo.fanfix.searchable.BasicSearchable; 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; +import be.nikiroo.utils.VersionCheck; /** * Main program entry point. @@ -42,7 +39,7 @@ import be.nikiroo.utils.serial.server.ServerObject; */ public class Main { private enum MainAction { - IMPORT, EXPORT, CONVERT, READ, READ_URL, LIST, HELP, SET_READER, START, VERSION, SERVER, STOP_SERVER, REMOTE, SET_SOURCE, SET_TITLE, SET_AUTHOR, SEARCH, SEARCH_TAG + IMPORT, EXPORT, CONVERT, READ, READ_URL, LIST, HELP, START, VERSION, SERVER, STOP_SERVER, REMOTE, SET_SOURCE, SET_TITLE, SET_AUTHOR, SEARCH, SEARCH_TAG } /** @@ -80,18 +77,32 @@ public class Main { *
  • --set-source [id] [new source]: change the source of the given story
  • *
  • --set-title [id] [new title]: change the title of the given story
  • *
  • --set-author [id] [new author]: change the author of the given story
  • - *
  • --set-reader [reader type]: set the reader type to CLI, TUI or LOCAL - * for this command
  • *
  • --version: get the version of the program
  • *
  • --server: start the server mode (see config file for parameters)
  • *
  • --stop-server: stop the running server on this port if any
  • - *
  • --remote [key] [host] [port]: use a the given remote library
  • + *
  • --remote [key] [host] [port]: use the given remote library
  • * * * @param args * see method description */ public static void main(String[] args) { + new Main().start(args); + } + + /** + * Start the default handling for the application. + *

    + * If specific actions were asked (with correct parameters), they will be + * forwarded to the different protected methods that you can override. + *

    + * At the end of the method, {@link Main#exit(int)} will be called; by + * default, it calls {@link System#exit(int)} if the status is not 0. + * + * @param args + * the arguments received from the system + */ + public void start(String [] args) { // Only one line, but very important: Instance.init(); @@ -117,6 +128,9 @@ public class Main { int exitCode = 0; for (int i = 0; exitCode == 0 && i < args.length; i++) { + if (args[i] == null) + continue; + // Action (--) handling: if (!noMoreActions && args[i].startsWith("--")) { if (args[i].equals("--")) { @@ -126,9 +140,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 +242,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 +283,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 +301,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; } } @@ -324,10 +332,6 @@ public class Main { case HELP: exitCode = 255; break; - case SET_READER: - exitCode = setReaderType(args[i]); - action = MainAction.START; - break; case START: exitCode = 255; // not supposed to be selected by user break; @@ -348,10 +352,19 @@ public class Main { } else if (port == null) { port = Integer.parseInt(args[i]); - BasicLibrary lib = new RemoteLibrary(key, host, port); - lib = new CacheLibrary(Instance.getRemoteDir(host), lib); + BasicLibrary lib; + if (host.startsWith("http://") + || host.startsWith("https://")) { + lib = new WebLibrary(key, host, port); + } else { + lib = new RemoteLibrary(key, host, port); + } + + lib = new CacheLibrary( + Instance.getInstance().getRemoteDir(host), lib, + Instance.getInstance().getUiConfig()); - BasicReader.setDefaultLibrary(lib); + Instance.getInstance().setLibrary(lib); action = MainAction.START; } else { @@ -388,129 +401,183 @@ public class Main { Progress pg = new Progress(); mainProgress.addProgress(pg, mainProgress.getMax()); - VersionCheck updates = VersionCheck.check(); - if (updates.isNewVersionAvailable()) { - // Sent to syserr so not to cause problem if one tries to capture a - // story content in text mode - System.err - .println("A new version of the program is available at https://github.com/nikiroo/fanfix/releases"); - System.err.println(""); - for (Version v : updates.getNewer()) { - System.err.println("\tVersion " + v); - System.err.println("\t-------------"); - System.err.println(""); - for (String it : updates.getChanges().get(v)) { - System.err.println("\t- " + it); - } - System.err.println(""); - } - } + VersionCheck updates = checkUpdates(); if (exitCode == 0) { switch (action) { case IMPORT: - exitCode = imprt(urlString, pg); - updates.ok(); // we consider it read + if (updates != null) { + // we consider it read + Instance.getInstance().setVersionChecked(); + } + + try { + exitCode = imprt(BasicReader.getUrl(urlString), pg); + } catch (MalformedURLException e) { + Instance.getInstance().getTraceHandler().error(e); + exitCode = 1; + } + break; case EXPORT: - exitCode = export(luid, sourceString, target, pg); - updates.ok(); // we consider it read + if (updates != null) { + // we consider it read + Instance.getInstance().setVersionChecked(); + } + + OutputType exportType = OutputType.valueOfNullOkUC(sourceString, null); + if (exportType == null) { + Instance.getInstance().getTraceHandler().error(new Exception(trans(StringId.OUTPUT_DESC, sourceString))); + exitCode = 1; + break; + } + + exitCode = export(luid, exportType, target, pg); + break; case CONVERT: - exitCode = convert(urlString, sourceString, target, + if (updates != null) { + // we consider it read + Instance.getInstance().setVersionChecked(); + } + + OutputType convertType = OutputType.valueOfAllOkUC(sourceString, null); + if (convertType == null) { + Instance.getInstance().getTraceHandler() + .error(new IOException(trans(StringId.ERR_BAD_OUTPUT_TYPE, sourceString))); + + exitCode = 2; + break; + } + + exitCode = convert(urlString, convertType, target, plusInfo == null ? false : plusInfo, pg); - updates.ok(); // we consider it read + break; case LIST: - if (BasicReader.getReader() == null) { - Instance.getTraceHandler() - .error(new Exception( - "No reader type has been configured")); - exitCode = 10; - break; - } exitCode = list(sourceString); 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")); - exitCode = 10; + if (luid == null || luid.isEmpty()) { + syntax(false); + exitCode = 255; break; } - exitCode = read(luid, chapString, true); + + try { + Integer chap = null; + if (chapString != null) { + try { + chap = Integer.parseInt(chapString); + } catch (NumberFormatException e) { + Instance.getInstance().getTraceHandler().error(new IOException( + "Chapter number cannot be parsed: " + chapString, e)); + exitCode = 2; + break; + } + } + + BasicLibrary lib = Instance.getInstance().getLibrary(); + exitCode = read(lib.getStory(luid, null), chap); + } catch (IOException e) { + Instance.getInstance().getTraceHandler() + .error(new IOException("Failed to read book", e)); + exitCode = 2; + } + break; case READ_URL: - if (BasicReader.getReader() == null) { - Instance.getTraceHandler() - .error(new Exception( - "No reader type has been configured")); - exitCode = 10; + if (urlString == null || urlString.isEmpty()) { + syntax(false); + exitCode = 255; break; } - exitCode = read(urlString, chapString, false); + + try { + Integer chap = null; + if (chapString != null) { + try { + chap = Integer.parseInt(chapString); + } catch (NumberFormatException e) { + Instance.getInstance().getTraceHandler().error(new IOException( + "Chapter number cannot be parsed: " + chapString, e)); + exitCode = 2; + break; + } + } + + BasicSupport support = BasicSupport + .getSupport(BasicReader.getUrl(urlString)); + if (support == null) { + Instance.getInstance().getTraceHandler() + .error("URL not supported: " + urlString); + exitCode = 2; + break; + } + + exitCode = read(support.process(null), chap); + } catch (IOException e) { + Instance.getInstance().getTraceHandler() + .error(new IOException("Failed to read book", e)); + exitCode = 2; + } + break; 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")); - exitCode = 10; - break; - } - - try { - if (searchOn == null) { - BasicReader.getReader().search(true); - } else if (search != null) { - - BasicReader.getReader().search(searchOn, search, page, - item, true); - } else { - exitCode = 255; + if (searchOn == null) { + try { + search(); + } catch (IOException e) { + Instance.getInstance().getTraceHandler().error(e); + exitCode = 1; } - } catch (IOException e1) { - Instance.getTraceHandler().error(e1); - exitCode = 20; + } else if (search != null) { + try { + searchKeywords(searchOn, search, page, item); + } catch (IOException e) { + Instance.getInstance().getTraceHandler().error(e); + exitCode = 20; + } + } else { + exitCode = 255; } break; @@ -522,31 +589,23 @@ 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")); - exitCode = 10; - break; - } - try { - BasicReader.getReader().searchTag(searchOn, page, item, - true, tags.toArray(new Integer[] {})); - } catch (IOException e1) { - Instance.getTraceHandler().error(e1); + searchTags(searchOn, page, item, + tags.toArray(new Integer[] {})); + } catch (IOException e) { + Instance.getInstance().getTraceHandler().error(e); } break; @@ -554,54 +613,66 @@ public class Main { syntax(true); exitCode = 0; break; - case SET_READER: - exitCode = 255; - break; case VERSION: + if (updates != null) { + // we consider it read + Instance.getInstance().setVersionChecked(); + } + System.out .println(String.format("Fanfix version %s" + "%nhttps://github.com/nikiroo/fanfix/" + "%n\tWritten by Nikiroo", Version.getCurrentVersion())); - updates.ok(); // we consider it read break; case START: - if (BasicReader.getReader() == null) { - Instance.getTraceHandler() - .error(new Exception( - "No reader type has been configured")); - exitCode = 10; - break; - } try { - BasicReader.getReader().browse(null); + start(); } 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); - if (port == null) { - System.err.println("No port configured in the config file"); - exitCode = 15; - break; - } try { - ServerObject server = new RemoteLibraryServer(key, port); - server.setTraceHandler(Instance.getTraceHandler()); - server.run(); + startServer(); } catch (IOException e) { - Instance.getTraceHandler().error(e); + Instance.getInstance().getTraceHandler().error(e); } - return; + + break; case STOP_SERVER: // Can be given via "--remote XX XX XX" - if (key == null) - key = Instance.getConfig().getString(Config.SERVER_KEY); - if (port == null) - port = Instance.getConfig().getInteger(Config.SERVER_PORT); + if (key == null) { + key = Instance.getInstance().getConfig() + .getString(Config.SERVER_KEY); + + // If a subkey in RW mode exists, use it + for (String subkey : Instance.getInstance().getConfig() + .getList(Config.SERVER_ALLOWED_SUBKEYS, + new ArrayList())) { + if ((subkey + "|").contains("|rw|")) { + key = key + "|" + subkey; + break; + } + } + } + + if (port == null) { + port = Instance.getInstance().getConfig().getInteger(Config.SERVER_PORT); + } + + if (host == null) { + String mode = Instance.getInstance().getConfig() + .getString(Config.SERVER_MODE, "fanfix"); + if ("http".equals(mode)) { + host = "http://localhost"; + } else if ("https".equals(mode)) { + host = "https://localhost"; + } else if ("fanfix".equals(mode)) { + host = "fanfix://localhost"; + } + } if (port == null) { System.err.println("No port given nor configured in the config file"); @@ -609,13 +680,13 @@ public class Main { break; } try { - new RemoteLibrary(key, host, port).exit(); + stopServer(key, host, port); } 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; } @@ -627,38 +698,119 @@ 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) { syntax(false); } - System.exit(exitCode); + exit(exitCode); + } + + /** + * A normal invocation of the program (without parameters or at least + * without "action" parameters). + *

    + * You will probably want to override that one if you offer a user + * interface. + * + * @throws IOException + * in case of I/O error + */ + protected void start() throws IOException { + new CliReader().listBooks(null); + } + + /** + * Will check if updates are available, synchronously. + *

    + * For this, it will simply forward the call to + * {@link Main#checkUpdates(String)} with a value of "nikiroo/fanfix". + *

    + * You may want to override it so you call the forward method with the right + * parameters (or also if you want it to be asynchronous). + * + * @return the newer version information or NULL if nothing new + */ + protected VersionCheck checkUpdates() { + return checkUpdates("nikiroo/fanfix"); + } + + /** + * Will check if updates are available on a specific GitHub project. + *

    + * Will be called by {@link Main#checkUpdates()}, but if you override that + * one you mall call it with another project. + * + * @param githubProject + * the GitHub project, for instance "nikiroo/fanfix" + * + * @return the newer version information or NULL if nothing new + */ + protected VersionCheck checkUpdates(String githubProject) { + try { + VersionCheck updates = VersionCheck.check(githubProject, + Instance.getInstance().getTrans().getLocale()); + if (updates.isNewVersionAvailable()) { + notifyUpdates(updates); + return updates; + } + } catch (IOException e) { + // Maybe no internet. Do not report any update. + } + + return null; } + /** + * Notify the user about available updates. + *

    + * Will only be called when a version is available. + *

    + * Note that you can call {@link Instance#setVersionChecked()} on it if the + * user has read the information (by default, it is marked read only on + * certain other actions). + * + * @param updates + * the new version information + */ + protected void notifyUpdates(VersionCheck updates) { + // Sent to syserr so not to cause problem if one tries to capture a + // story content in text mode + System.err.println( + "A new version of the program is available at https://github.com/nikiroo/fanfix/releases"); + System.err.println(""); + for (Version v : updates.getNewer()) { + System.err.println("\tVersion " + v); + System.err.println("\t-------------"); + System.err.println(""); + for (String it : updates.getChanges().get(v)) { + System.err.println("\t- " + it); + } + System.err.println(""); + } + } + /** * Import the given resource into the {@link LocalLibrary}. * - * @param urlString + * @param url * the resource to import * @param pg * the optional progress reporter * * @return the exit return code (0 = success) */ - public static int imprt(String urlString, Progress pg) { + protected static int imprt(URL url, 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(url, pg); + System.out.println(meta.getLuid() + ": \"" + meta.getTitle() + "\" imported."); } catch (IOException e) { - Instance.getTraceHandler().error(e); + Instance.getInstance().getTraceHandler().error(e); return 1; } @@ -671,7 +823,7 @@ public class Main { * * @param luid * the story LUID - * @param typeString + * @param type * the {@link OutputType} to use * @param target * the target @@ -680,25 +832,18 @@ public class Main { * * @return the exit return code (0 = success) */ - public static int export(String luid, String typeString, String target, + protected static int export(String luid, OutputType type, String target, Progress pg) { - OutputType type = OutputType.valueOfNullOkUC(typeString, null); - if (type == null) { - Instance.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; } return 0; } - + /** * List the stories of the given source from the {@link LocalLibrary} * (unless NULL is passed, in which case all stories will be listed). @@ -709,12 +854,11 @@ public class Main { * * @return the exit return code (0 = success) */ - private static int list(String source) { - BasicReader.setDefaultReaderType(ReaderType.CLI); + protected int list(String source) { try { - BasicReader.getReader().browse(source); + new CliReader().listBooks(source); } catch (IOException e) { - Instance.getTraceHandler().error(e); + Instance.getInstance().getTraceHandler().error(e); return 66; } @@ -725,42 +869,30 @@ public class Main { * Start the current reader for this {@link Story}. * * @param story - * the LUID of the {@link Story} in the {@link LocalLibrary} - * or the {@link Story} {@link URL} - * @param chapString + * the story to read + * @param chap * which {@link Chapter} to read (starting at 1), or NULL to get * the {@link Story} description - * @param library - * TRUE if the source is the {@link Story} LUID, FALSE if it is a - * {@link URL} * * @return the exit return code (0 = success) */ - private static int read(String story, String chapString, boolean library) { - try { - Reader reader = BasicReader.getReader(); - if (library) { - reader.setMeta(story); - } else { - reader.setMeta(BasicReader.getUrl(story), null); - } - - if (chapString != null) { - try { - reader.setChapter(Integer.parseInt(chapString)); - reader.read(true); - } catch (NumberFormatException e) { - Instance.getTraceHandler().error( - new IOException("Chapter number cannot be parsed: " - + chapString, e)); - return 2; - } - } else { - reader.read(true); + protected int read(Story story, Integer chap) { + if (story != null) { + try { + if (chap == null) { + new CliReader().listChapters(story); + } else { + new CliReader().printChapter(story, chap); + } + } catch (IOException e) { + Instance.getInstance().getTraceHandler() + .error(new IOException("Failed to read book", e)); + return 2; } - } catch (IOException e) { - Instance.getTraceHandler().error(e); - return 1; + } else { + Instance.getInstance().getTraceHandler() + .error("Cannot find book: " + story); + return 2; } return 0; @@ -771,7 +903,7 @@ public class Main { * * @param urlString * the source {@link Story} to convert - * @param typeString + * @param type * the {@link OutputType} to convert to * @param target * the target file @@ -783,11 +915,11 @@ public class Main { * * @return the exit return code (0 = success) */ - public static int convert(String urlString, String typeString, + protected int convert(String urlString, OutputType type, 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); @@ -796,75 +928,51 @@ public class Main { sourceName = sourceName.substring("file://".length()); } - OutputType type = OutputType.valueOfAllOkUC(typeString, null); - if (type == null) { - Instance.getTraceHandler().error( - new IOException(trans(StringId.ERR_BAD_OUTPUT_TYPE, - typeString))); - - exitCode = 2; - } else { - try { - BasicSupport support = BasicSupport.getSupport(source); - - if (support != null) { - Instance.getTraceHandler().trace( - "Support found: " + support.getClass()); - Progress pgIn = new Progress(); - Progress pgOut = new Progress(); - if (pg != null) { - pg.setMax(2); - pg.addProgress(pgIn, 1); - pg.addProgress(pgOut, 1); - } - - Story story = support.process(pgIn); - try { - target = new File(target).getAbsolutePath(); - BasicOutput.getOutput(type, infoCover, infoCover) - .process(story, target, pgOut); - } catch (IOException e) { - Instance.getTraceHandler().error( - new IOException(trans(StringId.ERR_SAVING, - target), e)); - exitCode = 5; - } - } else { - Instance.getTraceHandler().error( - new IOException(trans( - StringId.ERR_NOT_SUPPORTED, source))); + try { + BasicSupport support = BasicSupport.getSupport(source); + + if (support != null) { + Instance.getInstance().getTraceHandler() + .trace("Support found: " + support.getClass()); + Progress pgIn = new Progress(); + Progress pgOut = new Progress(); + if (pg != null) { + pg.setMax(2); + pg.addProgress(pgIn, 1); + pg.addProgress(pgOut, 1); + } - exitCode = 4; + Story story = support.process(pgIn); + try { + target = new File(target).getAbsolutePath(); + BasicOutput.getOutput(type, infoCover, infoCover) + .process(story, target, pgOut); + } catch (IOException e) { + Instance.getInstance().getTraceHandler() + .error(new IOException( + trans(StringId.ERR_SAVING, target), e)); + exitCode = 5; } - } catch (IOException e) { - Instance.getTraceHandler().error( - new IOException(trans(StringId.ERR_LOADING, - sourceName), e)); - exitCode = 3; + } else { + Instance.getInstance().getTraceHandler() + .error(new IOException( + trans(StringId.ERR_NOT_SUPPORTED, source))); + + exitCode = 4; } + } catch (IOException 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; } return exitCode; } - /** - * Simple shortcut method to call {link Instance#getTrans()#getString()}. - * - * @param id - * the ID to translate - * - * @return the translated result - */ - private static String trans(StringId id, Object... params) { - return Instance.getTrans().getString(id, params); - } - /** * Display the correct syntax of the program to the user to stdout, or an * error message if the syntax used was wrong on stderr. @@ -872,7 +980,7 @@ public class Main { * @param showHelp * TRUE to show the syntax help, FALSE to show "syntax error" */ - private static void syntax(boolean showHelp) { + protected void syntax(boolean showHelp) { if (showHelp) { StringBuilder builder = new StringBuilder(); for (SupportType type : SupportType.values()) { @@ -899,23 +1007,135 @@ public class Main { } /** - * Set the default reader type for this session only (it can be changed in - * the configuration file, too, but this value will override it). + * Starts a search operation (i.e., list the available web sites we can + * search on). * - * @param readerTypeString - * the type + * @throws IOException + * in case of I/O errors */ - private static int setReaderType(String readerTypeString) { - try { - ReaderType readerType = ReaderType.valueOf(readerTypeString - .toUpperCase()); - BasicReader.setDefaultReaderType(readerType); - return 0; - } catch (IllegalArgumentException e) { - Instance.getTraceHandler().error( - new IOException("Unknown reader type: " + readerTypeString, - e)); - return 1; + protected void search() throws IOException { + new CliReader().listSearchables(); + } + + /** + * Search for books by keywords on the given supported web site. + * + * @param searchOn + * the web site to search on + * @param search + * the keyword to look for + * @param page + * the page of results to get, or 0 to inquire about the number + * of pages + * @param item + * the index of the book we are interested by, or 0 to query + * about how many books are in that page of results + * + * @throws IOException + * in case of I/O error + */ + protected void searchKeywords(SupportType searchOn, String search, + int page, Integer item) throws IOException { + new CliReader().searchBooksByKeyword(searchOn, search, page, item); + } + + /** + * Search for books by tags on the given supported web site. + * + * @param searchOn + * the web site to search on + * @param page + * the page of results to get, or 0 to inquire about the number + * of pages + * @param item + * the index of the book we are interested by, or 0 to query + * about how many books are in that page of results + * @param tags + * the tags to look for + * + * @throws IOException + * in case of I/O error + */ + protected void searchTags(SupportType searchOn, Integer page, Integer item, + Integer[] tags) throws IOException { + new CliReader().searchBooksByTag(searchOn, page, item, tags); + } + + /** + * Start a Fanfix server. + * + * @throws IOException + * in case of I/O errors + * @throws SSLException + * when the key was not accepted + */ + private void startServer() throws IOException { + String mode = Instance.getInstance().getConfig() + .getString(Config.SERVER_MODE, "fanfix"); + if (mode.equals("fanfix")) { + RemoteLibraryServer server = new RemoteLibraryServer(); + server.setTraceHandler(Instance.getInstance().getTraceHandler()); + server.run(); + } else if (mode.equals("http")) { + WebLibraryServer server = new WebLibraryServer(false); + server.setTraceHandler(Instance.getInstance().getTraceHandler()); + server.run(); + } else if (mode.equals("https")) { + WebLibraryServer server = new WebLibraryServer(true); + server.setTraceHandler(Instance.getInstance().getTraceHandler()); + server.run(); + } else { + throw new IOException("Unknown server mode: " + mode); } } + + /** + * Stop a running Fanfix server. + * + * @param key + * the key to contact the Fanfix server + * @param host + * the host on which it runs + * @param port + * the port on which it runs + * + * @throws IOException + * in case of I/O errors + * @throws SSLException + * when the key was not accepted + */ + private void stopServer(String key, String host, int port) + throws IOException, SSLException { + if (host.startsWith("http://") || host.startsWith("https://")) { + new WebLibrary(key, host, port).stop(); + } else { + new RemoteLibrary(key, host, port).stop(); + } + } + + /** + * We are done and ready to exit. + *

    + * By default, it will call {@link System#exit(int)} if the status is not 0. + * + * @param status + * the exit status + */ + protected void exit(int status) { + if (status != 0) { + System.exit(status); + } + } + + /** + * Simple shortcut method to call {link Instance#getTrans()#getString()}. + * + * @param id + * the ID to translate + * + * @return the translated result + */ + static private String trans(StringId id, Object... params) { + return Instance.getInstance().getTrans().getString(id, params); + } }