1 package be
.nikiroo
.fanfix
.library
;
4 import java
.io
.IOException
;
6 import java
.net
.UnknownHostException
;
7 import java
.util
.ArrayList
;
10 import be
.nikiroo
.fanfix
.Instance
;
11 import be
.nikiroo
.fanfix
.data
.MetaData
;
12 import be
.nikiroo
.fanfix
.data
.Story
;
13 import be
.nikiroo
.utils
.Image
;
14 import be
.nikiroo
.utils
.Progress
;
15 import be
.nikiroo
.utils
.Version
;
16 import be
.nikiroo
.utils
.serial
.server
.ConnectActionClientObject
;
19 * This {@link BasicLibrary} will access a remote server to list the available
20 * stories, and download the ones you try to load to the local directory
21 * specified in the configuration.
25 public class RemoteLibrary
extends BasicLibrary
{
28 private final String key
;
31 * Create a {@link RemoteLibrary} linked to the given server.
34 * the key that will allow us to exchange information with the
37 * the host to contact or NULL for localhost
39 * the port to contact it on
41 public RemoteLibrary(String key
, String host
, int port
) {
48 public String
getLibraryName() {
49 return host
+ ":" + port
;
53 public Status
getStatus() {
54 final Status
[] result
= new Status
[1];
56 result
[0] = Status
.INVALID
;
59 Instance
.getTraceHandler().trace("Getting remote lib status...");
60 new ConnectActionClientObject(host
, port
, key
) {
62 public void action(Version serverVersion
) throws Exception
{
64 Object rep
= send(new Object
[] { "PING" });
66 if ("PONG".equals(rep
)) {
67 result
[0] = Status
.READY
;
69 result
[0] = Status
.UNAUTORIZED
;
71 } catch (IllegalArgumentException e
) {
72 result
[0] = Status
.UNAUTORIZED
;
77 protected void onError(Exception e
) {
78 result
[0] = Status
.UNAVAILABLE
;
81 } catch (UnknownHostException e
) {
82 result
[0] = Status
.INVALID
;
83 } catch (IllegalArgumentException e
) {
84 result
[0] = Status
.INVALID
;
85 } catch (Exception e
) {
86 result
[0] = Status
.UNAVAILABLE
;
89 Instance
.getTraceHandler().trace("Remote lib status: " + result
[0]);
94 public Image
getCover(final String luid
) {
95 final Image
[] result
= new Image
[1];
98 new ConnectActionClientObject(host
, port
, key
) {
100 public void action(Version serverVersion
) throws Exception
{
101 Object rep
= send(new Object
[] { "GET_COVER", luid
});
102 result
[0] = (Image
) rep
;
106 protected void onError(Exception e
) {
107 Instance
.getTraceHandler().error(e
);
110 } catch (Exception e
) {
111 Instance
.getTraceHandler().error(e
);
118 public Image
getCustomSourceCover(final String source
) {
119 return getCustomCover(source
, "SOURCE");
123 public Image
getCustomAuthorCover(final String author
) {
124 return getCustomCover(author
, "AUTHOR");
127 // type: "SOURCE" or "AUTHOR"
128 private Image
getCustomCover(final String source
, final String type
) {
129 final Image
[] result
= new Image
[1];
132 new ConnectActionClientObject(host
, port
, key
) {
134 public void action(Version serverVersion
) throws Exception
{
135 Object rep
= send(new Object
[] { "GET_CUSTOM_COVER", type
,
137 result
[0] = (Image
) rep
;
141 protected void onError(Exception e
) {
142 Instance
.getTraceHandler().error(e
);
145 } catch (Exception e
) {
146 Instance
.getTraceHandler().error(e
);
153 public synchronized Story
getStory(final String luid
, Progress pg
) {
154 final Progress pgF
= pg
;
155 final Story
[] result
= new Story
[1];
158 new ConnectActionClientObject(host
, port
, key
) {
160 public void action(Version serverVersion
) throws Exception
{
166 Object rep
= send(new Object
[] { "GET_STORY", luid
});
168 MetaData meta
= null;
169 if (rep
instanceof MetaData
) {
170 meta
= (MetaData
) rep
;
171 if (meta
.getWords() <= Integer
.MAX_VALUE
) {
172 pg
.setMinMax(0, (int) meta
.getWords());
176 List
<Object
> list
= new ArrayList
<Object
>();
177 for (Object obj
= send(null); obj
!= null; obj
= send(null)) {
182 result
[0] = RemoteLibraryServer
.rebuildStory(list
);
187 protected void onError(Exception e
) {
188 Instance
.getTraceHandler().error(e
);
191 } catch (Exception e
) {
192 Instance
.getTraceHandler().error(e
);
199 public synchronized Story
save(final Story story
, final String luid
,
200 Progress pg
) throws IOException
{
201 final String
[] luidSaved
= new String
[1];
202 Progress pgSave
= new Progress();
203 Progress pgRefresh
= new Progress();
209 pg
.addProgress(pgSave
, 9);
210 pg
.addProgress(pgRefresh
, 1);
212 final Progress pgF
= pgSave
;
214 new ConnectActionClientObject(host
, port
, key
) {
216 public void action(Version serverVersion
) throws Exception
{
218 if (story
.getMeta().getWords() <= Integer
.MAX_VALUE
) {
219 pg
.setMinMax(0, (int) story
.getMeta().getWords());
222 send(new Object
[] { "SAVE_STORY", luid
});
224 List
<Object
> list
= RemoteLibraryServer
.breakStory(story
);
225 for (Object obj
: list
) {
230 luidSaved
[0] = (String
) send(null);
236 protected void onError(Exception e
) {
237 Instance
.getTraceHandler().error(e
);
241 // because the meta changed:
242 MetaData meta
= getInfo(luidSaved
[0]);
243 if (story
.getMeta().getClass() != null) {
244 // If already available locally:
245 meta
.setCover(story
.getMeta().getCover());
248 meta
.setCover(getCover(meta
.getLuid()));
258 public synchronized void delete(final String luid
) throws IOException
{
259 new ConnectActionClientObject(host
, port
, key
) {
261 public void action(Version serverVersion
) throws Exception
{
262 send(new Object
[] { "DELETE_STORY", luid
});
266 protected void onError(Exception e
) {
267 Instance
.getTraceHandler().error(e
);
273 public void setSourceCover(final String source
, final String luid
) {
274 setCover(source
, luid
, "SOURCE");
278 public void setAuthorCover(final String author
, final String luid
) {
279 setCover(author
, luid
, "AUTHOR");
282 // type = "SOURCE" | "AUTHOR"
283 private void setCover(final String value
, final String luid
,
286 new ConnectActionClientObject(host
, port
, key
) {
288 public void action(Version serverVersion
) throws Exception
{
289 send(new Object
[] { "SET_COVER", type
, value
, luid
});
293 protected void onError(Exception e
) {
294 Instance
.getTraceHandler().error(e
);
297 } catch (IOException e
) {
298 Instance
.getTraceHandler().error(e
);
303 // Could work (more slowly) without it
304 public Story
imprt(final URL url
, Progress pg
) throws IOException
{
305 // Import the file locally if it is actually a file
306 if (url
== null || url
.getProtocol().equalsIgnoreCase("file")) {
307 return super.imprt(url
, pg
);
310 // Import it remotely if it is an URL
317 Progress pgImprt
= new Progress();
318 Progress pgGet
= new Progress();
319 pg
.addProgress(pgImprt
, 1);
320 pg
.addProgress(pgGet
, 1);
322 final Progress pgF
= pgImprt
;
323 final String
[] luid
= new String
[1];
326 new ConnectActionClientObject(host
, port
, key
) {
328 public void action(Version serverVersion
) throws Exception
{
331 Object rep
= send(new Object
[] { "IMPORT", url
.toString() });
334 if (!RemoteLibraryServer
.updateProgress(pg
, rep
)) {
342 luid
[0] = (String
) rep
;
346 protected void onError(Exception e
) {
347 Instance
.getTraceHandler().error(e
);
350 } catch (IOException e
) {
351 Instance
.getTraceHandler().error(e
);
354 if (luid
[0] == null) {
355 throw new IOException("Remote failure");
358 Story story
= getStory(luid
[0], pgGet
);
366 // Could work (more slowly) without it
367 protected synchronized void changeSTA(final String luid
,
368 final String newSource
, final String newTitle
,
369 final String newAuthor
, Progress pg
) throws IOException
{
370 final Progress pgF
= pg
== null ?
new Progress() : pg
;
373 new ConnectActionClientObject(host
, port
, key
) {
375 public void action(Version serverVersion
) throws Exception
{
378 Object rep
= send(new Object
[] { "CHANGE_STA", luid
,
379 newSource
, newTitle
, newAuthor
});
381 if (!RemoteLibraryServer
.updateProgress(pg
, rep
)) {
390 protected void onError(Exception e
) {
391 Instance
.getTraceHandler().error(e
);
394 } catch (IOException e
) {
395 Instance
.getTraceHandler().error(e
);
400 public synchronized File
getFile(final String luid
, Progress pg
) {
401 throw new java
.lang
.InternalError(
402 "Operation not supportorted on remote Libraries");
410 new ConnectActionClientObject(host
, port
, key
) {
412 public void action(Version serverVersion
) throws Exception
{
413 send(new Object
[] { "EXIT" });
417 protected void onError(Exception e
) {
418 Instance
.getTraceHandler().error(e
);
421 } catch (IOException e
) {
422 Instance
.getTraceHandler().error(e
);
427 public synchronized MetaData
getInfo(String luid
) {
428 List
<MetaData
> metas
= getMetasList(luid
, null);
429 if (!metas
.isEmpty()) {
437 protected List
<MetaData
> getMetas(Progress pg
) {
438 return getMetasList("*", pg
);
442 protected void updateInfo(MetaData meta
) {
443 // Will be taken care of directly server side
447 protected void invalidateInfo(String luid
) {
448 // Will be taken care of directly server side
451 // The following methods are only used by Save and Delete in BasicLibrary:
454 protected int getNextId() {
455 throw new java
.lang
.InternalError("Should not have been called");
459 protected void doDelete(String luid
) throws IOException
{
460 throw new java
.lang
.InternalError("Should not have been called");
464 protected Story
doSave(Story story
, Progress pg
) throws IOException
{
465 throw new java
.lang
.InternalError("Should not have been called");
471 * Return the meta of the given story or a list of all known metas if the
474 * Will not get the covers.
477 * the luid of the story or *
479 * the optional progress
484 private List
<MetaData
> getMetasList(final String luid
, Progress pg
) {
485 final Progress pgF
= pg
;
486 final List
<MetaData
> metas
= new ArrayList
<MetaData
>();
489 new ConnectActionClientObject(host
, port
, key
) {
491 public void action(Version serverVersion
) throws Exception
{
497 Object rep
= send(new Object
[] { "GET_METADATA", luid
});
500 if (!RemoteLibraryServer
.updateProgress(pg
, rep
)) {
507 if (rep
instanceof MetaData
[]) {
508 for (MetaData meta
: (MetaData
[]) rep
) {
511 } else if (rep
!= null) {
512 metas
.add((MetaData
) rep
);
517 protected void onError(Exception e
) {
518 Instance
.getTraceHandler().error(e
);
521 } catch (Exception e
) {
522 Instance
.getTraceHandler().error(e
);