From b9ce9cad4a94e7c88770d5f7ac6cf4f200e336de Mon Sep 17 00:00:00 2001 From: Niki Roo Date: Thu, 30 Nov 2017 23:08:14 +0100 Subject: [PATCH] Remote, JPG/PNG: - Remote mode now supports progress (not everywhere yet) - Remote mode can now send stories correctly - DataLoader now handle all JPG errors with a PNG retry - Update nikiroo-utils (Cache now works with parent-less files) --- changelog.md | 4 +- ...es.jar => nikiroo-utils-3.1.5-sources.jar} | Bin 274707 -> 274830 bytes src/be/nikiroo/fanfix/DataLoader.java | 29 +- .../nikiroo/fanfix/library/RemoteLibrary.java | 285 +++++++++++------- .../fanfix/library/RemoteLibraryServer.java | 211 ++++++++----- 5 files changed, 339 insertions(+), 190 deletions(-) rename libs/{nikiroo-utils-3.1.4-sources.jar => nikiroo-utils-3.1.5-sources.jar} (94%) diff --git a/changelog.md b/changelog.md index 41028127..9c30702c 100644 --- a/changelog.md +++ b/changelog.md @@ -3,11 +3,11 @@ # Version WIP - Bug fixes -- Remote server/client improvements +- Remote server/client improvements (progress report, can send large files) - Better support for some CBZ files (if SUMMARY or URL files are present in it) - Fix cover images not deleted on story delete - Fix some images not supported because not jpeg-able (now try again in png) -- Fix some covers not found (normal and remote hopefully) +- Fix some covers not found over the wire (nikiroo-utils) ## Version 1.6.2 diff --git a/libs/nikiroo-utils-3.1.4-sources.jar b/libs/nikiroo-utils-3.1.5-sources.jar similarity index 94% rename from libs/nikiroo-utils-3.1.4-sources.jar rename to libs/nikiroo-utils-3.1.5-sources.jar index 790a9821821253bea79fd1b1797542d4be9a0a14..38d88a67c60d68239a1824f121b6d04679560471 100644 GIT binary patch delta 11992 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 hgygbGNjcKvX~=G{`e62p#qY>5Ybg`akNt4x0b~ delta 11837 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 iAwr4Yg1JGYU@+8}9gGVd0fW(@9 getMetas(Progress pg) { - // TODO: progress - final List metas = new ArrayList(); - MetaData[] fromNetwork = this.getRemoteObject( // - new Object[] { key, "GET_METADATA", "*" }); + public BufferedImage getCover(final String luid) { + final BufferedImage[] result = new BufferedImage[1]; - if (fromNetwork != null) { - for (MetaData meta : fromNetwork) { - metas.add(meta); - } - } + try { + new ConnectActionClientObject(host, port, true) { + @Override + public void action(Version serverVersion) throws Exception { + Object rep = send(new Object[] { key, "GET_COVER", luid }); + result[0] = (BufferedImage) rep; + } - return metas; - } + @Override + protected void onError(Exception e) { + Instance.getTraceHandler().error(e); + } + }.connect(); + } catch (Exception e) { + Instance.getTraceHandler().error(e); + } - @Override - public BufferedImage getCover(final String luid) { - return this.getRemoteObject( // - new Object[] { key, "GET_COVER", luid }); + return result[0]; } @Override public BufferedImage getSourceCover(final String source) { - return this.getRemoteObject( // - new Object[] { key, "GET_SOURCE_COVER", source }); + final BufferedImage[] result = new BufferedImage[1]; + + try { + new ConnectActionClientObject(host, port, true) { + @Override + public void action(Version serverVersion) throws Exception { + Object rep = send(new Object[] { key, "GET_SOURCE_COVER", + source }); + result[0] = (BufferedImage) rep; + } + + @Override + protected void onError(Exception e) { + Instance.getTraceHandler().error(e); + } + }.connect(); + } catch (Exception e) { + Instance.getTraceHandler().error(e); + } + + return result[0]; } @Override public synchronized Story getStory(final String luid, Progress pg) { - return this.getRemoteStory( // - new Object[] { key, "GET_STORY", luid }); - } + final Progress pgF = pg; + final Story[] result = new Story[1]; - @Override - protected void clearCache() { + try { + new ConnectActionClientObject(host, port, true) { + @Override + public void action(Version serverVersion) throws Exception { + Progress pg = pgF; + if (pg == null) { + pg = new Progress(); + } + + Object rep = send(new Object[] { key, "GET_STORY", luid }); + + MetaData meta = null; + if (rep instanceof MetaData) { + meta = (MetaData) rep; + if (meta.getWords() <= Integer.MAX_VALUE) { + pg.setMinMax(0, (int) meta.getWords()); + } + } + + List list = new ArrayList(); + for (Object obj = send(null); obj != null; obj = send(null)) { + list.add(obj); + pg.add(1); + } + + result[0] = RemoteLibraryServer.rebuildStory(list); + pg.done(); + } + + @Override + protected void onError(Exception e) { + Instance.getTraceHandler().error(e); + } + }.connect(); + } catch (Exception e) { + Instance.getTraceHandler().error(e); + } + + return result[0]; } @Override - public synchronized Story save(Story story, String luid, Progress pg) - throws IOException { - getRemoteObject(new Object[] { key, "SAVE_STORY", story, luid }); + public synchronized Story save(final Story story, final String luid, + Progress pg) throws IOException { + final Progress pgF = pg; + + new ConnectActionClientObject(host, port, true) { + @Override + public void action(Version serverVersion) throws Exception { + Progress pg = pgF; + if (pg == null) { + pg = new Progress(); + } + + if (story.getMeta().getWords() <= Integer.MAX_VALUE) { + pg.setMinMax(0, (int) story.getMeta().getWords()); + } + + send(new Object[] { key, "SAVE_STORY", luid }); + + List list = RemoteLibraryServer.breakStory(story); + for (Object obj : list) { + send(obj); + pg.add(1); + } + + send(null); + pg.done(); + } + + @Override + protected void onError(Exception e) { + Instance.getTraceHandler().error(e); + } + }.connect(); // because the meta changed: clearCache(); @@ -98,14 +185,37 @@ public class RemoteLibrary extends BasicLibrary { } @Override - public synchronized void delete(String luid) throws IOException { - getRemoteObject(new Object[] { key, "DELETE_STORY", luid }); + public synchronized void delete(final String luid) throws IOException { + new ConnectActionClientObject(host, port, true) { + @Override + public void action(Version serverVersion) throws Exception { + send(new Object[] { key, "DELETE_STORY", luid }); + } + + @Override + protected void onError(Exception e) { + Instance.getTraceHandler().error(e); + } + }.connect(); } @Override - public void setSourceCover(String source, String luid) { - this. getRemoteObject( // - new Object[] { key, "SET_SOURCE_COVER", source, luid }); + public void setSourceCover(final String source, final String luid) { + try { + new ConnectActionClientObject(host, port, true) { + @Override + public void action(Version serverVersion) throws Exception { + send(new Object[] { key, "SET_SOURCE_COVER", source, luid }); + } + + @Override + protected void onError(Exception e) { + Instance.getTraceHandler().error(e); + } + }.connect(); + } catch (IOException e) { + Instance.getTraceHandler().error(e); + } } @Override @@ -114,86 +224,33 @@ public class RemoteLibrary extends BasicLibrary { "Operation not supportorted on remote Libraries"); } - // The following methods are only used by Save and Delete in BasicLibrary: - - @Override - protected int getNextId() { - throw new java.lang.InternalError("Should not have been called"); - } - @Override - protected void doDelete(String luid) throws IOException { - throw new java.lang.InternalError("Should not have been called"); - } - - @Override - protected Story doSave(Story story, Progress pg) throws IOException { - throw new java.lang.InternalError("Should not have been called"); - } - - /** - * Return an object from the server. - * - * @param - * the expected type of object - * @param command - * the command to send (can contain at most ONE {@link Story}) - * - * @return the object or NULL - */ - private T getRemoteObject(final Object[] command) { - return getRemoteObjectOrStory(command, false); - } - - /** - * Return an object from the server. - * - * @param command - * the command to send (can contain at most ONE {@link Story}) - * - * @return the object or NULL - */ - private Story getRemoteStory(final Object[] command) { - return getRemoteObjectOrStory(command, true); - } + protected List getMetas(Progress pg) { + final Progress pgF = pg; + final List metas = new ArrayList(); - /** - * Return an object from the server. - * - * @param - * the expected type of object - * @param command - * the command to send (can contain at most ONE {@link Story}) - * - * @return the object or NULL - */ - @SuppressWarnings("unchecked") - private T getRemoteObjectOrStory(final Object[] command, - final boolean getStory) { - final Object[] result = new Object[1]; try { new ConnectActionClientObject(host, port, true) { @Override public void action(Version serverVersion) throws Exception { - Story story = null; - for (int i = 0; i < command.length; i++) { - if (command[i] instanceof Story) { - story = (Story) command[i]; - command[i] = null; - } + Progress pg = pgF; + if (pg == null) { + pg = new Progress(); } - Object rep = send(command); + Object rep = send(new Object[] { key, "GET_METADATA", "*" }); - if (story != null) { - RemoteLibraryServer.sendStory(story, this); - } + while (true) { + if (!RemoteLibraryServer.updateProgress(pg, rep)) { + break; + } - if (getStory) { - rep = RemoteLibraryServer.recStory(this); + rep = send(null); } - result[0] = rep; + for (MetaData meta : (MetaData[]) rep) { + metas.add(meta); + } } @Override @@ -201,15 +258,31 @@ public class RemoteLibrary extends BasicLibrary { Instance.getTraceHandler().error(e); } }.connect(); - } catch (IOException e) { - Instance.getTraceHandler().error(e); - } - - try { - return (T) result[0]; } catch (Exception e) { Instance.getTraceHandler().error(e); - return null; } + + return metas; + } + + @Override + protected void clearCache() { + } + + // The following methods are only used by Save and Delete in BasicLibrary: + + @Override + protected int getNextId() { + throw new java.lang.InternalError("Should not have been called"); + } + + @Override + protected void doDelete(String luid) throws IOException { + throw new java.lang.InternalError("Should not have been called"); + } + + @Override + protected Story doSave(Story story, Progress pg) throws IOException { + throw new java.lang.InternalError("Should not have been called"); } } diff --git a/src/be/nikiroo/fanfix/library/RemoteLibraryServer.java b/src/be/nikiroo/fanfix/library/RemoteLibraryServer.java index 2799a65a..40386ec2 100644 --- a/src/be/nikiroo/fanfix/library/RemoteLibraryServer.java +++ b/src/be/nikiroo/fanfix/library/RemoteLibraryServer.java @@ -10,8 +10,9 @@ import be.nikiroo.fanfix.data.Chapter; import be.nikiroo.fanfix.data.MetaData; import be.nikiroo.fanfix.data.Paragraph; import be.nikiroo.fanfix.data.Story; +import be.nikiroo.utils.Progress; +import be.nikiroo.utils.Progress.ProgressListener; import be.nikiroo.utils.Version; -import be.nikiroo.utils.serial.server.ConnectActionClientObject; import be.nikiroo.utils.serial.server.ConnectActionServerObject; import be.nikiroo.utils.serial.server.ServerObject; @@ -58,6 +59,8 @@ public class RemoteLibraryServer extends ServerObject { public RemoteLibraryServer(String key, int port) throws IOException { super("Fanfix remote library", port, true); this.key = key; + + setTraceHandler(Instance.getTraceHandler()); } @Override @@ -79,31 +82,50 @@ public class RemoteLibraryServer extends ServerObject { } } - System.out.print("[" + command + "] "); + String trace = "[" + command + "] "; for (Object arg : args) { - System.out.print(arg + " "); + trace += arg + " "; } - System.out.println(""); + getTraceHandler().trace(trace); if (!key.equals(this.key)) { - System.out.println("Key rejected."); - throw new SecurityException("Invalid key"); + getTraceHandler().trace("Key rejected."); + return null; } - // TODO: progress (+send name + %age info back to client) - if ("GET_METADATA".equals(command)) { if (args[0].equals("*")) { - List metas = Instance.getLibrary().getMetas(null); + List metas = Instance.getLibrary().getMetas( + createPgForwarder(action)); return metas.toArray(new MetaData[] {}); } throw new InvalidParameterException( "only * is valid here, but you passed: " + args[0]); } else if ("GET_STORY".equals(command)) { + MetaData meta = Instance.getLibrary().getInfo("" + args[0]); + meta = meta.clone(); + meta.setCover(null); + + action.send(meta); + action.rec(); + Story story = Instance.getLibrary().getStory("" + args[0], null); - sendStory(story, action); + for (Object obj : breakStory(story)) { + action.send(obj); + action.rec(); + } } else if ("SAVE_STORY".equals(command)) { - Story story = recStory(action); + List list = new ArrayList(); + + action.send(null); + Object obj = action.rec(); + while (obj != null) { + list.add(obj); + action.send(null); + obj = action.rec(); + } + + Story story = rebuildStory(list); Instance.getLibrary().save(story, "" + args[1], null); } else if ("DELETE_STORY".equals(command)) { Instance.getLibrary().delete("" + args[0]); @@ -120,83 +142,132 @@ public class RemoteLibraryServer extends ServerObject { return null; } - public static void sendStory(Story story, Object sender) - throws NoSuchFieldException, NoSuchMethodException, - ClassNotFoundException, IOException { + @Override + protected void onError(Exception e) { + getTraceHandler().error(e); + } - if (!story.getMeta().isImageDocument()) { - sendNextObject(sender, story); - return; - } + /** + * Break a story in multiple {@link Object}s for easier serialisation. + * + * @param story + * the {@link Story} to break + * + * @return the list of {@link Object}s + */ + static List breakStory(Story story) { + List list = new ArrayList(); story = story.clone(); + list.add(story); - List chaps = story.getChapters(); - story.setChapters(new ArrayList()); - sendNextObject(sender, story); - - for (Chapter chap : chaps) { - List paras = chap.getParagraphs(); - chap.setParagraphs(new ArrayList()); - sendNextObject(sender, chap); - - for (Paragraph para : paras) { - sendNextObject(sender, para); + if (story.getMeta().isImageDocument()) { + for (Chapter chap : story) { + list.add(chap); + list.addAll(chap.getParagraphs()); + chap.setParagraphs(new ArrayList()); } + story.setChapters(new ArrayList()); } - } - public static Story recStory(Object source) throws NoSuchFieldException, - NoSuchMethodException, ClassNotFoundException, IOException { + return list; + } + /** + * Rebuild a story from a list of broke up {@link Story} parts. + * + * @param list + * the list of {@link Story} parts + * + * @return the reconstructed {@link Story} + */ + static Story rebuildStory(List list) { Story story = null; + Chapter chap = null; - Object obj = getNextObject(source); - if (obj instanceof Story) { - story = (Story) obj; - - Chapter current = null; - for (obj = getNextObject(source); obj != null; obj = getNextObject(source)) { - if (obj instanceof Chapter) { - current = (Chapter) obj; - story.getChapters().add(current); - } else if (obj instanceof Paragraph) { - current.getParagraphs().add((Paragraph) obj); - } + for (Object obj : list) { + if (obj instanceof Story) { + story = (Story) obj; + } else if (obj instanceof Chapter) { + chap = (Chapter) obj; + story.getChapters().add(chap); + } else if (obj instanceof Paragraph) { + chap.getParagraphs().add((Paragraph) obj); } } return story; } - private static Object getNextObject(Object clientOrServer) - throws NoSuchFieldException, NoSuchMethodException, - ClassNotFoundException, IOException { - if (clientOrServer instanceof ConnectActionClientObject) { - ConnectActionClientObject client = (ConnectActionClientObject) clientOrServer; - return client.send(null); - } else if (clientOrServer instanceof ConnectActionServerObject) { - ConnectActionServerObject server = (ConnectActionServerObject) clientOrServer; - Object obj = server.rec(); - server.send(null); - return obj; - } else { - throw new ClassNotFoundException(); + /** + * Update the {@link Progress} with the adequate {@link Object} received + * from the network via {@link RemoteLibraryServer}. + * + * @param pg + * the {@link Progress} to update + * @param rep + * the object received from the network + * + * @return TRUE if it was a progress event, FALSE if not + */ + static boolean updateProgress(Progress pg, Object rep) { + if (rep instanceof Integer[]) { + Integer[] a = (Integer[]) rep; + if (a.length == 3) { + int min = a[0]; + int max = a[1]; + int progress = a[2]; + + if (min >= 0 && min <= max) { + pg.setMinMax(min, max); + pg.setProgress(progress); + + return true; + } + } } + + return false; } - private static void sendNextObject(Object clientOrServer, Object obj) - throws NoSuchFieldException, NoSuchMethodException, - ClassNotFoundException, IOException { - if (clientOrServer instanceof ConnectActionClientObject) { - ConnectActionClientObject client = (ConnectActionClientObject) clientOrServer; - client.send(obj); - } else if (clientOrServer instanceof ConnectActionServerObject) { - ConnectActionServerObject server = (ConnectActionServerObject) clientOrServer; - server.send(obj); - server.rec(); - } else { - throw new ClassNotFoundException(); - } + /** + * Create a {@link Progress} that will forward its progress over the + * network. + * + * @param action + * the {@link ConnectActionServerObject} to use to forward it + * + * @return the {@link Progress} + */ + private static Progress createPgForwarder( + final ConnectActionServerObject action) { + final Progress pg = new Progress(); + final Integer[] p = new Integer[] { -1, -1, -1 }; + pg.addProgressListener(new ProgressListener() { + @Override + public void progress(Progress progress, String name) { + int min = pg.getMin(); + int max = pg.getMax(); + int relativeProgress = min + + (int) Math.round(pg.getRelativeProgress() + * (max - min)); + + // Do not re-send the same value twice over the wire + if (p[0] != min || p[1] != max || p[2] != relativeProgress) { + p[0] = min; + p[1] = max; + p[2] = relativeProgress; + + try { + action.send(new Integer[] { min, max, relativeProgress }); + action.rec(); + } catch (Exception e) { + Instance.getTraceHandler().error(e); + } + } + } + }); + + return pg; } } -- 2.27.0