Statistics
| Revision:

svn-gvsig-desktop / tags / v2_0_0_Build_2059 / libraries / libRemoteServices / src / org / gvsig / remoteclient / wcs / WCSProtocolHandler.java @ 39318

History | View | Annotate | Download (12.3 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.IOException;
46
import java.net.MalformedURLException;
47
import java.net.URL;
48
import java.util.ArrayList;
49
import java.util.Hashtable;
50
import java.util.StringTokenizer;
51

    
52
import org.gvsig.compat.CompatLocator;
53
import org.gvsig.compat.lang.StringUtils;
54
import org.gvsig.compat.net.ICancellable;
55
import org.gvsig.remoteclient.exceptions.ServerErrorException;
56
import org.gvsig.remoteclient.exceptions.WCSException;
57
import org.gvsig.remoteclient.exceptions.WMSException;
58
import org.gvsig.remoteclient.ogc.OGCProtocolHandler;
59
import org.gvsig.remoteclient.ogc.OGCServiceInformation;
60
import org.gvsig.remoteclient.utils.CapabilitiesTags;
61
import org.gvsig.remoteclient.utils.ExceptionTags;
62
import org.gvsig.remoteclient.utils.Utilities;
63
import org.gvsig.remoteclient.wcs.request.WCSDescribeCoverageRequest;
64
import org.gvsig.remoteclient.wcs.request.WCSGetCoverageRequest;
65
import org.kxml2.io.KXmlParser;
66
import org.xmlpull.v1.XmlPullParserException;
67
/**
68
 *
69
 * @author jaume
70
 *
71
 */
72
public abstract class WCSProtocolHandler extends OGCProtocolHandler {
73
        /**
74
         * Encoding used to parse different xml documents.
75
         */
76
        protected String encoding = "UTF-8";
77
        protected Hashtable layerPool = new Hashtable();
78

    
79
        /**
80
     * WCS metadata
81
     */
82
    protected WCSServiceInformation serviceInfo = new WCSServiceInformation();
83
    
84
    private static final StringUtils stringUtils = CompatLocator.getStringUtils();
85

    
86
        /*
87
         * (non-Javadoc)
88
         * @see org.gvsig.remoteClient.OGCProtocolHandler#setHost(java.lang.String)
89
         */
90
        public void setHost(String host) {
91
                try {
92
                        // Validates the URL if doesn't produces an exception
93
                        new URL(host);
94

    
95
                        int index = host.indexOf("?");
96
                        
97
                        if (index == -1)
98
                                super.setHost(host);
99
                        else
100
                                super.setHost(host.substring(0, index));
101
                }
102
                catch (MalformedURLException m) {
103
                        // Bad URL -> hold it
104
                        super.setHost(host);
105
                }
106
        }
107

    
108
        /**
109
     * <p>
110
     * Builds a GetCapabilities request that is sent to the WCS
111
     * the response will be parse to extract the data needed by the
112
     * WCS client.
113
     * </p>
114
     * @param override, if true the cache is ignored
115
     */
116
    public void getCapabilities(WCSStatus status, boolean override, ICancellable cancel) {
117
           URL request = null;
118
            try {
119
                request = new URL(buildCapabilitiesRequest(status));
120
            }
121
            catch(Exception e) {
122
                e.printStackTrace();
123
            }
124
            try {
125
                    if (override)
126
                        downloader.removeURL(request);
127
                    File f =  downloader.downloadFile(request,"wcs_capabilities.xml", cancel);
128
                    if (f!=null)
129
                            parseCapabilities(f);
130
            } catch(Exception e) {
131
                    e.printStackTrace();
132
            }
133
    }
134

    
135
    /**
136
     * Builds a complete URL-string that can be used to send a GetCapabilities request.
137
     * @return String
138
     */
139
    private String buildCapabilitiesRequest(WCSStatus status) {
140
            StringBuffer req = new StringBuffer();
141
                String symbol = null;
142

    
143
                String onlineResource;
144
                if (status == null || status.getOnlineResource() == null)
145
                        onlineResource = getHost();
146
                else
147
                        onlineResource = status.getOnlineResource();
148
                symbol = getSymbol(onlineResource);
149

    
150
                req.append(onlineResource).append(symbol).append("REQUEST=GetCapabilities&SERVICE=WCS&");
151
                req.append("VERSION=").append(getVersion()).append("&EXCEPTIONS=XML");
152
                return req.toString();
153
    }
154

    
155

    
156

    
157
    /**
158
     * parses the data retrieved by the DescribeCoverage XML document
159
     */
160
    public abstract boolean parseDescribeCoverage(File f);
161

    
162
    /**
163
     * Send a DescribeCoverage request using the settings passed in the status argument.
164
     * If status is null, then default settings are used.
165
     * @param override
166
     * @return String
167
     */
168
    public void describeCoverage(WCSStatus status, boolean override, ICancellable cancel) {
169
       try {
170
               WCSDescribeCoverageRequest request = createDescribeCoverageRequest(status);
171
           File f = request.sendRequest(cancel);
172
                if (f!=null)
173
                        parseDescribeCoverage(f);
174
        } catch(Exception e) {
175
                e.printStackTrace();
176
        }
177
    }
178

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

    
191
            if (f!=null && Utilities.isTextFile(f)) {
192
                byte[] data = fileToBytes(f);
193

    
194
                            WCSException wcsEx = null;
195

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

    
209
                }
210
                     wcsEx = new WCSException(exceptionMessage);
211
                    wcsEx.setWCSMessage(new String(data));
212

    
213
                    // Since it is an error file, It must be deleted from the cache
214
                    downloader.removeURL(request);
215
                throw wcsEx;
216
            }
217
                        return f;
218
                }
219
                catch(IOException e)
220
                {
221
                        e.printStackTrace();
222
            throw new ServerErrorException();
223
                }
224
    }
225
    
226
    public URL getCoverageURL(WCSStatus status, ICancellable cancel) throws ServerErrorException, WMSException {
227
            try {
228
                        WCSGetCoverageRequest request = createGetCoverageRequest(status);
229
                        return request.getURL();
230
                } catch(IOException e) {
231
                        e.printStackTrace();
232
            throw new ServerErrorException();
233
                }
234
    }
235
    
236
    /**
237
     * Returns the exception message if the file is a XML instead of a image.
238
     * @param file3
239
     * @return
240
     * @throws IOException 
241
     */
242
    public String getExceptionMessage(File f) throws IOException {
243
            if (f == null)
244
                    return null;
245
            
246
        if (Utilities.isTextFile(f)) {
247
            byte[] data = fileToBytes(f);
248

    
249
                String exceptionMessage = parseException(data);
250
            if (exceptionMessage == null) {
251
                     String error = new String(data);
252
                    int pos = error.indexOf("<?xml");
253
                    if (pos!= -1) {
254
                            String xml = error.substring(pos,error.length());
255
                            exceptionMessage = parseException(xml.getBytes());
256
                    }
257
                if (exceptionMessage == null)
258
                        exceptionMessage = new String(data);
259
            }
260
                 return exceptionMessage;
261
        }
262
        return null;
263
    }
264

    
265
    /**
266
     * Parses the WCS Exception document.
267
     * @param bytes, byte[]
268
     * @return
269
     */
270
    private String parseException(byte[] data) {
271
            // TODO: a?? est? fusilat del WMS, comprovar que funciona.
272
            ArrayList errors = new ArrayList();
273
        KXmlParser kxmlParser = new KXmlParser();
274
        boolean end = false;
275
        try
276
        {
277
            kxmlParser.setInput(new ByteArrayInputStream(data), encoding);
278
            kxmlParser.nextTag();
279
            int tag;
280
            if ( kxmlParser.getEventType() != KXmlParser.END_DOCUMENT )
281
            {
282
                kxmlParser.require(KXmlParser.START_TAG, null, ExceptionTags.EXCEPTION_ROOT);
283
                tag = kxmlParser.nextTag();
284
                 while(!end)
285
                 {
286
                     switch(tag)
287
                     {
288
                        case KXmlParser.START_TAG:
289
                            if (kxmlParser.getName().compareTo(ExceptionTags.SERVICE_EXCEPTION)==0){
290
                                String errorCode = kxmlParser.getAttributeValue("", ExceptionTags.CODE);
291
                                errorCode = (errorCode != null) ? "["+errorCode+"] " : "";
292
                                String errorMessage = kxmlParser.nextText();
293
                                errors.add(errorCode+errorMessage);
294
                            }
295
                            break;
296
                        case KXmlParser.END_TAG:
297
                                 if (kxmlParser.getName().compareTo(ExceptionTags.SERVICE_EXCEPTION) == 0 ||
298
                                                 kxmlParser.getName().compareTo(ExceptionTags.EXCEPTION_ROOT) == 0)
299
                                 end = true;
300
                            break;
301

    
302
                     }
303
                     if (!end)
304
                             tag = kxmlParser.nextTag();
305
                 }
306
                 //kxmlParser.require(KXmlParser.END_DOCUMENT, null, null);
307
            }
308
        }
309
        catch(XmlPullParserException parser_ex){
310
            parser_ex.printStackTrace();
311
        }
312
        catch (IOException ioe) {
313
            ioe.printStackTrace();
314
        }
315
        String message = errors.size()>0? "" : null;
316
        for (int i = 0; i < errors.size(); i++) {
317
            message += (String) errors.get(i)+"\n";
318
        }
319
        return message;
320
        }        
321

    
322
    /**
323
     * Builds the GetCapabilitiesRequest according to the OGC WCS Specifications
324
     * without a VERSION, to get the highest version than a WCS supports.
325
     */
326
    public static String buildCapabilitiesSuitableVersionRequest(String _host, String _version) {
327
                int index = _host.indexOf('?');
328
                
329
                if (index > -1) {
330
                        String host = _host.substring(0, index + 1);
331
                        String query = _host.substring(index + 1, _host.length());
332
                        
333
                        StringTokenizer tokens = new StringTokenizer(query, "&");
334
                        String newQuery = "", token;
335

    
336
                        // If there is a field or a value with spaces, (and then it's on different tokens) -> unify them
337
                        while (tokens.hasMoreTokens()) {
338
                                token = tokens.nextToken().trim();
339

    
340
                                if (token.toUpperCase().compareTo("REQUEST=GETCAPABILITIES") == 0)
341
                                        continue;
342

    
343
                                if (token.toUpperCase().compareTo("SERVICE=WCS") == 0)
344
                                        continue;
345

    
346
                                if ((_version != null) && (_version.length() > 0)) {
347
                                    if (token.toUpperCase().compareTo("VERSION=" + _version) == 0)
348
                                            continue;
349
                                }
350

    
351
                                if (token.toUpperCase().compareTo("EXCEPTIONS=XML") == 0)
352
                                        continue;
353

    
354
                                newQuery += token + "&";
355
                        }
356

    
357
                _host = host + newQuery;
358
                }
359
                else {
360
                        _host += "?";
361
                }
362

    
363
            if ((_version != null) && (_version.compareTo("") != 0))
364
                    _host += "REQUEST=GetCapabilities&SERVICE=WCS&VERSION=" + _version + "&EXCEPTIONS=XML";
365
            else
366
                    _host += "REQUEST=GetCapabilities&SERVICE=WCS&EXCEPTIONS=XML";
367

    
368
            return stringUtils.replaceAll(_host, " ", "%20");
369
    }
370

    
371
        public ArrayList getFormats() {
372
                return new ArrayList(serviceInfo.formats);
373
        }       
374

    
375
        public Hashtable getLayers() {
376
                return layerPool;
377
        }
378
        
379
        public abstract WCSDescribeCoverageRequest createDescribeCoverageRequest(WCSStatus status);
380
        
381
        public abstract WCSGetCoverageRequest createGetCoverageRequest(WCSStatus status);
382

    
383
        /* (non-Javadoc)
384
         * @see org.gvsig.remoteclient.ogc.OGCProtocolHandler#getServiceInformation()
385
         */        
386
        public OGCServiceInformation getServiceInformation() {
387
                return serviceInfo;
388
        }        
389
        
390
}