Statistics
| Revision:

svn-gvsig-desktop / tags / Root_piloto3d / libraries / libRemoteServices / src / org / gvsig / remoteClient / wcs / WCSProtocolHandler.java @ 9537

History | View | Annotate | Download (13.8 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
     * @param override, if true the cache is ignored
87
     */
88
    public void getCapabilities(WCSStatus status, boolean override, ICancellable cancel) {
89
           URL request = null;
90
            try {
91
                request = new URL(buildCapabilitiesRequest(status));
92
            }
93
            catch(Exception e) {
94
                e.printStackTrace();
95
            }
96
            try {
97
                    if (override)
98
                                    Utilities.removeURL(request);
99
                    File f =  Utilities.downloadFile(request,"wcs_capabilities.xml", cancel);
100
                    if (f!=null)
101
                            parseCapabilities(f);
102
            } catch(Exception e) {
103
                    e.printStackTrace();
104
            }
105
    }
106

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

    
115
                String onlineResource;
116
                if (status == null || status.getOnlineResource() == null)
117
                        onlineResource = getHost();
118
                else
119
                        onlineResource = status.getOnlineResource();
120
                symbol = getSymbol(onlineResource);
121

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

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

    
137
                String onlineResource;
138
                if (status == null || status.getOnlineResource() == null)
139
                        onlineResource = getHost();
140
                else
141
                        onlineResource = status.getOnlineResource();
142

    
143

    
144
                symbol = getSymbol(onlineResource);
145

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

    
153
    /**
154
     * parses the data retrieved by the DescribeCoverage XML document
155
     */
156
    public abstract boolean parseDescribeCoverage(File f);
157

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

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

    
195
            File f = Utilities.downloadFile(request, "wcsGetCoverage", cancel);
196

    
197
            if (f!=null && Utilities.isTextFile(f)) {
198
                            FileInputStream fis = new FileInputStream(f);
199
                            FileChannel fc = fis.getChannel();
200
                            byte[] data = new byte[(int)fc.size()];   // fc.size returns the size of the file which backs the channel
201
                            ByteBuffer bb = ByteBuffer.wrap(data);
202
                            fc.read(bb);
203

    
204
                            WCSException wcsEx = null;
205

    
206
                    String exceptionMessage = parseException(data);
207
                if (exceptionMessage==null)
208
                {
209
                         String error = new String(data);
210
                        int pos = error.indexOf("<?xml");
211
                        if (pos!= -1)
212
                        {
213
                                String xml = error.substring(pos,error.length());
214
                                exceptionMessage = parseException(xml.getBytes());
215
                        }
216
                    if (exceptionMessage == null)
217
                            exceptionMessage = new String(data);
218

    
219
                }
220
                     wcsEx = new WCSException(exceptionMessage);
221
                    wcsEx.setWCSMessage(new String(data));
222

    
223
                    // Since it is an error file, It must be deleted from the cache
224
                    Utilities.removeURL(request);
225
                throw wcsEx;
226
            }
227
                        return f;
228
                }
229
                catch(IOException e)
230
                {
231
                        e.printStackTrace();
232
            throw new ServerErrorException();
233
                }
234
    }
235

    
236

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

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

    
289
        /**
290
     * Builds the GetMapRequest according to the OGC WCS Specifications
291
     */
292
    private String buildCoverageRequest(WCSStatus status)
293
    {
294
                StringBuffer req = new StringBuffer();
295
                String symbol = null;
296
                String onlineResource = null;
297

    
298
                if (status.getOnlineResource() == null)
299
                        onlineResource = getHost();
300
                else
301
                        onlineResource = status.getOnlineResource();
302
                symbol = getSymbol(onlineResource);
303

    
304
                req.append(onlineResource + symbol + "service=WCS&version=").append(getVersion()).append("&request=GetCoverage&");
305
                req.append(getPartialQuery(status));
306
                if (status.getExceptionFormat() != null) {
307
                        req.append("&EXCEPTIONS=" + status.getExceptionFormat());
308
                } else {
309
                        req.append("&EXCEPTIONS=XML");
310
                }
311
                return req.toString().replaceAll(" ", "%20");
312
    }
313

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

    
334
        return req.toString();
335
    }
336

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

    
352

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

    
369
        public ArrayList getFormats() {
370
                return new ArrayList(serviceInfo.formats);
371
        }
372

    
373
    public class ServiceInformation {
374

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

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

    
424
     }
425

    
426
        public Hashtable getLayers() {
427
                return layerPool;
428
        }
429
}