Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: jhfc/HylaFaxConnectionManager.java


1   /*
2    * $Id: NetCon.java,v 0.12 1998/11/23 14:19:22 choeger Exp choeger $
3    *
4    * Die Klasse NetCon
5    * (c) 1997 S.u.S.E. GmbH
6    * Autor: Carsten Hoeger
7    * 
8    * Zustaendig fuer die Kommunikation mit dem HylaFAX
9    * Protokollserver. Saemtliche Ausnahmen werden in der naechst
10   * hoeheren Instanz verarbeitet
11   * 
12   * Konstruktor:
13   * public NetCon(int port, String host, boolean debug)
14   *
15   * int     port  : Portnummer des HylaFax Servers (default 4559)
16   * String  host  : Hostname des Fax-Servers
17   * boolean debug : Debug-Flag
18   */
19  package jhfc;
20  
21  
22  import java.io.*;
23  import java.net.*;
24  import java.util.StringTokenizer;
25  import java.util.Vector;
26  import java.util.zip.*;
27  
28  public class HylaFaxConnectionManager
29  {
30    private String    hostname;
31    private int    port;
32  
33    private boolean    debug;
34    
35    // Reply Codes des ftp Protokolles (rfc959)
36    public static final int CONNECTION_ALREADY_OPEN  = 125;
37    public static final int ABOUT_TO_OPEN_DATACON    = 150;
38    public static final int COMMAND_OK               = 200;
39    public static final int COM_NOT_IMPL_SUPERFLUOUS = 202;
40    public static final int SYSTEM_STATUS            = 211;
41    public static final int DIRECTORY_STATUS         = 212;
42    public static final int FILE_STATUS              = 213;
43    public static final int HELP_MESSAGE             = 214;
44    public static final int CLOSING_CONNECTION       = 221;
45    public static final int CLOSING_DATA_CONNECTION  = 226;
46    public static final int USER_LOGGED_IN           = 230;
47    public static final int FILE_ACTION_OK           = 250;
48    public static final int NEEDS_PASSWD             = 331;
49    public static final int NEEDS_ACCOUNT            = 332;
50    public static final int SERVICE_NOT_AVAILABLE    = 421;
51    public static final int NO_DATA_CONNECTION       = 425;
52    public static final int CONNECTION_CLOSED        = 426;
53    public static final int FILE_ACTION_NOT_TAKEN    = 450;
54    public static final int ACTION_ABORTED_ERROR     = 451;
55    public static final int ACTION_NOT_TAKEN_SPACE   = 452;
56    public static final int FAILED_TO_KILL_JOB       = 460;
57    public static final int SYNTAX_ERROR_COMMAND     = 500;
58    public static final int SYNTAX_ERROR_PARAMETER   = 501;
59    public static final int COMMAND_NOT_IMPLEMENTED  = 502;
60    public static final int BAD_COMMAND_SEQUENCE     = 503;
61    public static final int OPERATION_NOT_PERMITTET  = 504;
62    public static final int NOT_LOGGED_IN            = 530;
63    public static final int NEED_ACC_FOR_STORING     = 532;
64    public static final int ACTION_NOT_TAKEN         = 550;
65    public static final int ACTION_ABORTED_PAGETYPE  = 551;
66    public static final int FILE_ACTION_ABORTED      = 552;
67    public static final int ACTION_NOT_TAKEN_NAME    = 553;
68  
69    // Eigene Reply-Codes
70    public static final int LOST_CONNECTION          = -1;
71    public static final int EMPTY_REPLY_STRING       = -2;
72  
73    private Socket socket = null;
74    private BufferedReader clntIn = null;
75    private PrintWriter clntOut = null;
76  
77    protected static final int NONE    = 0;
78    protected static final int RECEIVE = 1;
79    protected static final int SEND    = 2;
80  private static int typeOfThread = NONE;
81    private static String errText   = "";
82  
83    // Konstruktor
84    public HylaFaxConnectionManager
85    (
86      String  hostname, 
87      int  port, 
88      boolean  debug
89    )
90    {
91      this.hostname=hostname;
92      this.port=port;
93      this.debug=debug;
94  debug=true;    
95    }
96  
97  
98    public void openConnection
99    (
100   )
101   throws java.io.IOException, 
102     jhfc.ProtocollException
103   {  
104     String line;
105     
106     // Socket erzeugen
107 System.out.println("opening socket to "+hostname+" over port "+port+"...");    
108     socket = new Socket(hostname, port);
109 
110     if(debug)
111     {
112       System.out.println("socket open: " + socket.getInetAddress() +
113         ":" + socket.getPort());
114     }
115 
116     // I/O Streams erzeugen
117     clntIn=new BufferedReader(new InputStreamReader(socket.getInputStream()));
118     clntOut=new PrintWriter(socket.getOutputStream());
119     
120     
121     check(clntIn.readLine());
122   }
123 
124 
125   
126   public int login
127   (
128     String username
129   )
130   throws java.io.IOException, 
131     jhfc.ProtocollException
132   {
133     clntOut.print("USER " + username + "\n");
134     clntOut.flush();
135 
136     // Reply-Code zurueckgeben
137     return check(clntIn.readLine());
138   }
139   
140 
141   private String makePORT(byte iaddr[], int port) {
142     // unteres byte
143     byte a = (byte)( port & 0xff );
144     // oberes byte
145     byte b = (byte)( ( port & 0xff00 ) >> 8 );
146     
147     // Zusammensetzen des Strings
148     return new String((0xff & iaddr[0]) + "," + (0xff & iaddr[1]) + "," + 
149           (0xff & iaddr[2]) + "," + (0xff & iaddr[3]) + "," + 
150           (0xff & b) + "," + (0xff & a));
151     // Die UND-Verknuepfung mit 0xff ist notwendig, um das
152     // Vorzeichen-Bit auszumaskieren
153     // byte in Java = -128 - +127
154   }
155 
156 
157   protected int check
158   (
159     String str
160   )
161   throws ProtocollException
162   {
163       /*
164        * check prueft die Antworten des Faxservers und reagiert
165        * folgendermassen:
166        *
167        * - gibt die Nummer des Reply-Codes zurueck, wenn alles
168        *   in Ordnung ist
169        * - erzeugt ein Ausnahmeobjekt vom Typ PROTOException
170        *   wenn ein fataler Fehler auftrat
171        * - gibt 0 zurück, wenn str kein Reply-Code ist
172        */
173 
174 //    if( debug )
175 //      System.out.println("NetCon.check: str='"+str+"'");
176 
177     String delim;
178     String Message = new String("");
179     int ret_val;
180 
181     /* Wenn der Protokollserver beendet wird, waerend eine Verbindung
182      * bestand, wird ein null-String geliefert */
183     if( str == null )
184     {
185   System.out.println(getClass().getName()+".check(): empty Reply String!!!");
186   Thread.dumpStack();
187       throw new ProtocollException(getClass().getName()+".check(): empty Reply String!!!",
188              EMPTY_REPLY_STRING);
189     }
190 
191     if( str.charAt(3) == '-' )
192       delim = new String("-");
193     else
194       delim = new String(" ");
195 
196     StringTokenizer st = new StringTokenizer(str,delim);
197 
198     // Wenn str ein normaler String ist, gib 0 zurueck
199     try {
200       ret_val = new Integer(st.nextToken()).intValue();
201     }
202     catch (NumberFormatException e) {
203       ret_val=0;
204     }
205 
206     for(int i=st.countTokens(); i>0; i--) {
207       Message += st.nextToken() + " ";
208     }
209 
210 //    if( debug )
211 //      System.out.println("NetCon.check: " + Message);
212     
213     // Die folgenden Reply-Codes erzeugen ein Ausnahmeobject
214     if( ret_val == SERVICE_NOT_AVAILABLE   ||
215   ret_val == NO_DATA_CONNECTION      ||
216   ret_val == CONNECTION_CLOSED       ||
217   ret_val == FILE_ACTION_NOT_TAKEN   ||
218   ret_val == ACTION_ABORTED_ERROR    ||
219   ret_val == ACTION_NOT_TAKEN_SPACE  ||
220   ret_val == SYNTAX_ERROR_COMMAND    ||
221   ret_val == SYNTAX_ERROR_PARAMETER  ||
222   ret_val == COMMAND_NOT_IMPLEMENTED ||
223   ret_val == BAD_COMMAND_SEQUENCE    ||
224   ret_val == OPERATION_NOT_PERMITTET ||
225   ret_val == NOT_LOGGED_IN           ||
226   ret_val == NEED_ACC_FOR_STORING    ||
227   ret_val == ACTION_NOT_TAKEN        ||
228   ret_val == ACTION_ABORTED_PAGETYPE ||
229   ret_val == FILE_ACTION_ABORTED     ||
230   ret_val == FAILED_TO_KILL_JOB      ||
231   ret_val == ACTION_NOT_TAKEN_NAME )
232     {
233   System.out.println(getClass().getName()+".check(): "+Message+" ret_val="+ret_val);
234 //  Thread.dumpStack();
235   throw new ProtocollException(Message, ret_val);
236     }
237     else
238       return ret_val;
239   }
240 
241 
242   
243   public void logout
244   (
245   )
246   {
247     try
248     {
249       clntOut.print("QUIT" + "\n");
250       clntOut.flush();
251 
252       check(clntIn.readLine());
253     }
254     catch (java.io.IOException ex)
255     {
256       System.out.println(getClass().getName()+"(): "+ex+" "+ex.getMessage());
257       Thread.dumpStack();
258     }
259     catch (jhfc.ProtocollException ex)
260     {
261       System.out.println(getClass().getName()+"(): "+ex+" "+ex.getMessage());
262       Thread.dumpStack();
263     }
264   }
265 
266   // Verbindung schliessen
267   public void closeConnection
268   (
269   )
270   {
271     if(socket!=null)
272     {
273       try
274       {
275         clntIn.close();
276         clntOut.close();
277         socket.close();
278 System.out.println("socket to "+hostname+" closed");
279       }
280       catch (java.io.IOException ex)
281       {
282         System.out.println(getClass().getName()+"(): "+ex+" "+ex.getMessage());
283         Thread.dumpStack();
284       }
285     }
286   }
287 
288   public String sendbuffer(char buf[]) throws Exception {
289     byte bytebuf[] = new byte[buf.length];
290 
291     for(int i=0; i<buf.length; i++)
292       bytebuf[i] = (byte)buf[i];
293 
294     return sendbuffer(bytebuf);
295   }
296 
297   public String sendbuffer
298   (
299     byte buf[]
300   )
301   throws java.io.IOException, 
302     jhfc.ProtocollException
303   {
304     // Diese Funktion sendet das Byte-Array buf an den Server
305     SendServ sndsrv;
306     String pstr;
307     byte iaddr[];
308 
309     Deflater df = new Deflater(9, false);
310     
311     ByteArrayOutputStream baos = new ByteArrayOutputStream();
312     
313     DeflaterOutputStream dos = 
314       new DeflaterOutputStream(baos, df, buf.length);
315     
316     dos.write(buf, 0, buf.length);
317     dos.close();
318     
319     //System.out.write(baos.toByteArray(), 0, baos.toByteArray().length);
320     
321     //System.exit(0);
322     
323     // Erzeugen des SendServ-Threads
324     //sndsrv = new SendServ(buf, debug);
325     sndsrv = new SendServ(baos.toByteArray(), debug);
326     
327     iaddr = getInetAddr();
328     pstr = makePORT(iaddr, sndsrv.port);
329 
330     clntOut.print("TYPE I" + "\n"); // Binaer
331     clntOut.flush();
332     check(clntIn.readLine());
333 
334     clntOut.print("MODE Z" + "\n"); // ZIP
335     //clntOut.print("MODE S" + "\n"); // Stream
336     clntOut.flush();
337     check(clntIn.readLine());
338 
339     clntOut.print("PORT " + pstr + "\n");
340     clntOut.flush();
341     check(clntIn.readLine());
342     
343     clntOut.print("STOT" + "\n");
344     clntOut.flush();
345     String line = clntIn.readLine();
346     check(line); 
347 
348     if( debug )
349       System.out.println("NetCon.sendbuffer: Jetzt senden!!!");
350 
351     // Auf Beendigung des Threads warten
352     try {
353       sndsrv.join();
354     }
355     catch (InterruptedException e) {};
356 
357     StringTokenizer st = new StringTokenizer(line," ");
358     st.nextToken();
359     st.nextToken();
360     String filename = st.nextToken();
361     check(clntIn.readLine());
362 
363     // Zurueckgegeben wird der Dateiname, unter dem der Server
364     // den Buffer gespeichert hat
365     return filename;
366   }
367 
368   public byte[] getReceived
369   (
370   String name
371   )
372   throws java.io.IOException, 
373     jhfc.ProtocollException
374   {
375     // Diese Funktion gibt in einem Byte-Array die angeforderte
376     // Datei name zurueck. 
377 
378     String pstr;      // String für port
379     byte iaddr[];     // byte-array für Internetadresse
380     RecvServ recsrv;  // server-thread-object
381 
382     // Thread erzeugen
383     recsrv = new RecvServ(debug);
384 
385     iaddr = getInetAddr();
386     pstr = makePORT(iaddr, recsrv.port);
387 
388     if( debug )
389       System.out.println("NetCon.getReceived: " + pstr);
390     
391     clntOut.print("TYPE I" + "\n");
392     clntOut.flush();
393     check(clntIn.readLine());
394 
395     clntOut.print("MODE S" + "\n");
396     //clntOut.print("MODE Z" + "\n");
397     clntOut.flush();
398     check(clntIn.readLine());
399 
400 //    clntOut.print("CWD recvq" + "\n");  // in das recvq Verzeichnis wechseln
401 //    clntOut.flush();
402 //    check(clntIn.readLine());
403 
404     clntOut.print("PORT " + pstr + "\n");
405     clntOut.flush();
406     check(clntIn.readLine());
407     
408     clntOut.print("RETR " + name + "\n");
409     clntOut.flush();
410     check(clntIn.readLine());
411     check(clntIn.readLine());
412     
413     // Auf Beendigung des Threads warten
414     try {
415       recsrv.join();
416     }
417     catch (InterruptedException e) {};
418 
419     clntOut.print("CWD" + "\n"); // zurueck nach Serverroot
420     clntOut.flush();
421     check(clntIn.readLine());
422 
423     if( debug )
424       System.out.println("NetCon.getReceived(): " + recsrv.data.length);
425 
426     //ByteArrayInputStream is = new ByteArrayInputStream(recsrv.data);
427 
428     //InflaterInputStream iis = new InflaterInputStream(is);
429 
430     return recsrv.data;
431   }
432   
433   public String list
434   (
435     String what
436   )
437   throws java.io.IOException, 
438     jhfc.ProtocollException
439   {
440     // Diese Funktion gibt den Inhalt des mit what angegebenen
441     // Verzeichnisses als String zurueck.
442 
443     String pstr;      // String für port
444     String line;      // String für linebuffer
445     byte iaddr[];     // byte-array für Internetadresse
446     RecvServ recsrv;  // server-thread-object
447 
448     // Thread erzeugen
449     recsrv = new RecvServ(debug);
450 
451     iaddr = getInetAddr();
452     pstr = makePORT(iaddr, recsrv.port);
453 
454     if( debug )
455       System.out.println("NetCon.infoS: " + pstr);
456     
457     clntOut.print("PORT " + pstr + "\n");
458     clntOut.flush();
459     check(clntIn.readLine());
460     
461     clntOut.print("LIST " + what + "\n");
462     clntOut.flush();
463 
464 
465     // Auf Beendigung des Threads warten
466     try {
467       recsrv.join();
468     }
469     catch (InterruptedException e) {};
470 
471     if( typeOfThread != NONE ) {
472 //      throw new ProtocollException(errText, LOST_CONNECTION);
473   throw new java.io.IOException(errText);
474     }
475 
476     if( check(clntIn.readLine()) == ABOUT_TO_OPEN_DATACON ) {
477       check(clntIn.readLine());
478     } else {
479 //      throw new ProtocollException("NetCon.infoS: No Data from Faxserver",1);
480   throw new java.io.IOException("NetCon.infoS: No Data from Faxserver");
481     }
482     
483     //     // Auf Beendigung des Threads warten
484     //     try {
485     //       recsrv.join();
486     //     }
487     //     catch (InterruptedException e) {};
488     
489     int cnt; // Anzahl der Zeichen zaehlen
490     for(cnt=0; cnt<recsrv.data.length; cnt++)
491       if( recsrv.data[cnt] == 0 ) break;
492 
493     //hibyte - the top 8 bits of each 16-bit Unicode character 
494     return new String(recsrv.data,0,cnt);
495   }
496   
497 
498   public String command
499   (
500     String what
501   )
502   throws java.io.IOException, 
503     jhfc.ProtocollException
504   {
505     /*
506      * Sendet ein Kommando an den Faxserver und
507      * gibt die Antwort zurueck oder erzeugt ein
508      * Ausnahmeobjekt
509      */
510 
511     byte buf[] = new byte[80];
512     byte data[];
513     String response;
514     String line;
515 
516     clntOut.print(what + "\n");
517     clntOut.flush();
518 
519     response=new String(clntIn.readLine());
520     int erg = check(response);
521 
522     if(debug==true)
523     {
524 //      System.out.println(getClass().getName()+": erg="+erg+" what='"+what+"' "+response.charAt(3));
525     }
526     
527     // SYSTEM_STATUS und HELP_MESSAGE sind laenger als
528     // eine Zeile
529     if((erg==SYSTEM_STATUS)||
530        (erg==HELP_MESSAGE)||
531        ((erg==FILE_STATUS)&&(response.charAt(3)=='-')))
532     {
533       while(true)
534       {
535         line = clntIn.readLine();
536         if( check(line) == erg )
537         {
538           break;
539         }
540         response += line + "\n";
541       }
542     }
543 
544     return response;
545   }
546 
547 
548   
549 
550   private byte[] getInetAddr
551   (
552   )
553   {
554     byte iaddr[];
555 
556     try
557     {
558       iaddr = socket.getInetAddress().getLocalHost().getAddress();
559     }
560     catch (java.net.UnknownHostException ex)
561     {
562       System.out.println(getClass().getName()+".check(): empty Reply String!!!");
563       Thread.dumpStack();
564       System.exit(-1);
565       return(null);
566     }
567     return(iaddr);
568   }
569 
570   
571   protected static void fail
572   (
573     String msg, 
574     Exception e, 
575     int which
576   )
577   {
578     // Wird vom RecServ aufgerufen, wenn im Thread ein Fehler auftritt
579     System.err.println(msg + ": " + e);
580 
581     typeOfThread = which;
582     errText      = msg + ": " + e;
583   }
584 }
585 
586 /*
587  * Die Klasse RecServ ist abgeleitet von der Klasse Thread.
588  * Sie empfaengt Daten vom Protokoll Server
589  */
590 
591 class RecvServ extends Thread {
592   protected int port;
593   protected byte data[];
594 
595   private final static int timeout = 20; // in seconds
596   private ServerSocket srv;
597   private Socket srv_clnt;
598   private boolean debug;
599 
600 
601   public RecvServ
602   (
603     boolean debug
604   )
605   throws java.io.IOException
606   {
607     this.debug = debug;
608 
609     // naechsten freien Port benutzen
610     srv = new ServerSocket(0, timeout);
611     port = srv.getLocalPort();
612     if( debug )
613       System.out.println("RecvServ: port=" + port);
614     this.start();
615   }
616 
617   // thread body
618   public void run() {
619     DataInputStream in;
620     byte buf[] = new byte[1024];
621     
622     try {
623       if( debug )
624   System.out.println("RecvServ.run: Baue Verbindung auf");
625       srv_clnt = srv.accept();
626       
627       if( debug )
628   System.out.println("RecvServ.run: Erzeuge InputStream");
629       in = new DataInputStream(srv_clnt.getInputStream());
630       
631       if( debug )
632   System.out.println("RecvServ.run: Warte auf Daten");
633 
634       // ByteArrayOutputStream verhaelt sich wie ein Stream
635       // und laesst sich wunderbar in ein Byte-Array zurueckwandeln
636       ByteArrayOutputStream out = new ByteArrayOutputStream();
637 
638       int anz;
639       while( (anz = in.read(buf)) > 0 )
640   out.write(buf,0,anz);
641 
642       data = out.toByteArray();
643 
644       if( srv != null )
645   srv.close();
646     }
647   catch (IOException e)
648   {
649     HylaFaxConnectionManager.fail("RecvServ", e, HylaFaxConnectionManager.RECEIVE);
650   }
651     
652   if(debug)
653   {
654         System.out.println("RecvServ.run: Thread beendet!");
655   }
656   }
657 }
658 
659 /*
660  * Die Klasse SendServ ist abgeleitet von der Klasse Thread.
661  * Sie sendet Daten zum Protokoll Server
662  */
663 
664 class SendServ extends Thread {
665   protected int port;
666 
667   private final static int timeout = 20; // in seconds
668   private byte buf[];
669   private ServerSocket srv;
670   private Socket srv_clnt;
671   private boolean debug;
672 
673   public SendServ
674   (
675     byte buf[], 
676     boolean debug
677   )
678   throws java.io.IOException
679   {
680 
681     this.buf = buf;
682     this.debug = debug;
683 
684     // get next free port
685     srv = new ServerSocket(0, timeout);
686     port = srv.getLocalPort();
687     if( debug )
688       System.out.println("SendServ: port=" + port);
689     this.start();
690   }
691 
692   // thread body
693   public void run() {
694     DataOutputStream out;
695     
696     try {
697       if( debug )
698   System.out.println("SendServ.run: Baue Verbindung auf");
699       srv_clnt = srv.accept();
700       
701       if( debug )
702   System.out.println("SendServ.run: Erzeuge OutputStream");
703       out = new DataOutputStream(srv_clnt.getOutputStream());
704       
705       out.write(buf, 0, buf.length);
706       out.flush();
707 
708       srv_clnt.close();
709 
710       if( debug )
711   System.out.println("SendServ.run: Gesendete Bytes=" + out.size());
712 
713       if( srv != null )
714   srv.close();
715     }
716   catch (IOException e)
717   {
718     HylaFaxConnectionManager.fail("Thread error", e, HylaFaxConnectionManager.SEND);
719   }
720     
721   if(debug)
722   {
723     System.out.println("SendServ.run: Thread beendet!");
724   }
725   }
726 }
727