1 package be
.nikiroo
.fanfix
.library
;
4 import java
.io
.IOException
;
6 import java
.net
.UnknownHostException
;
7 import java
.util
.ArrayList
;
10 import javax
.net
.ssl
.SSLException
;
12 import be
.nikiroo
.fanfix
.Instance
;
13 import be
.nikiroo
.fanfix
.data
.MetaData
;
14 import be
.nikiroo
.fanfix
.data
.Story
;
15 import be
.nikiroo
.utils
.Image
;
16 import be
.nikiroo
.utils
.Progress
;
17 import be
.nikiroo
.utils
.serial
.server
.ConnectActionClientObject
;
20 * This {@link BasicLibrary} will access a remote server to list the available
21 * stories, and download the ones you try to load to the local directory
22 * specified in the configuration.
26 public class RemoteLibrary
extends BasicLibrary
{
29 private final String key
;
31 // TODO: error handling is not up to par!
34 * Create a {@link RemoteLibrary} linked to the given server.
37 * the key that will allow us to exchange information with the
40 * the host to contact or NULL for localhost
42 * the port to contact it on
44 public RemoteLibrary(String key
, String host
, int port
) {
51 public String
getLibraryName() {
52 return host
+ ":" + port
;
56 public Status
getStatus() {
57 Instance
.getTraceHandler().trace("Getting remote lib status...");
58 Status status
= getStatusDo();
59 Instance
.getTraceHandler().trace("Remote lib status: " + status
);
63 private boolean check() {
64 Status status
= getStatusDo();
65 if (status
!= Status
.READY
) {
66 Instance
.getTraceHandler().error("Remote lib not ready: " + status
);
73 private Status
getStatusDo() {
74 final Status
[] result
= new Status
[1];
76 result
[0] = Status
.INVALID
;
79 new ConnectActionClientObject(host
, port
, key
) {
81 public void action() throws Exception
{
82 Object rep
= send(new Object
[] { "PING" });
84 if ("PONG".equals(rep
)) {
85 result
[0] = Status
.READY
;
87 result
[0] = Status
.UNAUTHORIZED
;
92 protected void onError(Exception e
) {
93 // if (e instanceof SSLException) {
94 result
[0] = Status
.UNAUTHORIZED
;
96 // result[0] = Status.UNAVAILABLE;
100 } catch (UnknownHostException e
) {
101 result
[0] = Status
.INVALID
;
102 } catch (IllegalArgumentException e
) {
103 result
[0] = Status
.INVALID
;
104 } catch (Exception e
) {
105 result
[0] = Status
.UNAVAILABLE
;
112 public Image
getCover(final String luid
) {
117 final Image
[] result
= new Image
[1];
120 new ConnectActionClientObject(host
, port
, key
) {
122 public void action() throws Exception
{
123 Object rep
= send(new Object
[] { "GET_COVER", luid
});
124 result
[0] = (Image
) rep
;
128 protected void onError(Exception e
) {
129 if (e
instanceof SSLException
) {
130 Instance
.getTraceHandler().error(
131 "Connection refused (bad key)");
133 Instance
.getTraceHandler().error(e
);
137 } catch (Exception e
) {
138 Instance
.getTraceHandler().error(e
);
145 public Image
getCustomSourceCover(final String source
) {
150 return getCustomCover(source
, "SOURCE");
154 public Image
getCustomAuthorCover(final String author
) {
159 return getCustomCover(author
, "AUTHOR");
162 // type: "SOURCE" or "AUTHOR"
163 private Image
getCustomCover(final String source
, final String type
) {
168 final Image
[] result
= new Image
[1];
171 new ConnectActionClientObject(host
, port
, key
) {
173 public void action() throws Exception
{
174 Object rep
= send(new Object
[] { "GET_CUSTOM_COVER", type
,
176 result
[0] = (Image
) rep
;
180 protected void onError(Exception e
) {
181 if (e
instanceof SSLException
) {
182 Instance
.getTraceHandler().error(
183 "Connection refused (bad key)");
185 Instance
.getTraceHandler().error(e
);
189 } catch (Exception e
) {
190 Instance
.getTraceHandler().error(e
);
197 public synchronized Story
getStory(final String luid
, Progress pg
) {
202 final Progress pgF
= pg
;
203 final Story
[] result
= new Story
[1];
206 new ConnectActionClientObject(host
, port
, key
) {
208 public void action() throws Exception
{
214 Object rep
= send(new Object
[] { "GET_STORY", luid
});
216 MetaData meta
= null;
217 if (rep
instanceof MetaData
) {
218 meta
= (MetaData
) rep
;
219 if (meta
.getWords() <= Integer
.MAX_VALUE
) {
220 pg
.setMinMax(0, (int) meta
.getWords());
224 List
<Object
> list
= new ArrayList
<Object
>();
225 for (Object obj
= send(null); obj
!= null; obj
= send(null)) {
230 result
[0] = RemoteLibraryServer
.rebuildStory(list
);
235 protected void onError(Exception e
) {
236 if (e
instanceof SSLException
) {
237 Instance
.getTraceHandler().error(
238 "Connection refused (bad key)");
240 Instance
.getTraceHandler().error(e
);
244 } catch (Exception e
) {
245 Instance
.getTraceHandler().error(e
);
252 public synchronized Story
save(final Story story
, final String luid
,
253 Progress pg
) throws IOException
{
258 final String
[] luidSaved
= new String
[1];
259 Progress pgSave
= new Progress();
260 Progress pgRefresh
= new Progress();
266 pg
.addProgress(pgSave
, 9);
267 pg
.addProgress(pgRefresh
, 1);
269 final Progress pgF
= pgSave
;
271 new ConnectActionClientObject(host
, port
, key
) {
273 public void action() throws Exception
{
275 if (story
.getMeta().getWords() <= Integer
.MAX_VALUE
) {
276 pg
.setMinMax(0, (int) story
.getMeta().getWords());
279 send(new Object
[] { "SAVE_STORY", luid
});
281 List
<Object
> list
= RemoteLibraryServer
.breakStory(story
);
282 for (Object obj
: list
) {
287 luidSaved
[0] = (String
) send(null);
293 protected void onError(Exception e
) {
294 if (e
instanceof SSLException
) {
295 Instance
.getTraceHandler().error(
296 "Connection refused (bad key)");
298 Instance
.getTraceHandler().error(e
);
303 // because the meta changed:
304 MetaData meta
= getInfo(luidSaved
[0]);
305 if (story
.getMeta().getClass() != null) {
306 // If already available locally:
307 meta
.setCover(story
.getMeta().getCover());
310 meta
.setCover(getCover(meta
.getLuid()));
320 public synchronized void delete(final String luid
) throws IOException
{
322 throw new IOException("Library not ready");
325 new ConnectActionClientObject(host
, port
, key
) {
327 public void action() throws Exception
{
328 send(new Object
[] { "DELETE_STORY", luid
});
332 protected void onError(Exception e
) {
333 if (e
instanceof SSLException
) {
334 Instance
.getTraceHandler().error(
335 "Connection refused (bad key)");
337 Instance
.getTraceHandler().error(e
);
344 public void setSourceCover(final String source
, final String luid
) {
349 setCover(source
, luid
, "SOURCE");
353 public void setAuthorCover(final String author
, final String luid
) {
358 setCover(author
, luid
, "AUTHOR");
361 // type = "SOURCE" | "AUTHOR"
362 private void setCover(final String value
, final String luid
,
369 new ConnectActionClientObject(host
, port
, key
) {
371 public void action() throws Exception
{
372 send(new Object
[] { "SET_COVER", type
, value
, luid
});
376 protected void onError(Exception e
) {
377 if (e
instanceof SSLException
) {
378 Instance
.getTraceHandler().error(
379 "Connection refused (bad key)");
381 Instance
.getTraceHandler().error(e
);
385 } catch (IOException e
) {
386 Instance
.getTraceHandler().error(e
);
391 // Could work (more slowly) without it
392 public Story
imprt(final URL url
, Progress pg
) throws IOException
{
397 // Import the file locally if it is actually a file
398 if (url
== null || url
.getProtocol().equalsIgnoreCase("file")) {
399 return super.imprt(url
, pg
);
402 // Import it remotely if it is an URL
409 Progress pgImprt
= new Progress();
410 Progress pgGet
= new Progress();
411 pg
.addProgress(pgImprt
, 1);
412 pg
.addProgress(pgGet
, 1);
414 final Progress pgF
= pgImprt
;
415 final String
[] luid
= new String
[1];
418 new ConnectActionClientObject(host
, port
, key
) {
420 public void action() throws Exception
{
423 Object rep
= send(new Object
[] { "IMPORT", url
.toString() });
426 if (!RemoteLibraryServer
.updateProgress(pg
, rep
)) {
434 luid
[0] = (String
) rep
;
438 protected void onError(Exception e
) {
439 if (e
instanceof SSLException
) {
440 Instance
.getTraceHandler().error(
441 "Connection refused (bad key)");
443 Instance
.getTraceHandler().error(e
);
447 } catch (IOException e
) {
448 Instance
.getTraceHandler().error(e
);
451 if (luid
[0] == null) {
452 throw new IOException("Remote failure");
455 Story story
= getStory(luid
[0], pgGet
);
463 // Could work (more slowly) without it
464 protected synchronized void changeSTA(final String luid
,
465 final String newSource
, final String newTitle
,
466 final String newAuthor
, Progress pg
) throws IOException
{
471 final Progress pgF
= pg
== null ?
new Progress() : pg
;
474 new ConnectActionClientObject(host
, port
, key
) {
476 public void action() throws Exception
{
479 Object rep
= send(new Object
[] { "CHANGE_STA", luid
,
480 newSource
, newTitle
, newAuthor
});
482 if (!RemoteLibraryServer
.updateProgress(pg
, rep
)) {
491 protected void onError(Exception e
) {
492 if (e
instanceof SSLException
) {
493 Instance
.getTraceHandler().error(
494 "Connection refused (bad key)");
496 Instance
.getTraceHandler().error(e
);
500 } catch (IOException e
) {
501 Instance
.getTraceHandler().error(e
);
506 public synchronized File
getFile(final String luid
, Progress pg
) {
507 throw new java
.lang
.InternalError(
508 "Operation not supportorted on remote Libraries");
520 new ConnectActionClientObject(host
, port
, key
) {
522 public void action() throws Exception
{
523 send(new Object
[] { "EXIT" });
527 protected void onError(Exception e
) {
528 if (e
instanceof SSLException
) {
529 Instance
.getTraceHandler().error(
530 "Connection refused (bad key)");
532 Instance
.getTraceHandler().error(e
);
536 } catch (IOException e
) {
537 Instance
.getTraceHandler().error(e
);
542 public synchronized MetaData
getInfo(String luid
) {
547 List
<MetaData
> metas
= getMetasList(luid
, null);
548 if (!metas
.isEmpty()) {
556 protected List
<MetaData
> getMetas(Progress pg
) {
557 return getMetasList("*", pg
);
561 protected void updateInfo(MetaData meta
) {
562 // Will be taken care of directly server side
566 protected void invalidateInfo(String luid
) {
567 // Will be taken care of directly server side
570 // The following methods are only used by Save and Delete in BasicLibrary:
573 protected int getNextId() {
574 throw new java
.lang
.InternalError("Should not have been called");
578 protected void doDelete(String luid
) throws IOException
{
579 throw new java
.lang
.InternalError("Should not have been called");
583 protected Story
doSave(Story story
, Progress pg
) throws IOException
{
584 throw new java
.lang
.InternalError("Should not have been called");
590 * Return the meta of the given story or a list of all known metas if the
593 * Will not get the covers.
596 * the luid of the story or *
598 * the optional progress
603 private List
<MetaData
> getMetasList(final String luid
, Progress pg
) {
608 final Progress pgF
= pg
;
609 final List
<MetaData
> metas
= new ArrayList
<MetaData
>();
612 new ConnectActionClientObject(host
, port
, key
) {
614 public void action() throws Exception
{
620 Object rep
= send(new Object
[] { "GET_METADATA", luid
});
623 if (!RemoteLibraryServer
.updateProgress(pg
, rep
)) {
630 if (rep
instanceof MetaData
[]) {
631 for (MetaData meta
: (MetaData
[]) rep
) {
634 } else if (rep
!= null) {
635 metas
.add((MetaData
) rep
);
640 protected void onError(Exception e
) {
641 if (e
instanceof SSLException
) {
642 Instance
.getTraceHandler().error(
643 "Connection refused (bad key)");
645 Instance
.getTraceHandler().error(e
);
649 } catch (Exception e
) {
650 Instance
.getTraceHandler().error(e
);