Statistics
| Revision:

root / trunk / libraries / libRemoteServices / src / org / gvsig / remoteClient / wms / WMSProtocolHandler.java @ 3655

History | View | Annotate | Download (13.8 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

    
291
        String symbol = getSymbol(host);
292
        req = req + getHost() + symbol + "REQUEST=GetCapabilities&SERVICE=WMS&";
293
                req = req + "VERSION=" + getVersion();
294
                req += ("&EXCEPTIONS=XML");
295
                return req;
296
    }
297

    
298
    /**
299
     * Builds the GetFeatureInfoRequest according to the OGC WMS Specifications
300
     */
301
    private String buildGetFeatureInfoRequest(WMSStatus status, int x, int y)
302
    {
303
                String req = new String();
304

    
305
        String symbol = getSymbol(host);
306
        
307
                req = req + getHost() + symbol + "REQUEST=GetFeatureInfo&SERVICE=WMS&";
308
                req = req + "QUERY_LAYERS="+Utilities.Vector2CS(status.getLayerNames()); 
309
                req = req + "&VERSION=" + getVersion() + "&";
310
                req = req + "INFO_FORMAT=application/vnd.ogc.gml&";
311
                req = req + getPartialQuery(status);
312
                req = req + "&x="+x + "&y="+y;
313
       if (status.getExceptionFormat() != null) {
314
            req += ("&EXCEPTIONS=" + status.getExceptionFormat());
315
        } else {
316
            req += ("&EXCEPTIONS=XML");
317
        }
318
                return req;
319
    }    
320

    
321
    /**
322
     * Builds the GetMapRequest according to the OGC WMS Specifications
323
     */
324
    private String buildMapRequest(WMSStatus status)
325
    { 
326
                String req = new String();
327

    
328
                String symbol = getSymbol(host);
329
                req = req + getHost() + symbol + "REQUEST=GetMap&SERVICE=WMS&";
330
                req = req + "VERSION=" + getVersion() + "&";
331
                req = req + getPartialQuery(status);
332
       if (status.getExceptionFormat() != null) {
333
            req += ("&EXCEPTIONS=" + status.getExceptionFormat());
334
        } else {
335
            req += ("&EXCEPTIONS=XML");
336
        }
337
                return req;
338
    }
339
    
340
    /**
341
     * Just for not repeat code. Gets the correct separator according to the server URL
342
     * @param h
343
     * @return
344
     */
345
    private String getSymbol(String h) {
346
        String symbol;
347
        if (h.indexOf("?")==-1) 
348
            symbol = "?";
349
        else if (h.indexOf("?")!=h.length()-1)
350
            symbol = "&";
351
        else
352
            symbol = "";
353
        return symbol;
354
    }
355

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

    
373
        if (status.getTransparency()) {
374
            req += "&TRANSPARENT=TRUE";
375
        }
376
//
377
//        if (status.getBGColor() != null) {
378
//            req += ("&COLOR=" + status.getBGColor());
379
//        }
380
//
381

    
382

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

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

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

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

    
489
 }