ce9a301d51bb4ecc8170f25d49542b0370cd1eff
[openjpeg.git] / src / bin / jpip / opj_viewer / src / JPIPHttpClient.java
1 /*
2  * $Id$
3  *
4  * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
5  * Copyright (c) 2002-2011, Professor Benoit Macq
6  * Copyright (c) 2010-2011, Kaori Hagihara
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 import java.net.*;
32 import java.io.*;
33 import java.util.*;
34
35
36 public class JPIPHttpClient 
37 {    
38     private String comURL;
39     protected int fw, fh;
40     protected int rx, ry;
41     protected int rw, rh;
42     protected String cid;
43     protected String tid;
44     private boolean JPTstream;
45     private boolean JPPstream;
46     private boolean aux;
47     private boolean tcp; // true: tcp, false: udp
48     private int port;
49     
50     public JPIPHttpClient( String URI)
51     {
52         comURL = URI + "?";
53         fw = fh = -1;
54         rx = ry = -1;
55         rw = rh = -1;
56         cid = null;
57         tid = null;
58         JPTstream = JPPstream = aux = false;
59         port = 0;
60     }
61
62     public int getFw(){ return fw;}
63     public int getFh(){ return fh;}
64     public int getRx(){ return rx;}
65     public int getRy(){ return ry;}
66     public int getRw(){ return rw;}
67     public int getRh(){ return rh;}
68     
69     public byte[] requestViewWindow( int reqfw, int reqfh)
70     {
71         if( cid != null)
72             return requestViewWindow( reqfw, reqfh, cid);
73         else
74             return null;
75     }
76   
77     public byte[] requestViewWindow( int reqfw, int reqfh, int reqrx, int reqry, int reqrw, int reqrh)
78     {
79         if( cid != null)
80             return requestViewWindow( reqfw, reqfh, reqrx, reqry, reqrw, reqrh, cid);
81         else
82             if( tid != null)
83                 return requestViewWindow( null, tid, reqfw, reqfh, reqrx, reqry, reqrw, reqrh, null, false, 0, false, false);
84             else
85                 return null;
86     }
87
88     public byte[] requestViewWindow( int reqfw, int reqfh, String reqcid)
89     {
90         return requestViewWindow( null, null, reqfw, reqfh, -1, -1, -1, -1, reqcid, false, 0, false, false);
91     }
92
93     public byte[] requestViewWindow( int reqfw, int reqfh, int reqrx, int reqry, int reqrw, int reqrh, String reqcid)
94     {
95         return requestViewWindow( null, null, reqfw, reqfh, reqrx, reqry, reqrw, reqrh, reqcid, false, 0, false, false);
96     }
97
98     public byte[] requestViewWindow( String target, int reqfw, int reqfh)
99     {
100         return requestViewWindow( target, null, reqfw, reqfh, -1, -1, -1, -1, null, false, 0, false, false);
101     }
102     
103     public byte[] requestViewWindow( String target, int reqfw, int reqfh, boolean reqcnew, int reqaux, boolean reqJPP, boolean reqJPT)
104     {
105         if( cid == null) // 1 channel allocation only
106             return requestViewWindow( target, null, reqfw, reqfh, -1, -1, -1, -1, null, reqcnew, reqaux, reqJPP, reqJPT);
107         else
108             return null;
109     }
110
111     public byte[] requestViewWindow( String target, String reqtid, int reqfw, int reqfh, boolean reqcnew, int reqaux, boolean reqJPP, boolean reqJPT)
112     {
113         if( cid == null) // 1 channel allocation only
114             return requestViewWindow( target, reqtid, reqfw, reqfh, -1, -1, -1, -1, null, reqcnew, reqaux, reqJPP, reqJPT);
115         else
116             return null;
117     }
118     
119     public byte[] requestViewWindow( String target, int reqfw, int reqfh, int reqrx, int reqry, int reqrw, int reqrh)
120     {
121         return requestViewWindow( target, null, reqfw, reqfh, reqrx, reqry, reqrw, reqrh, null, false, 0, false, false);
122     }
123  
124     public byte[] requestViewWindow( int reqfw, int reqfh, String reqcid, boolean reqcnew, int reqaux, boolean reqJPP, boolean reqJPT)
125     {
126         return requestViewWindow( null, null, reqfw, reqfh, -1, -1, -1, -1, reqcid, reqcnew, reqaux, reqJPP, reqJPT);
127     }
128     
129     public byte[] requestViewWindow( String target,
130                                      String reqtid,
131                                      int reqfw, int reqfh, 
132                                      int reqrx, int reqry, 
133                                      int reqrw, int reqrh, 
134                                      String reqcid, boolean reqcnew, int reqaux, boolean reqJPP, boolean reqJPT)
135     {
136         if( reqtid != null)
137             tid = reqtid;
138
139         String urlstring = const_urlstring( target, reqtid, reqfw, reqfh, reqrx, reqry, reqrw, reqrh, reqcid, reqcnew, reqaux, reqJPP, reqJPT);
140         return GETrequest( urlstring);
141     }
142     
143     public byte[] requestXML()
144     {
145         String urlstring = comURL;
146         
147         if( cid == null)
148             return null;
149         
150         urlstring = urlstring.concat( "cid=" + cid);
151         urlstring = urlstring.concat( "&metareq=[xml_]");
152     
153         return GETrequest( urlstring);
154     }
155   
156     private byte[] GETrequest( String urlstring)
157     {
158         URL url = null;
159         HttpURLConnection urlconn = null;
160         byte[] jpipstream = null;
161     
162         try{
163             url = new URL( urlstring);
164         
165             System.err.println("Requesting: " + url);
166       
167             urlconn = (HttpURLConnection)url.openConnection();
168             urlconn.setRequestMethod("GET");
169             urlconn.setInstanceFollowRedirects(false);
170             urlconn.connect();
171
172             set_responseheader( urlconn);
173             
174             if( !aux){
175                 jpipstream = receive_httpchunk( urlconn);
176                 urlconn.disconnect();
177             }
178             else{
179                 urlconn.disconnect();
180                 jpipstream = receive_tcpaux( comURL.substring( 7, comURL.indexOf('/', 7)), port, cid);
181             }
182         }
183         catch ( MalformedURLException e){
184             e.printStackTrace();
185         }
186         catch ( ProtocolException e){
187             e.printStackTrace();
188         }    
189         catch( ClassCastException  e){
190             e.printStackTrace();
191         }
192         catch( NullPointerException e){
193             e.printStackTrace();
194         }  
195         catch( UnknownServiceException e){
196             e.printStackTrace();
197         }
198         catch ( IOException e){
199             e.printStackTrace();
200         }
201         
202         return jpipstream;
203     }
204
205     private void set_responseheader( HttpURLConnection urlconn)
206     {
207         Map<String,java.util.List<String>> headers = urlconn.getHeaderFields();
208         java.util.List<String> hvaluelist;
209         String hvalueline;
210         
211         String status = headers.get(null).get(0);
212             
213         System.err.println( status);
214         if( !status.contains("OK"))
215             System.err.println( headers.get("Reason"));
216             
217         if(( hvaluelist = headers.get("Content-type")) == null)
218             hvaluelist = headers.get("Content-Type");
219         hvalueline = hvaluelist.get(0);
220         System.err.println( hvalueline);
221
222         if( hvalueline.endsWith("jpt-stream"))
223             JPTstream = true;
224         else if( hvalueline.endsWith("jpp-stream"))
225             JPPstream = true;
226             
227         if(( hvaluelist = headers.get("JPIP-fsiz")) != null){
228             hvalueline = hvaluelist.get(0);
229             fw = Integer.valueOf( hvalueline.substring( 0, hvalueline.indexOf(','))).intValue();
230             fh = Integer.valueOf( hvalueline.substring( hvalueline.indexOf(',')+1 )).intValue();
231         
232             System.err.println("fw,fh: " + fw + "," + fh);
233         }
234       
235         if(( hvaluelist = headers.get("JPIP-roff")) != null){
236             hvalueline = hvaluelist.get(0);
237             rx = Integer.valueOf( hvalueline.substring( 0, hvalueline.indexOf(','))).intValue();
238             ry = Integer.valueOf( hvalueline.substring( hvalueline.indexOf(',')+1 )).intValue();
239             System.err.println("rx,ry: " + rx + "," + ry);
240         }
241     
242         if(( hvaluelist = headers.get("JPIP-rsiz")) != null){
243             hvalueline = hvaluelist.get(0);
244             rw = Integer.valueOf( hvalueline.substring( 0, hvalueline.indexOf(','))).intValue();
245             rh = Integer.valueOf( hvalueline.substring( hvalueline.indexOf(',')+1 )).intValue();
246             System.err.println("rw,rh: " + rw + "," + rh);
247         }
248             
249         if(( hvaluelist = headers.get("JPIP-cnew")) != null){
250             hvalueline = hvaluelist.get(0);
251             cid = hvalueline.substring( hvalueline.indexOf('=')+1, hvalueline.indexOf(','));
252                 
253             int idxOfcid = hvalueline.indexOf("transport")+10;
254             int idxOfcid2 = hvalueline.indexOf(',', idxOfcid);
255             String transport;
256             if( idxOfcid2 != -1)
257                 transport = hvalueline.substring( idxOfcid, idxOfcid2);
258             else
259                 transport = hvalueline.substring( idxOfcid);
260
261             if( transport.matches("http-tcp")){
262                 aux = true;
263                 tcp = true;
264             }
265             else if( transport.matches("http-udp")){
266                 aux = true;
267                 tcp = false;
268             }
269             else
270                 aux = false;
271                 
272             if( aux){
273                 idxOfcid = hvalueline.indexOf("auxport")+8;
274                 port = Integer.valueOf( hvalueline.substring( idxOfcid)).intValue();
275                 System.err.println("cid: " + cid + ", transport: " + transport + ", auxport: " + port);
276             }
277             else                
278                 System.err.println("cid: " + cid + ", transport: " + transport);
279         }
280
281         if(( hvaluelist = headers.get("JPIP-tid")) != null){
282             hvalueline = hvaluelist.get(0);
283             tid = hvalueline.substring( hvalueline.indexOf('=')+1);
284             System.err.println("tid: " + tid);
285         }
286     }
287
288     private static byte[] receive_httpchunk( HttpURLConnection urlconn)
289     {   
290         byte[] chunk = null;
291         InputStream input;
292
293         try{
294             input = urlconn.getInputStream();
295                 
296             if( input.available() > 0){    
297                 ByteArrayOutputStream tmpstream = new ByteArrayOutputStream();
298                 byte[] buf = new byte[ 1024];
299                 int redlen, buflen;
300
301                 System.err.println("reading jpipstream...");
302             
303                 do{
304                     redlen = input.read( buf);
305                 
306                     if( redlen == -1)
307                         break;
308                     tmpstream.write( buf, 0, redlen);
309                 }while( redlen > 0);
310       
311                 buflen = tmpstream.size();
312                 chunk = tmpstream.toByteArray();
313             
314                 buf = null;
315                 tmpstream = null;
316
317                 System.err.println("jpiplen: " + buflen);
318                 System.err.println("    succeeded");
319             }
320             else{
321                 System.err.println("No new jpipstream");
322             }
323             input.close();
324         }
325         catch ( IOException e){
326             e.printStackTrace();
327         }
328
329         return chunk;
330     }
331
332     private static byte[] receive_tcpaux( String host, int port, String cid)
333     {   
334         Socket jpipsocket;
335         DataOutputStream os;
336         DataInputStream  is;
337         byte []auxheader;
338         byte []chunkbody = null;
339         byte []stream = null;
340         int chunkbodylen, streamlen, headlen = 8;
341         ByteArrayOutputStream tmpstream;
342
343         try{
344             jpipsocket = new Socket( host, port);
345             os = new DataOutputStream( jpipsocket.getOutputStream());
346             is = new DataInputStream( jpipsocket.getInputStream());
347             auxheader = new byte[headlen];
348             tmpstream = new ByteArrayOutputStream();
349         
350             os.writeBytes( cid + "\r\n");
351
352             do{
353                 read_stream( is, auxheader, headlen);
354             
355                 chunkbodylen = ((auxheader[0]&0xff)<<8 | (auxheader[1]&0xff)) - headlen;
356                 
357                 chunkbody = new byte [ chunkbodylen];
358                 read_stream( is, chunkbody, chunkbodylen);
359                 tmpstream.write( chunkbody, 0, chunkbodylen);
360
361                 os.write( auxheader, 0, headlen);
362             }while( !(chunkbody[chunkbodylen-3]==0x00 && ( chunkbody[chunkbodylen-2]==0x01 || chunkbody[chunkbodylen-2]== 0x02)));
363         
364             streamlen = tmpstream.size();
365             stream = tmpstream.toByteArray();
366             
367             System.err.println("jpiplen: " + streamlen);
368             System.err.println("    succeeded");
369         
370             chunkbody = null;
371             tmpstream = null;
372             
373             os.close();
374             is.close();
375             
376             jpipsocket.close();
377         }
378         catch ( IOException e){
379             e.printStackTrace();
380         }
381
382         return stream;
383     }
384     
385     private static void read_stream( InputStream is, byte []stream, int length)
386     {
387         int remlen = length;
388         int off = 0;
389
390         try{
391             while( remlen > 0){
392                 int redlen = is.read( stream, off, remlen);
393
394                 if( redlen == -1){
395                     System.err.println("    failed to read_stream()");
396                     break;
397                 }
398                 off += redlen;
399                 remlen -= redlen;
400             }
401         } catch (IOException e) {
402             System.err.println("IOException: " + e);
403         }
404     }
405   
406     private String const_urlstring( String target,
407                                     String reqtid,
408                                     int reqfw, int reqfh, 
409                                     int reqrx, int reqry, 
410                                     int reqrw, int reqrh, 
411                                     String reqcid, boolean reqcnew, int reqaux, boolean reqJPP, boolean reqJPT)
412     {
413         String urlstring = comURL;
414
415         // C.7.3 Image Return Type
416         // add type=jpp-stream(;ptype=ext) or type=jpt-stream;ttype=ext
417
418         if( target != null){
419             if( !urlstring.endsWith("?"))
420                 urlstring = urlstring.concat( "&");
421             urlstring = urlstring.concat( "target=" + target);
422         }
423         if( reqtid != null){
424             if( !urlstring.endsWith("?"))
425                 urlstring = urlstring.concat( "&");
426             urlstring = urlstring.concat( "tid=" + reqtid);
427         }
428         if( reqfw != -1 && reqfh != -1){
429             if( !urlstring.endsWith("?"))
430                 urlstring = urlstring.concat( "&");
431             urlstring = urlstring.concat( "fsiz=" + reqfw + "," + reqfh);
432         }
433         if( reqrx != -1 && reqry != -1){
434             if( !urlstring.endsWith("?"))
435                 urlstring = urlstring.concat( "&");
436             urlstring = urlstring.concat( "roff=" + reqrx + "," + reqry);
437         }
438         if( reqrw != -1 && reqrh != -1){
439             if( !urlstring.endsWith("?"))
440                 urlstring = urlstring.concat( "&");
441             urlstring = urlstring.concat( "rsiz=" + reqrw + "," + reqrh);
442         }
443         if( reqcid != null){
444             if( !urlstring.endsWith("?"))
445                 urlstring = urlstring.concat( "&");
446             urlstring = urlstring.concat( "cid=" + reqcid);
447         }
448         if( reqcnew){
449             if( !urlstring.endsWith("?"))
450                 urlstring = urlstring.concat( "&");
451             if( reqaux == 1)
452                 urlstring = urlstring.concat( "cnew=http-tcp");
453             else if( reqaux == 2)
454                 urlstring = urlstring.concat( "cnew=http-udp");
455             else
456                 urlstring = urlstring.concat( "cnew=http");
457         }
458         if( reqJPP && !JPTstream){
459             if( !urlstring.endsWith("?"))
460                 urlstring = urlstring.concat( "&");
461             urlstring = urlstring.concat( "type=jpp-stream");
462         }
463         else if( reqJPT && !JPPstream){
464             if( !urlstring.endsWith("?"))
465                 urlstring = urlstring.concat( "&");
466             urlstring = urlstring.concat( "type=jpt-stream");
467         }
468         else{ // remove this option later
469             if( !urlstring.endsWith("?"))
470                 urlstring = urlstring.concat( "&");
471             if( JPTstream)
472                 urlstring = urlstring.concat( "type=jpt-stream");
473             else if( JPPstream)
474                 urlstring = urlstring.concat( "type=jpp-stream");
475         }
476
477         return urlstring;
478     }
479     
480     public void closeChannel()
481     {
482         if( cid == null)
483             return;
484       
485         try{
486             URL url = new URL( comURL + "cclose=" + cid);
487             System.err.println( "closing cid: " + cid);
488       
489             HttpURLConnection urlconn = (HttpURLConnection)url.openConnection();
490             urlconn.setRequestMethod("GET");
491             urlconn.setInstanceFollowRedirects(false);
492             urlconn.connect();
493       
494             Map headers = urlconn.getHeaderFields();
495      
496             urlconn.disconnect();
497         } catch ( MalformedURLException e){
498             e.printStackTrace();
499         } catch ( IOException e){
500             e.printStackTrace();
501         }
502     }    
503 }