1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package gnu.hylafax.pool;
24
25 import gnu.hylafax.HylaFAXClient;
26 import gnu.hylafax.Job;
27 import gnu.inet.ftp.ServerResponseException;
28
29 import java.io.FileNotFoundException;
30 import java.io.IOException;
31 import java.io.InputStream;
32 import java.io.OutputStream;
33 import java.net.InetAddress;
34 import java.net.SocketException;
35 import java.net.UnknownHostException;
36 import java.util.Vector;
37
38 import org.apache.commons.logging.Log;
39 import org.apache.commons.logging.LogFactory;
40
41 /***
42 * This is an extension of the <code>gnu.hylafax.HylaFAXClient</code>
43 * specifically designed to work with the
44 * <code>gnu.hylafax.pool.ClientPool</code> pooling functionality.
45 *
46 * @author <a href="mailto:sjardine@users.sourceforge.net">Steven Jardine </a>
47 */
48 public class HylaFAXPooledClient extends HylaFAXClient implements PooledClient,
49 Runnable {
50
51 private final static Log log = LogFactory.getLog(HylaFAXPooledClient.class);
52
53 private ClientPool clientPool;
54
55 private boolean terminated = false;
56
57 private Thread thread = new Thread(this);
58
59 private boolean valid = true;
60
61 private boolean working = false;
62
63 /***
64 * Default constructor.
65 *
66 * @param clientPool
67 */
68 public HylaFAXPooledClient(ClientPool clientPool) {
69 this.clientPool = clientPool;
70 }
71
72
73
74
75
76
77 public void admin(String password) throws IOException,
78 ServerResponseException {
79 log.warn("Method ignored for pooled clients.");
80 }
81
82
83
84
85
86
87 public Job createJob() throws ServerResponseException, IOException {
88 if (valid && working)
89 return super.createJob();
90 return null;
91 }
92
93
94
95
96
97
98 public void delete(Job job) throws ServerResponseException, IOException {
99 if (valid && working)
100 super.delete(job);
101 }
102
103 private boolean forceReopen = false;
104
105
106
107
108
109
110 public void destroy() throws ClientPoolException {
111 try {
112 super.quit();
113 stop();
114 } catch (Exception e) {
115 throw new ClientPoolException(e.getMessage());
116 }
117 }
118
119
120
121
122
123
124 public String filefmt() throws IOException, ServerResponseException {
125 if (valid && working)
126 return super.filefmt();
127 return null;
128 }
129
130
131
132
133
134
135 public void filefmt(String value) throws IOException,
136 ServerResponseException {
137 if (valid && working)
138 super.filefmt(value);
139 }
140
141
142
143
144
145
146 public void get(String path, OutputStream out) throws IOException,
147 FileNotFoundException, ServerResponseException {
148 if (valid && working)
149 super.get(path, out);
150 }
151
152
153
154
155
156
157 public Job getJob(long id) throws ServerResponseException, IOException {
158 if (valid && working)
159 return super.getJob(id);
160 return null;
161 }
162
163
164
165
166
167
168 public Vector getList() throws IOException, FileNotFoundException,
169 ServerResponseException {
170 if (valid && working)
171 return super.getList();
172 return null;
173 }
174
175
176
177
178
179
180 public Vector getList(String path) throws IOException,
181 FileNotFoundException, ServerResponseException {
182 if (valid && working)
183 return super.getList(path);
184 return null;
185 }
186
187
188
189
190
191
192 public Vector getNameList() throws IOException, ServerResponseException,
193 FileNotFoundException {
194 if (valid && working)
195 return super.getNameList();
196 return null;
197 }
198
199
200
201
202
203
204 public Vector getNameList(String path) throws IOException,
205 ServerResponseException, FileNotFoundException {
206 if (valid && working)
207 return super.getNameList(path);
208 return null;
209 }
210
211
212
213
214
215
216 public boolean getPassive() {
217 if (valid && working)
218 return super.getPassive();
219 return false;
220 }
221
222
223
224
225
226
227 public long idle() throws IOException, ServerResponseException {
228 if (valid && working)
229 return super.idle();
230 return -1;
231 }
232
233
234
235
236
237
238 public void idle(long timeout) throws IOException, ServerResponseException {
239 if (valid && working)
240 super.idle(timeout);
241 }
242
243
244
245
246
247
248 public void interrupt(Job job) throws ServerResponseException, IOException {
249 if (valid && working)
250 super.interrupt(job);
251 }
252
253
254
255
256
257
258 public boolean isValid() {
259 return valid;
260 }
261
262 /***
263 * @return true if the client is given out for work.
264 */
265 public boolean isWorking() {
266 return working;
267 }
268
269
270
271
272
273
274 public void jdele(long jobid) throws IOException, ServerResponseException {
275 if (valid && working)
276 super.jdele(jobid);
277 }
278
279
280
281
282
283
284 public void jintr(long jobid) throws IOException, ServerResponseException {
285 if (valid && working)
286 super.jintr(jobid);
287 }
288
289
290
291
292
293
294 public void jkill(long jobid) throws IOException, ServerResponseException {
295 if (valid && working)
296 super.jkill(jobid);
297 }
298
299
300
301
302
303
304 public void jnew() throws IOException, ServerResponseException {
305 if (valid && working)
306 super.jnew();
307 }
308
309
310
311
312
313
314 public long job() throws IOException, ServerResponseException {
315 if (valid && working)
316 return super.job();
317 return -1;
318 }
319
320
321
322
323
324
325 public void job(long value) throws IOException, ServerResponseException {
326 if (valid && working)
327 super.job(value);
328 }
329
330
331
332
333
334
335 public String jobfmt() throws IOException, ServerResponseException {
336 if (valid && working)
337 return super.jobfmt();
338 return null;
339 }
340
341
342
343
344
345
346 public void jobfmt(String value) throws IOException,
347 ServerResponseException {
348 if (valid && working)
349 super.jobfmt(value);
350 }
351
352
353
354
355
356
357 public String jparm(String parm) throws IOException,
358 ServerResponseException {
359 if (valid && working)
360 return super.jparm(parm);
361 return null;
362 }
363
364
365
366
367
368
369 public void jparm(String parm, int value) throws IOException,
370 ServerResponseException {
371 if (valid && working)
372 super.jparm(parm, value);
373 }
374
375
376
377
378
379
380 public void jparm(String parm, long value) throws IOException,
381 ServerResponseException {
382 if (valid && working)
383 super.jparm(parm, value);
384 }
385
386
387
388
389
390
391 public void jparm(String parm, Object value) throws IOException,
392 ServerResponseException {
393 if (valid && working)
394 super.jparm(parm, value);
395 }
396
397
398
399
400
401
402 public void jparm(String parm, String value) throws IOException,
403 ServerResponseException {
404 if (valid && working)
405 super.jparm(parm, value);
406 }
407
408
409
410
411
412
413 public void jrest() throws IOException, ServerResponseException {
414 if (valid && working)
415 super.jrest();
416 }
417
418
419
420
421
422
423 public long jsubm() throws IOException, ServerResponseException {
424 if (valid && working)
425 return super.jsubm();
426 return -1;
427 }
428
429
430
431
432
433
434 public int jsubm(long jobid) throws IOException, ServerResponseException {
435 if (valid && working)
436 return super.jsubm(jobid);
437 return -1;
438 }
439
440
441
442
443
444
445 public void jsusp(long jobid) throws IOException, ServerResponseException {
446 if (valid && working)
447 super.jsusp(jobid);
448 }
449
450
451
452
453
454
455 public void jwait(long jobid) throws IOException, ServerResponseException {
456 if (valid && working)
457 super.jwait(jobid);
458 }
459
460
461
462
463
464
465 public void kill(Job job) throws ServerResponseException, IOException {
466 if (valid && working)
467 super.kill(job);
468 }
469
470
471
472
473
474
475 public String mdmfmt() throws IOException, ServerResponseException {
476 if (valid && working)
477 return super.mdmfmt();
478 return null;
479 }
480
481
482
483
484
485
486 public void mdmfmt(String value) throws IOException,
487 ServerResponseException {
488 if (valid && working)
489 super.mdmfmt(value);
490 }
491
492
493
494
495
496
497 public void mode(char mode) throws IOException, ServerResponseException {
498 if (valid && working)
499 super.mode(mode);
500 }
501
502
503
504
505
506
507 public void noop() throws IOException, ServerResponseException {
508 if (valid && working)
509 super.noop();
510 }
511
512
513
514
515
516
517 public void open() throws UnknownHostException, IOException,
518 ServerResponseException {
519 log.warn("Method open() ignored for pooled clients.");
520 }
521
522
523
524
525
526
527 public void open(String host) throws UnknownHostException, IOException,
528 ServerResponseException {
529 log.warn("Method open(String host) ignored for pooled clients.");
530 }
531
532
533
534
535
536
537 public void open(String host, int newPort) throws UnknownHostException,
538 IOException, ServerResponseException {
539 log.warn("Method open(String host, int port)"
540 + " ignored for pooled clients.");
541 }
542
543
544
545
546
547
548 public void pass(String password) throws IOException,
549 ServerResponseException {
550 log.warn("Method pass(String password) ignored for pooled clients.");
551 }
552
553 /***
554 * Set the admin password for pooled clients.
555 *
556 * @param password
557 * @throws IOException
558 * @throws ServerResponseException
559 */
560 void poolAdmin(String password) throws IOException, ServerResponseException {
561 super.admin(password);
562 }
563
564 /***
565 * Open method for pooled clients.
566 *
567 * @throws UnknownHostException
568 * @throws IOException
569 * @throws ServerResponseException
570 */
571 void poolOpen() throws UnknownHostException, IOException,
572 ServerResponseException {
573 super.open();
574 }
575
576 /***
577 * Open method for pooled clients.
578 *
579 * @param host
580 * @throws UnknownHostException
581 * @throws IOException
582 * @throws ServerResponseException
583 */
584 void poolOpen(String host) throws UnknownHostException, IOException,
585 ServerResponseException {
586 super.open(host, DEFAULT_PORT);
587 }
588
589 /***
590 * Open method for pooled clients.
591 *
592 * @param host
593 * @param port
594 * @throws UnknownHostException
595 * @throws IOException
596 * @throws ServerResponseException
597 */
598 void poolOpen(String host, int newPort) throws UnknownHostException,
599 IOException, ServerResponseException {
600 super.open(host, newPort);
601 }
602
603 /***
604 * Password method for pooled clients.
605 *
606 * @param password
607 * @throws IOException
608 * @throws ServerResponseException
609 */
610 void poolPass(String password) throws IOException, ServerResponseException {
611 super.pass(password);
612 }
613
614 /***
615 * Timezone method for pooled clients.
616 *
617 * @param value
618 * @throws IOException
619 * @throws ServerResponseException
620 */
621 void poolTzone(String value) throws IOException, ServerResponseException {
622 super.tzone(value);
623 }
624
625 /***
626 * User method for pooled clients.
627 *
628 * @param username
629 * @return the user associated with the username.
630 * @throws IOException
631 * @throws ServerResponseException
632 */
633 boolean poolUser(String username) throws IOException,
634 ServerResponseException {
635 return super.user(username);
636 }
637
638
639
640
641
642
643 public String put(InputStream in) throws IOException,
644 ServerResponseException {
645 if (valid && working)
646 return super.put(in);
647 return null;
648 }
649
650
651
652
653
654
655 public void put(InputStream in, String pathname) throws IOException,
656 ServerResponseException {
657 if (valid && working)
658 super.put(in, pathname);
659 }
660
661
662
663
664
665
666 public String putTemporary(InputStream data) throws IOException,
667 ServerResponseException {
668 if (valid && working)
669 return super.putTemporary(data);
670 return null;
671 }
672
673
674
675
676
677
678 public void quit() throws IOException, ServerResponseException {
679 try {
680 clientPool.put(this);
681 } catch (ClientPoolException e) {
682 log.error(e);
683 }
684 }
685
686
687
688
689
690
691 public String rcvfmt() throws IOException, ServerResponseException {
692 if (valid && working)
693 return super.rcvfmt();
694 return null;
695 }
696
697
698
699
700
701
702 public void rcvfmt(String value) throws IOException,
703 ServerResponseException {
704 if (valid && working)
705 super.rcvfmt(value);
706 }
707
708 /***
709 * Attempts to reopen the client connection.
710 *
711 * @throws ClientPoolException
712 */
713 private void reopen() throws ClientPoolException {
714 try {
715 log.debug("Attempting to reopen client.");
716
717 forceReopen = false;
718 try {
719 super.quit();
720 } catch (SocketException e) {
721
722 }
723 stop();
724 clientPool.openClient(this);
725
726 log.debug("Reopen successful.");
727 } catch (Exception e) {
728 throw new ClientPoolException(e.getMessage());
729 }
730 }
731
732 private long lastNoop = -1;
733
734 private long lastReopen = -1;
735
736
737
738
739
740
741 public void run() {
742 Thread.currentThread().setName("Pooled Client");
743 while (!terminated) {
744 try {
745
746 if (!working) {
747 long time = System.currentTimeMillis();
748 if (forceReopen
749 || (time - lastReopen) >= clientPool
750 .getConfiguration().getMaxIdleTime()) {
751 reopen();
752 lastReopen = System.currentTimeMillis();
753 } else if ((time - lastNoop) >= clientPool
754 .getConfiguration().getMaxNoopTime()) {
755 super.noop();
756 lastNoop = System.currentTimeMillis();
757 }
758 }
759
760 Thread.sleep(1000);
761 if (clientPool.isStopped())
762 terminated = true;
763 } catch (InterruptedException e) {
764
765 } catch (Exception e) {
766 log.debug(e.getMessage(), e);
767
768 valid = false;
769 forceReopen = true;
770
771 try {
772 Thread.sleep(5000);
773
774 } catch (Exception e2) {
775
776 }
777 }
778 }
779 }
780
781
782
783
784
785
786 public void setPassive(boolean passive) {
787 if (valid && working)
788 super.setPassive(passive);
789 }
790
791
792
793
794
795
796 public void setValid(boolean valid) {
797 this.valid = valid;
798 }
799
800 /***
801 * Set to true when the client has been given out of the pool. false when
802 * the client is idle.
803 *
804 * @param working
805 */
806 void setWorking(boolean working) {
807 this.working = working;
808 }
809
810
811
812
813
814
815 public long size(String pathname) throws IOException,
816 FileNotFoundException, ServerResponseException {
817 if (valid && working)
818 return super.size(pathname);
819 return -1;
820
821 }
822
823 /***
824 * Start the maintaince thread for this client.
825 */
826 public void start() {
827 if (thread.isAlive())
828 return;
829
830 terminated = false;
831 lastNoop = lastReopen = System.currentTimeMillis();
832 thread.start();
833 }
834
835 /***
836 * Stops the maintaince thread for this client.
837 */
838 public void stop() {
839 log.debug("stopping client thread");
840 terminated = true;
841 }
842
843
844
845
846
847
848 public String stot(InputStream data) throws IOException,
849 ServerResponseException {
850 if (valid && working)
851 return super.stot(data);
852 return null;
853 }
854
855
856
857
858
859
860 public void submit(Job job) throws ServerResponseException, IOException {
861 if (valid && working)
862 super.submit(job);
863 }
864
865
866
867
868
869
870 public void suspend(Job job) throws ServerResponseException, IOException {
871 if (valid && working)
872 super.suspend(job);
873 }
874
875
876
877
878
879
880 public void tzone(String value) throws IOException, ServerResponseException {
881 log.warn("Method tzone(String value) ignored for pooled clients.");
882 }
883
884
885
886
887
888
889 public boolean user(String username) throws IOException,
890 ServerResponseException {
891 log.warn("Method user(String username) ignored for pooled clients.");
892 return false;
893 }
894
895
896
897
898
899
900 public InetAddress vrfy(String dialstring) throws IOException,
901 ServerResponseException {
902 if (valid && working)
903 return super.vrfy(dialstring);
904 return null;
905 }
906
907
908
909
910
911
912 public void wait(Job job) throws ServerResponseException, IOException {
913 if (valid && working)
914 super.wait(job);
915 }
916
917 }