Statistics
| Revision:

svn-gvsig-desktop / trunk / libraries / libRemoteServices / src / org / gvsig / remoteClient / wms / WMSProtocolHandler.java @ 3532

History | View | Annotate | Download (14 KB)

1

    
2
package org.gvsig.remoteClient.wms;
3

    
4
import java.io.BufferedOutputStream;
5
import java.io.DataOutputStream;
6
import java.io.File;
7
import java.io.FileOutputStream;
8
import java.io.FileReader;
9
import java.io.IOException;
10
import java.io.InputStream;
11
import java.io.OutputStream;
12
import java.net.ConnectException;
13
import java.net.URL;
14
import java.net.UnknownHostException;
15
import java.util.TreeMap;
16
import java.util.Vector;
17

    
18
import org.gvsig.remoteClient.exceptions.ServerErrorException;
19
import org.gvsig.remoteClient.exceptions.WMSException;
20
import org.gvsig.remoteClient.utils.CapabilitiesTags;
21
import org.gvsig.remoteClient.utils.Utilities;
22
import org.kxml2.io.KXmlParser;
23

    
24
import com.devx.io.TempFileManager;
25

    
26

    
27
/**
28
 * <p> Abstract class that represents handlers to comunicate via WMS protocol.
29
 * </p>
30
 * 
31
 */
32
public abstract class WMSProtocolHandler {
33

    
34
        /**
35
         * procotol handler name
36
         */
37
    protected String name;
38
    /**
39
     * protocol handler version
40
     */
41
    protected String version;
42
    /**
43
     * host of the WMS to connect
44
     */
45
    protected String host;
46
    /**
47
     *  port number of the comunication channel of the WMS to connect
48
     */
49
    protected String port;    
50
    /**
51
     * WMS metadata
52
     */
53
    protected ServiceInformation serviceInfo;
54
    public TreeMap layers;
55
    public WMSLayer rootLayer;
56
    public Vector srs;
57
    
58

    
59
    // abstract methods to implement by the handlers that implement
60
    // the connection to a WMS with certain version.
61
    //    public abstract String getName();   
62
    //    public abstract String getVersion();
63
    
64
    /**
65
     * parses the data retrieved by the WMS in XML format. 
66
     * It will be mostly the WMS Capabilities, but the implementation
67
     * will be placed in the handler implementing certain version of the protocol.
68
     * 
69
     */
70
    public abstract void parse(File f) ;
71

    
72
    public String getName() {        
73
            return name;
74
    } 
75

    
76
    public String getVersion() {        
77
            return version;
78
    }    
79
    
80
    public ServiceInformation getServiceInformation() {        
81
        return serviceInfo;
82
    }  
83
    public String getHost ()
84
    {
85
            return host;
86
    }
87
    public void setHost(String _host)
88
    {
89
            host = _host;
90
    }
91
    public String getPort()
92
    {
93
            return port;
94
    }
95
    public void setPort(String _port)
96
    {
97
            port = _port;
98
    }
99

    
100
    /**
101
     * <p>Builds a GetMap request that is sent to the WMS
102
     * the response (image) will be redirect to the
103
     * WMS client</p>
104
     */
105
    
106
    public byte[] getMap(WMSStatus status) throws ServerErrorException, WMSException
107
    {        
108
            URL request = null;
109
                try
110
                {
111
                        //TODO:
112
                        //pass this buildXXXRequest to the WMSProtocolHandlerXXX: The request can depend on the WMS version.
113
                        request = new URL(buildMapRequest(status));
114
            System.out.println(request.toString());
115
                    byte[] imageBytes = null;
116
                    byte[] buffer = new byte[1024*256];
117
            InputStream is = request.openStream();
118
                    int readed = 0;
119
                    
120
                    for (int i = is.read(buffer); i>0; i = is.read(buffer)){
121
                // Creates a new buffer to contain the previous readed bytes and the next bunch of bytes
122
                            byte[] buffered = new byte[readed+i];
123
                            for (int j = 0; j < buffered.length; j++) {
124
                                    if (j<readed){
125
                        // puts the previously downloaded bytes into the image buffer
126
                                            buffered[j] = imageBytes[j];
127
                                    }
128
                                    else {
129
                        // appends the recently downloaded bytes to the image buffer.
130
                                            buffered[j] = buffer[j-readed];
131
                                    }
132
                                }
133
                            imageBytes = (byte[]) buffered.clone();
134
                            readed += i;
135
                            
136
                    }
137
            System.out.println(imageBytes);
138
                        if (Utilities.isTextData(imageBytes)){
139
                String exceptionMessage = parseException(imageBytes);
140
                if (exceptionMessage!=null)
141
                    throw new WMSException(exceptionMessage);
142
                throw new ServerErrorException();
143
            }
144
                        return imageBytes;
145
                    
146
                }
147
                catch(IOException e)
148
                {
149
                        e.printStackTrace();
150
            throw new ServerErrorException();
151
                }
152
    } 
153

    
154
        /**
155
     * Parses a WMS exception XML document.
156
     * @param imageBytes
157
     * @return
158
     */
159
    protected abstract String parseException(byte[] imageBytes) ;
160

    
161
    /**
162
         * <p>Builds a GetCapabilities request that is sent to the WMS
163
         * the response will be parse to extract the data needed by the
164
         * WMS client</p>
165
         */
166
    public void getCapabilities()
167
    {                
168
            URL request = null;
169
                try
170
                {
171
                        request = new URL(buildCapabilitiesRequest());
172
                }
173
                catch(Exception e)
174
                {
175
                        e.printStackTrace();
176
                }
177
                
178
//                   File f = null;
179
//                   f = new File("tochangethis.txt");
180
//            
181
//            if (!f.exists())
182
//            {
183
//                    try
184
//                    {
185
//                            DataOutputStream dos = new DataOutputStream( new BufferedOutputStream(new FileOutputStream(f)));
186
//                            byte[] buffer = new byte[1024*256];
187
//                            InputStream is = request.openStream();
188
//                            long readed = 0;
189
//                            for (int i = is.read(buffer); i>0; i = is.read(buffer)){
190
//                                    dos.write(buffer, 0, i);
191
//                                    readed += i;
192
//                            }
193
//                            dos.close();
194
//                    }
195
//                    catch(Exception e)
196
//                    {}
197
//            }
198
                try
199
                {
200
                File f = downloadFile(request,"wms_capabilities.xml");
201
            parse(f);
202
                } catch(Exception e)
203
                {
204
                        //TODO
205
                        e.printStackTrace();
206
                }
207
    }
208

    
209
/**
210
 * <p>It will send a GetFeatureInfo request to the WMS
211
 * Parsing the response and redirecting the info to the WMS client</p>
212
 */
213
    public String getFeatureInfo(WMSStatus status, int x, int y, int featureCount)
214
    {
215
            URL request = null;
216
            StringBuffer  output = new StringBuffer();
217
                try
218
                {
219
                        //TODO:
220
                        //pass this buildXXXRequest to the WMSProtocolHandlerXXX: The request can depend on the WMS version.
221
                        request = new URL(buildGetFeatureInfoRequest(status, x, y));
222
                }
223
                catch(Exception e)
224
                {
225
                        e.printStackTrace();
226
                }
227
                
228
            try
229
            {            
230
                    System.out.println(request.toString());
231
                    File f = new File("featureInfo.xml");
232
                    DataOutputStream dos = new DataOutputStream(new FileOutputStream(f));           
233
                    OutputStream bos = null;
234

    
235
                    byte[] buffer = new byte[1024*256];
236
                    InputStream is = request.openStream();
237
                    //long readed = 0;
238
                    for (int i = is.read(buffer); i>0; i = is.read(buffer)){
239
                            dos.write(buffer, 0, i);
240
                            output.append(buffer);
241
                            //readed += i;
242
                    }
243
                    dos.close();
244
                    
245
                    StringBuffer sb = new StringBuffer();
246
                    sb.append("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");
247
                    int tag;
248
                    KXmlParser kxmlParser = null;
249
                    kxmlParser = new KXmlParser();            
250
                    kxmlParser.setInput(new FileReader(f));                
251
                        tag = kxmlParser.nextTag();
252
                    if ( kxmlParser.getEventType() != KXmlParser.END_DOCUMENT ) 
253
                    {                    
254
                            //tag = kxmlParser.nextTag();
255
                                 while(tag != KXmlParser.END_DOCUMENT)
256
                                 {
257
                                         switch(tag)
258
                                         {
259
                                                case KXmlParser.START_TAG:                                                         
260
                                                        sb.append("<" + kxmlParser.getName() + ">\n");
261
                                                        break;
262
                                                case KXmlParser.END_TAG:        
263
                                                        sb.append("</" + kxmlParser.getName() + ">\n");
264
                                                        break;
265
                                                case KXmlParser.TEXT:
266
                                                        sb.append(kxmlParser.getText());                                                
267
                                                break;
268
                                         }
269
                                     tag = kxmlParser.next();
270
                             }
271
                    }        
272
                    System.out.println(sb.toString());
273
                return sb.toString();
274
            //return output.toString() ;
275
            }
276
            catch(Exception e)
277
            {
278
                    e.printStackTrace();
279
            return null;
280
            }
281
    }
282

    
283
    /**
284
     * Builds the GetCapabilitiesRequest according to the OGC WMS Specifications
285
     */
286
    private String buildCapabilitiesRequest()
287
    {
288
                String req = new String();
289
                String host = getHost();
290
//                if ((!host.endsWith("?"))&&(host.indexOf("?")==-1))                        
291
//                        req = req + getHost() + "?REQUEST=GetCapabilities&SERVICE=WMS&";
292
//                else
293
//                {
294
//                        String symbol = (host.endsWith("&")) ? "" : "&";
295
//                        req = req + getHost() + symbol + "REQUEST=GetCapabilities&SERVICE=WMS&";
296
//                }
297
                String symbol = (host.indexOf("?")==-1) ? "?" : "&";
298
                req = req + getHost() + symbol + "REQUEST=GetCapabilities&SERVICE=WMS&";
299
                req = req + "VERSION=" + getVersion();
300
                req += ("&EXCEPTIONS=XML");
301
                return req;
302
    }
303

    
304
    /**
305
     * Builds the GetFeatureInfoRequest according to the OGC WMS Specifications
306
     */
307
    private String buildGetFeatureInfoRequest(WMSStatus status, int x, int y)
308
    {
309
                String req = new String();
310
//                if (!host.endsWith("?"))
311
//                        req = req + getHost() + "?REQUEST=GetFeatureInfo&SERVICE=WMS&";
312
//                else
313
//                        req = req + getHost() + "REQUEST=GetFeatureInfo&SERVICE=WMS&";
314
                String symbol = (host.indexOf("?")==-1) ? "?" : "&";
315
                req = req + getHost() + symbol + "REQUEST=GetFeatureInfo&SERVICE=WMS&";
316
                req = req + "QUERY_LAYERS="+Utilities.Vector2CS(status.getLayerNames()); 
317
                req = req + "&VERSION=" + getVersion() + "&";
318
                req = req + "INFO_FORMAT=application/vnd.ogc.gml&";
319
                req = req + getPartialQuery(status);
320
                req = req + "&x="+x + "&y="+y;
321
       if (status.getExceptionFormat() != null) {
322
            req += ("&EXCEPTIONS=" + status.getExceptionFormat());
323
        } else {
324
            req += ("&EXCEPTIONS=XML");
325
        }
326
                return req;
327
    }    
328
    
329
    /**
330
     * Builds the GetMapRequest according to the OGC WMS Specifications
331
     */
332
    private String buildMapRequest(WMSStatus status)
333
    { 
334
                String req = new String();
335
//                if (!host.endsWith("?"))
336
//                        req = req + getHost() + "?REQUEST=GetMap&SERVICE=WMS&";
337
//                else
338
//                        req = req + getHost() + "REQUEST=GetMap&SERVICE=WMS&";
339
                String symbol = (host.indexOf("?")==-1) ? "?" : "&";
340
                req = req + getHost() + symbol + "REQUEST=GetMap&SERVICE=WMS&";
341
                req = req + "VERSION=" + getVersion() + "&";
342
                req = req + getPartialQuery(status);
343
       if (status.getExceptionFormat() != null) {
344
            req += ("&EXCEPTIONS=" + status.getExceptionFormat());
345
        } else {
346
            req += ("&EXCEPTIONS=XML");
347
        }
348
                return req;
349
    }
350

    
351
    /**
352
     * Gets the part of the OGC request that share GetMap and GetFeatureInfo
353
     * @return String request
354
     */
355
    public String getPartialQuery(WMSStatus status)
356
    {            
357
        String req = "LAYERS=" + Utilities.Vector2CS(status.getLayerNames()) + "&STYLES=" +
358
        Utilities.Vector2CS(status.getStyles()) + "&SRS=" + status.getSrs() +
359
            "&BBOX=" + status.getExtent().getMinX()+ "," +
360
                                    status.getExtent().getMinY()+ "," +
361
                                    status.getExtent().getMaxX()+ "," +
362
                                    status.getExtent().getMaxY() +
363
            "&WIDTH=" + status.getWidth() +
364
            "&HEIGHT=" + status.getHeight() + "&FORMAT=" + status.getFormat();
365

    
366
//        if (status.getTransparency()) {
367
//            req += "&TRANSPARENT=TRUE";
368
//        }
369
//
370
//        if (status.getBGColor() != null) {
371
//            req += ("&COLOR=" + status.getBGColor());
372
//        }
373
//
374
//        if (time != null) {
375
//            req += ("&TIME=" + time);
376
//        }
377
//
378
//        if (elevation != -1) {
379
//            req += ("&ELEVATION=" + elevation);
380
//        }
381

    
382
        return req.replaceAll(" ", "%20");
383
    }
384

    
385
    
386
    
387
    public void close() {        
388
        // your code here
389
    } 
390
    
391
    /**
392
     * Inner class that represents the description of the WMS metadata.
393
     * The first part of the capabilities will return the service information
394
     * from the WMS, this class will hold this information. 
395
     * 
396
     */
397
    public class ServiceInformation {
398

    
399
        public String online_resource;
400
        public String version;
401
        public String name;
402
        public String scope;
403
        public String title;
404
        public String abstr;
405
        public String keywords;
406
        public String fees;
407
        public String operationsInfo;
408
        public String personname;
409
        public String organization;
410
        public String function;
411
        public String addresstype;
412
        public String address;
413
        public String place;
414
        public String province;
415
        public String postcode;
416
        public String country;
417
        public String phone;
418
        public String fax;
419
        public String email;
420
        public Vector formats;
421
        
422
        public ServiceInformation()
423
        {
424
                online_resource = new String();
425
            version = new String();
426
            name = new String();
427
            scope = new String();
428
            title = new String();
429
            abstr = new String();
430
            keywords = new String();
431
            fees = new String();
432
            operationsInfo = new String();
433
            personname = new String();
434
            organization = new String();
435
            function = new String();
436
            addresstype = new String();
437
            address = new String();
438
            place = new String();
439
            province = new String();
440
            postcode = new String();
441
            country = new String();
442
            phone = new String();
443
            fax = new String();
444
            email = new String();
445
            formats = new Vector();               
446
        }
447
     }   
448
    
449
    /**
450
     * Downloads an URL into a temporary file that is removed the next time the 
451
     * tempFileManager class is called, which means the next time gvSIG is launched.
452
     * 
453
     * @param url
454
     * @param name
455
     * @return
456
     * @throws IOException
457
     * @throws ServerErrorResponseException
458
     * @throws ConnectException
459
     * @throws UnknownHostException
460
     */
461
    private File downloadFile(URL url, String name) throws IOException,ConnectException, UnknownHostException{
462
            File f = null;
463

    
464
            try{
465
                if ((f=Utilities.getPreviousDownloadedURL(url))==null){
466
                    f = TempFileManager.createTempFile(name, "tmp");
467
                    System.out.println("downloading '"+url.toString()+"' to: "+f.getAbsolutePath());
468
                    
469
                    f.deleteOnExit();
470
                DataOutputStream dos = new DataOutputStream( new BufferedOutputStream(new FileOutputStream(f)));
471
                byte[] buffer = new byte[1024*256];
472
                InputStream is = url.openStream();
473
                long readed = 0;
474
                for (int i = is.read(buffer); i>0; i = is.read(buffer)){
475
                    dos.write(buffer, 0, i);
476
                    readed += i;
477
                }
478
                dos.close();
479
                Utilities.addDownloadedURL(url, f.getAbsolutePath());
480
                }
481
            } catch (IOException io) {
482
                    io.printStackTrace();
483
            }
484
            
485
            return f;
486
        }
487

    
488
 }