Statistics
| Revision:

svn-gvsig-desktop / trunk / libraries / libRemoteServices / src / org / gvsig / remoteClient / wcs / WCSProtocolHandler.java @ 7010

History | View | Annotate | Download (13.5 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 *
19
 * For more information, contact:
20
 *
21
 *  Generalitat Valenciana
22
 *   Conselleria d'Infraestructures i Transport
23
 *   Av. Blasco Ib??ez, 50
24
 *   46010 VALENCIA
25
 *   SPAIN
26
 *
27
 *      +34 963862235
28
 *   gvsig@gva.es
29
 *      www.gvsig.gva.es
30
 *
31
 *    or
32
 *
33
 *   IVER T.I. S.A
34
 *   Salamanca 50
35
 *   46005 Valencia
36
 *   Spain
37
 *
38
 *   +34 963163400
39
 *   dac@iver.es
40
 */
41
package org.gvsig.remoteClient.wcs;
42

    
43
import java.io.ByteArrayInputStream;
44
import java.io.File;
45
import java.io.FileInputStream;
46
import java.io.IOException;
47
import java.net.URL;
48
import java.nio.ByteBuffer;
49
import java.nio.channels.FileChannel;
50
import java.util.ArrayList;
51
import java.util.HashMap;
52
import java.util.Hashtable;
53
import java.util.Vector;
54

    
55
import org.gvsig.remoteClient.OGCProtocolHandler;
56
import org.gvsig.remoteClient.exceptions.ServerErrorException;
57
import org.gvsig.remoteClient.exceptions.WCSException;
58
import org.gvsig.remoteClient.utils.ExceptionTags;
59
import org.gvsig.remoteClient.utils.Utilities;
60
import org.gvsig.remoteClient.wms.ICancellable;
61
import org.kxml2.io.KXmlParser;
62
import org.xmlpull.v1.XmlPullParserException;
63
/**
64
 *
65
 * @author jaume
66
 *
67
 */
68
public abstract class WCSProtocolHandler extends OGCProtocolHandler{
69
        /**
70
         * Encoding used to parse different xml documents.
71
         */
72
        protected String encoding = "UTF-8";
73
        protected Hashtable layerPool = new Hashtable();
74

    
75
        /**
76
     * WCS metadata
77
     */
78
    protected ServiceInformation serviceInfo = new ServiceInformation();
79

    
80
    /**
81
     * <p>
82
     * Builds a GetCapabilities request that is sent to the WCS
83
     * the response will be parse to extract the data needed by the
84
     * WCS client.
85
     * </p>
86
     */
87
    public void getCapabilities(WCSStatus status, ICancellable cancel) {
88
           URL request = null;
89
            try {
90
                request = new URL(buildCapabilitiesRequest(status));
91
            }
92
            catch(Exception e) {
93
                e.printStackTrace();
94
            }
95
            try {
96
                    File f =  Utilities.downloadFile(request,"wcs_capabilities.xml", cancel);
97
                    if (f!=null)
98
                            parseCapabilities(f);
99
            } catch(Exception e) {
100
                    e.printStackTrace();
101
            }
102
    }
103

    
104
    /**
105
     * Builds a complete URL-string that can be used to send a GetCapabilities request.
106
     * @return String
107
     */
108
    private String buildCapabilitiesRequest(WCSStatus status) {
109
            StringBuffer req = new StringBuffer();
110
                String symbol = null;
111

    
112
                String onlineResource;
113
                if (status == null || status.getOnlineResource() == null)
114
                        onlineResource = getHost();
115
                else
116
                        onlineResource = status.getOnlineResource();
117
                symbol = getSymbol(onlineResource);
118

    
119
                req.append(onlineResource).append(symbol).append("REQUEST=GetCapabilities&SERVICE=WCS&");
120
                req.append("VERSION=").append(getVersion()).append("&EXCEPTIONS=XML");
121
                return req.toString();
122
    }
123

    
124
    /**
125
     * Builds a complete URL-string that can be used to send a DescribeCoverage request.
126
     * If status is null, then default settings are used.
127
     * @param WCSStatus
128
     * @return String
129
     */
130
    private String buildDescribeCoverageRequest(WCSStatus status) {
131
            StringBuffer req = new StringBuffer();
132
                String symbol = null;
133

    
134
                String onlineResource;
135
                if (status == null || status.getOnlineResource() == null)
136
                        onlineResource = getHost();
137
                else
138
                        onlineResource = status.getOnlineResource();
139

    
140

    
141
                symbol = getSymbol(onlineResource);
142

    
143
                req.append(onlineResource).append(symbol).append("REQUEST=DescribeCoverage&SERVICE=WCS&");
144
                if (status != null && status.getCoverageName()!= null)
145
                        req.append("COVERAGE="+status.getCoverageName()+"&");
146
                req.append("VERSION=").append(getVersion()).append("&EXCEPTIONS=XML");
147
                return req.toString();
148
    }
149

    
150
    /**
151
     * parses the data retrieved by the DescribeCoverage XML document
152
     */
153
    public abstract boolean parseDescribeCoverage(File f);
154

    
155
    /**
156
     * Send a DescribeCoverage request using the settings passed in the status argument.
157
     * If status is null, then default settings are used.
158
     * @return String
159
     */
160
    public void describeCoverage(WCSStatus status, ICancellable cancel) {
161
        URL request = null;
162
        try {
163
            request = new URL(buildDescribeCoverageRequest(status));
164
        }
165
        catch(Exception e) {
166
            e.printStackTrace();
167
        }
168
        try {
169
                File f = Utilities.downloadFile(request, "wcs_describeCoverage.xml", cancel);
170
                if (f!=null)
171
                        parseDescribeCoverage(f);
172
        } catch(Exception e) {
173
                e.printStackTrace();
174
        }
175
    }
176

    
177
    /**
178
     * Send a GetCoverage request using the settings passed in the status.
179
     * @return String
180
     */
181
    public File getCoverage(WCSStatus status, ICancellable cancel) throws ServerErrorException, WCSException {
182
            URL request = null;
183
                try
184
                {
185
                        //TODO:
186
                        //pass this buildXXXRequest to the WCSProtocolHandlerXXX: The request can depend on the WCS version.
187
                        request = new URL(buildCoverageRequest(status));
188

    
189
            File f = Utilities.downloadFile(request, "wcsGetCoverage", cancel);
190

    
191
            if (f!=null && Utilities.isTextFile(f)) {
192
                            FileInputStream fis = new FileInputStream(f);
193
                            FileChannel fc = fis.getChannel();
194
                            byte[] data = new byte[(int)fc.size()];   // fc.size returns the size of the file which backs the channel
195
                            ByteBuffer bb = ByteBuffer.wrap(data);
196
                            fc.read(bb);
197

    
198
                            WCSException wcsEx = null;
199

    
200
                    String exceptionMessage = parseException(data);
201
                if (exceptionMessage==null)
202
                {
203
                         String error = new String(data);
204
                        int pos = error.indexOf("<?xml");
205
                        if (pos!= -1)
206
                        {
207
                                String xml = error.substring(pos,error.length());
208
                                exceptionMessage = parseException(xml.getBytes());
209
                        }
210
                    if (exceptionMessage == null)
211
                            exceptionMessage = new String(data);
212

    
213
                }
214
                     wcsEx = new WCSException(exceptionMessage);
215
                    wcsEx.setWCSMessage(new String(data));
216

    
217
                    // Since it is an error file, It must be deleted from the cache
218
                    Utilities.removeURL(request);
219
                throw wcsEx;
220
            }
221
                        return f;
222
                }
223
                catch(IOException e)
224
                {
225
                        e.printStackTrace();
226
            throw new ServerErrorException();
227
                }
228
    }
229

    
230

    
231
    /**
232
     * Parses the WCS Exception document.
233
     * @param bytes, byte[]
234
     * @return
235
     */
236
    private String parseException(byte[] data) {
237
            // TODO: a?? est? fusilat del WMS, comprovar que funciona.
238
            ArrayList errors = new ArrayList();
239
        KXmlParser kxmlParser = new KXmlParser();
240
        try
241
        {
242
            kxmlParser.setInput(new ByteArrayInputStream(data), encoding);
243
            kxmlParser.nextTag();
244
            int tag;
245
            if ( kxmlParser.getEventType() != KXmlParser.END_DOCUMENT )
246
            {
247
                kxmlParser.require(KXmlParser.START_TAG, null, ExceptionTags.EXCEPTION_ROOT);
248
                tag = kxmlParser.nextTag();
249
                 while(tag != KXmlParser.END_DOCUMENT)
250
                 {
251
                     switch(tag)
252
                     {
253
                        case KXmlParser.START_TAG:
254
                            if (kxmlParser.getName().compareTo(ExceptionTags.SERVICE_EXCEPTION)==0){
255
                                String errorCode = kxmlParser.getAttributeValue("", ExceptionTags.CODE);
256
                                errorCode = (errorCode != null) ? "["+errorCode+"] " : "";
257
                                String errorMessage = kxmlParser.nextText();
258
                                errors.add(errorCode+errorMessage);
259
                            }
260
                            break;
261
                        case KXmlParser.END_TAG:
262
                            break;
263

    
264
                     }
265
                     tag = kxmlParser.nextTag();
266
                 }
267
                 //kxmlParser.require(KXmlParser.END_DOCUMENT, null, null);
268
            }
269
        }
270
        catch(XmlPullParserException parser_ex){
271
            parser_ex.printStackTrace();
272
        }
273
        catch (IOException ioe) {
274
            ioe.printStackTrace();
275
        }
276
        String message = errors.size()>0? "" : null;
277
        for (int i = 0; i < errors.size(); i++) {
278
            message += (String) errors.get(i)+"\n";
279
        }
280
        return message;
281
        }
282

    
283
        /**
284
     * Builds the GetMapRequest according to the OGC WCS Specifications
285
     */
286
    private String buildCoverageRequest(WCSStatus status)
287
    {
288
                StringBuffer req = new StringBuffer();
289
                String symbol = null;
290
                String onlineResource = null;
291

    
292
                if (status.getOnlineResource() == null)
293
                        onlineResource = getHost();
294
                else
295
                        onlineResource = status.getOnlineResource();
296
                symbol = getSymbol(onlineResource);
297

    
298
                req.append(onlineResource + symbol + "service=WCS&version=").append(getVersion()).append("&request=GetCoverage&");
299
                req.append(getPartialQuery(status));
300
                if (status.getExceptionFormat() != null) {
301
                        req.append("&EXCEPTIONS=" + status.getExceptionFormat());
302
                } else {
303
                        req.append("&EXCEPTIONS=XML");
304
                }
305
                return req.toString().replaceAll(" ", "%20");
306
    }
307

    
308
    /**
309
     * Gets the part of the OGC request that share GetMap and GetFeatureInfo
310
     * @return String request
311
     */
312
    public String getPartialQuery(WCSStatus status)
313
    {
314
        StringBuffer req = new StringBuffer();
315
        req.append( (status.getTime() != null) ? "TIME="+status.getTime() : "" )
316
           .append( "&COVERAGE=" + status.getCoverageName())
317
           .append ("&CRS=" + status.getSrs())
318
           .append( "&FORMAT=" + status.getFormat() )
319
           .append( "&HEIGHT=" + status.getHeight())
320
           .append( "&WIDTH=" + status.getWidth())
321
           .append( (status.getDepth() != null) ? "&DEPTH="+status.getDepth() : "" )
322
           .append( "&BBOX=" + status.getExtent().getMinX()+ "," )
323
           .append( status.getExtent().getMinY()+ ",")
324
           .append( status.getExtent().getMaxX()+ ",")
325
           .append( status.getExtent().getMaxY())
326
           .append( (status.getParameters() != null) ? "&"+status.getParameters() : "");
327

    
328
        return req.toString();
329
    }
330

    
331
    /**
332
     * Builds the GetCapabilitiesRequest according to the OGC WCS Specifications
333
     * without a VERSION, to get the highest version than a WCS supports.
334
     */
335
    public static String buildCapabilitiesSuitableVersionRequest(String _host, String _version) {
336
                String req = new String();
337
        String symbol = getSymbol(_host);
338
        req = req + _host + symbol + "REQUEST=GetCapabilities&SERVICE=WCS&";
339
        if((_version != null) && (_version.length()>0 )) {
340
                req += ("&VERSION=" + _version);
341
        }
342
                req += ("&EXCEPTIONS=XML");
343
                return req.toString().replaceAll(" ", "%20");
344
    }
345

    
346

    
347
    /**
348
     * Just for not repeat code. Gets the correct separator according to the server URL
349
     * @param h
350
     * @return
351
     */
352
    private static String getSymbol(String h) {
353
        String symbol;
354
        if (h.indexOf("?")==-1)
355
            symbol = "?";
356
        else if (h.indexOf("?")!=h.length()-1)
357
            symbol = "&";
358
        else
359
            symbol = "";
360
        return symbol;
361
    }
362

    
363
        public ArrayList getFormats() {
364
                return new ArrayList(serviceInfo.formats);
365
        }
366

    
367
    public class ServiceInformation {
368

    
369
        public String online_resource = null;
370
        public String version;
371
        public String name;
372
        public String scope;
373
        public String title;
374
        public String abstr;
375
        public String keywords;
376
        public String fees;
377
        public String operationsInfo;
378
        public String personname;
379
        public String organization;
380
        public String function;
381
        public String addresstype;
382
        public String address;
383
        public String place;
384
        public String province;
385
        public String postcode;
386
        public String country;
387
        public String phone;
388
        public String fax;
389
        public String email;
390
        public Vector formats;
391
        public HashMap operations; // operations that WCS supports
392

    
393
        public ServiceInformation()
394
        {
395
            version = new String();
396
            name = new String();
397
            scope = new String();
398
            title = new String();
399
            abstr = new String();
400
            keywords = new String();
401
            fees = new String();
402
            operationsInfo = new String();
403
            personname = new String();
404
            organization = new String();
405
            function = new String();
406
            addresstype = new String();
407
            address = new String();
408
            place = new String();
409
            province = new String();
410
            postcode = new String();
411
            country = new String();
412
            phone = new String();
413
            fax = new String();
414
            email = new String();
415
            operations = new HashMap();
416
        }
417

    
418
     }
419

    
420
        public Hashtable getLayers() {
421
                return layerPool;
422
        }
423
}