Statistics
| Revision:

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

History | View | Annotate | Download (13.8 KB)

1 3483 jaume
/* 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 4924 jaume
import java.io.ByteArrayInputStream;
44 3483 jaume
import java.io.File;
45 4493 jaume
import java.io.FileInputStream;
46
import java.io.IOException;
47 3483 jaume
import java.net.URL;
48 4493 jaume
import java.nio.ByteBuffer;
49
import java.nio.channels.FileChannel;
50 4427 jaume
import java.util.ArrayList;
51 4222 jaume
import java.util.HashMap;
52 4427 jaume
import java.util.Hashtable;
53 4222 jaume
import java.util.Vector;
54 3483 jaume
55
import org.gvsig.remoteClient.OGCProtocolHandler;
56 4493 jaume
import org.gvsig.remoteClient.exceptions.ServerErrorException;
57
import org.gvsig.remoteClient.exceptions.WCSException;
58 4924 jaume
import org.gvsig.remoteClient.utils.ExceptionTags;
59 4493 jaume
import org.gvsig.remoteClient.utils.Utilities;
60 5409 jaume
import org.gvsig.remoteClient.wms.ICancellable;
61 4924 jaume
import org.kxml2.io.KXmlParser;
62
import org.xmlpull.v1.XmlPullParserException;
63 3483 jaume
/**
64 7010 jaume
 *
65 3483 jaume
 * @author jaume
66
 *
67
 */
68
public abstract class WCSProtocolHandler extends OGCProtocolHandler{
69 4500 jaume
        /**
70
         * Encoding used to parse different xml documents.
71
         */
72
        protected String encoding = "UTF-8";
73 4427 jaume
        protected Hashtable layerPool = new Hashtable();
74 7010 jaume
75 4924 jaume
        /**
76 3483 jaume
     * WCS metadata
77
     */
78 4222 jaume
    protected ServiceInformation serviceInfo = new ServiceInformation();
79 7010 jaume
80 3483 jaume
    /**
81 4924 jaume
     * <p>
82
     * Builds a GetCapabilities request that is sent to the WCS
83 3483 jaume
     * the response will be parse to extract the data needed by the
84 4924 jaume
     * WCS client.
85
     * </p>
86 9048 jaume
     * @param override, if true the cache is ignored
87 3483 jaume
     */
88 9048 jaume
    public void getCapabilities(WCSStatus status, boolean override, ICancellable cancel) {
89 3483 jaume
           URL request = null;
90 4427 jaume
            try {
91
                request = new URL(buildCapabilitiesRequest(status));
92 3483 jaume
            }
93 4427 jaume
            catch(Exception e) {
94 3483 jaume
                e.printStackTrace();
95
            }
96 4427 jaume
            try {
97 9048 jaume
                    if (override)
98
                                    Utilities.removeURL(request);
99 5409 jaume
                    File f =  Utilities.downloadFile(request,"wcs_capabilities.xml", cancel);
100
                    if (f!=null)
101
                            parseCapabilities(f);
102 4427 jaume
            } catch(Exception e) {
103
                    e.printStackTrace();
104 3483 jaume
            }
105
    }
106 7010 jaume
107 3483 jaume
    /**
108 4924 jaume
     * Builds a complete URL-string that can be used to send a GetCapabilities request.
109
     * @return String
110 3483 jaume
     */
111 4427 jaume
    private String buildCapabilitiesRequest(WCSStatus status) {
112
            StringBuffer req = new StringBuffer();
113
                String symbol = null;
114 7010 jaume
115 4427 jaume
                String onlineResource;
116
                if (status == null || status.getOnlineResource() == null)
117
                        onlineResource = getHost();
118 7010 jaume
                else
119 4427 jaume
                        onlineResource = status.getOnlineResource();
120
                symbol = getSymbol(onlineResource);
121 7010 jaume
122 4427 jaume
                req.append(onlineResource).append(symbol).append("REQUEST=GetCapabilities&SERVICE=WCS&");
123
                req.append("VERSION=").append(getVersion()).append("&EXCEPTIONS=XML");
124
                return req.toString();
125 3483 jaume
    }
126 4427 jaume
127 4924 jaume
    /**
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 4427 jaume
    private String buildDescribeCoverageRequest(WCSStatus status) {
134
            StringBuffer req = new StringBuffer();
135
                String symbol = null;
136 7010 jaume
137 4427 jaume
                String onlineResource;
138
                if (status == null || status.getOnlineResource() == null)
139
                        onlineResource = getHost();
140 7010 jaume
                else
141 4427 jaume
                        onlineResource = status.getOnlineResource();
142 7010 jaume
143
144 4427 jaume
                symbol = getSymbol(onlineResource);
145 7010 jaume
146 4427 jaume
                req.append(onlineResource).append(symbol).append("REQUEST=DescribeCoverage&SERVICE=WCS&");
147 7010 jaume
                if (status != null && status.getCoverageName()!= null)
148
                        req.append("COVERAGE="+status.getCoverageName()+"&");
149 4427 jaume
                req.append("VERSION=").append(getVersion()).append("&EXCEPTIONS=XML");
150
                return req.toString();
151
    }
152
153 3483 jaume
    /**
154
     * parses the data retrieved by the DescribeCoverage XML document
155
     */
156 4222 jaume
    public abstract boolean parseDescribeCoverage(File f);
157 7010 jaume
158 4924 jaume
    /**
159
     * Send a DescribeCoverage request using the settings passed in the status argument.
160
     * If status is null, then default settings are used.
161 9048 jaume
     * @param override
162 4924 jaume
     * @return String
163
     */
164 9048 jaume
    public void describeCoverage(WCSStatus status, boolean override, ICancellable cancel) {
165 4427 jaume
        URL request = null;
166
        try {
167
            request = new URL(buildDescribeCoverageRequest(status));
168
        }
169
        catch(Exception e) {
170
            e.printStackTrace();
171
        }
172
        try {
173 9048 jaume
                if (override)
174
                                Utilities.removeURL(request);
175 5409 jaume
                File f = Utilities.downloadFile(request, "wcs_describeCoverage.xml", cancel);
176
                if (f!=null)
177
                        parseDescribeCoverage(f);
178 4427 jaume
        } catch(Exception e) {
179
                e.printStackTrace();
180
        }
181 3483 jaume
    }
182 7010 jaume
183 4924 jaume
    /**
184
     * Send a GetCoverage request using the settings passed in the status.
185
     * @return String
186
     */
187 5409 jaume
    public File getCoverage(WCSStatus status, ICancellable cancel) throws ServerErrorException, WCSException {
188 4493 jaume
            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 7010 jaume
195
            File f = Utilities.downloadFile(request, "wcsGetCoverage", cancel);
196
197 5409 jaume
            if (f!=null && Utilities.isTextFile(f)) {
198 4493 jaume
                            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 7010 jaume
204 4493 jaume
                            WCSException wcsEx = null;
205 7010 jaume
206 4493 jaume
                    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 7010 jaume
                        }
216 4493 jaume
                    if (exceptionMessage == null)
217
                            exceptionMessage = new String(data);
218 7010 jaume
219 4493 jaume
                }
220
                     wcsEx = new WCSException(exceptionMessage);
221
                    wcsEx.setWCSMessage(new String(data));
222 7010 jaume
223 4493 jaume
                    // Since it is an error file, It must be deleted from the cache
224 5409 jaume
                    Utilities.removeURL(request);
225 4493 jaume
                throw wcsEx;
226
            }
227 7010 jaume
                        return f;
228 4493 jaume
                }
229
                catch(IOException e)
230
                {
231
                        e.printStackTrace();
232
            throw new ServerErrorException();
233
                }
234 7010 jaume
    }
235
236
237 4924 jaume
    /**
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 7010 jaume
            kxmlParser.setInput(new ByteArrayInputStream(data), encoding);
249 4924 jaume
            kxmlParser.nextTag();
250
            int tag;
251 7010 jaume
            if ( kxmlParser.getEventType() != KXmlParser.END_DOCUMENT )
252
            {
253
                kxmlParser.require(KXmlParser.START_TAG, null, ExceptionTags.EXCEPTION_ROOT);
254 4924 jaume
                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 7010 jaume
                        case KXmlParser.END_TAG:
268 4924 jaume
                            break;
269 7010 jaume
270 4924 jaume
                     }
271
                     tag = kxmlParser.nextTag();
272
                 }
273
                 //kxmlParser.require(KXmlParser.END_DOCUMENT, null, null);
274
            }
275
        }
276 7010 jaume
        catch(XmlPullParserException parser_ex){
277 4924 jaume
            parser_ex.printStackTrace();
278
        }
279 7010 jaume
        catch (IOException ioe) {
280
            ioe.printStackTrace();
281 4924 jaume
        }
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 4493 jaume
        }
288
289
        /**
290
     * Builds the GetMapRequest according to the OGC WCS Specifications
291
     */
292
    private String buildCoverageRequest(WCSStatus status)
293 7010 jaume
    {
294 4493 jaume
                StringBuffer req = new StringBuffer();
295
                String symbol = null;
296
                String onlineResource = null;
297 7010 jaume
298 4493 jaume
                if (status.getOnlineResource() == null)
299
                        onlineResource = getHost();
300 7010 jaume
                else
301 4493 jaume
                        onlineResource = status.getOnlineResource();
302
                symbol = getSymbol(onlineResource);
303 7010 jaume
304 4606 jaume
                req.append(onlineResource + symbol + "service=WCS&version=").append(getVersion()).append("&request=GetCoverage&");
305 4493 jaume
                req.append(getPartialQuery(status));
306 4606 jaume
                if (status.getExceptionFormat() != null) {
307
                        req.append("&EXCEPTIONS=" + status.getExceptionFormat());
308
                } else {
309
                        req.append("&EXCEPTIONS=XML");
310
                }
311 4493 jaume
                return req.toString().replaceAll(" ", "%20");
312 3483 jaume
    }
313 7010 jaume
314 4293 jaume
    /**
315 4493 jaume
     * Gets the part of the OGC request that share GetMap and GetFeatureInfo
316
     * @return String request
317
     */
318
    public String getPartialQuery(WCSStatus status)
319 7010 jaume
    {
320 4493 jaume
        StringBuffer req = new StringBuffer();
321 4606 jaume
        req.append( (status.getTime() != null) ? "TIME="+status.getTime() : "" )
322
           .append( "&COVERAGE=" + status.getCoverageName())
323 8765 jjdelcerro
           .append( "&CRS=" + status.getSrs())
324 4606 jaume
           .append( "&FORMAT=" + status.getFormat() )
325
           .append( "&HEIGHT=" + status.getHeight())
326
           .append( "&WIDTH=" + status.getWidth())
327 4925 jaume
           .append( (status.getDepth() != null) ? "&DEPTH="+status.getDepth() : "" )
328 4606 jaume
           .append( "&BBOX=" + status.getExtent().getMinX()+ "," )
329
           .append( status.getExtent().getMinY()+ ",")
330
           .append( status.getExtent().getMaxX()+ ",")
331
           .append( status.getExtent().getMaxY())
332 4493 jaume
           .append( (status.getParameters() != null) ? "&"+status.getParameters() : "");
333 7010 jaume
334 4493 jaume
        return req.toString();
335
    }
336 7010 jaume
337 4493 jaume
    /**
338 4427 jaume
     * Builds the GetCapabilitiesRequest according to the OGC WCS Specifications
339
     * without a VERSION, to get the highest version than a WCS supports.
340 4293 jaume
     */
341
    public static String buildCapabilitiesSuitableVersionRequest(String _host, String _version) {
342 7010 jaume
                String req = new String();
343 4293 jaume
        String symbol = getSymbol(_host);
344 7010 jaume
        req = req + _host + symbol + "REQUEST=GetCapabilities&SERVICE=WCS&";
345 4293 jaume
        if((_version != null) && (_version.length()>0 )) {
346
                req += ("&VERSION=" + _version);
347
        }
348
                req += ("&EXCEPTIONS=XML");
349 7010 jaume
                return req.toString().replaceAll(" ", "%20");
350 4293 jaume
    }
351 7010 jaume
352
353 4293 jaume
    /**
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 7010 jaume
        if (h.indexOf("?")==-1)
361 4293 jaume
            symbol = "?";
362
        else if (h.indexOf("?")!=h.length()-1)
363
            symbol = "&";
364
        else
365
            symbol = "";
366
        return symbol;
367
    }
368 7010 jaume
369 4931 jaume
        public ArrayList getFormats() {
370
                return new ArrayList(serviceInfo.formats);
371
        }
372
373 4222 jaume
    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 4241 jaume
        public HashMap operations; // operations that WCS supports
398 7010 jaume
399 4222 jaume
        public ServiceInformation()
400 7010 jaume
        {
401 4222 jaume
            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 7010 jaume
            operations = new HashMap();
422 4222 jaume
        }
423 4241 jaume
424 4427 jaume
     }
425
426
        public Hashtable getLayers() {
427
                return layerPool;
428 7010 jaume
        }
429 3483 jaume
}