Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.remoteclient / src / main / java / org / gvsig / remoteclient / wcs / WCSProtocolHandler.java @ 40559

History | View | Annotate | Download (12 KB)

1 40559 jjdelcerro
/**
2
 * gvSIG. Desktop Geographic Information System.
3 40435 jjdelcerro
 *
4 40559 jjdelcerro
 * Copyright (C) 2007-2013 gvSIG Association.
5 40435 jjdelcerro
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8 40559 jjdelcerro
 * as published by the Free Software Foundation; either version 3
9 40435 jjdelcerro
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18 40559 jjdelcerro
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20 40435 jjdelcerro
 *
21 40559 jjdelcerro
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23 40435 jjdelcerro
 */
24
package org.gvsig.remoteclient.wcs;
25
26
import java.io.ByteArrayInputStream;
27
import java.io.File;
28
import java.io.IOException;
29
import java.net.MalformedURLException;
30
import java.net.URL;
31
import java.util.ArrayList;
32
import java.util.Hashtable;
33
import java.util.StringTokenizer;
34
35
import org.gvsig.compat.CompatLocator;
36
import org.gvsig.compat.lang.StringUtils;
37
import org.gvsig.compat.net.ICancellable;
38
import org.gvsig.remoteclient.exceptions.ServerErrorException;
39
import org.gvsig.remoteclient.exceptions.WCSException;
40
import org.gvsig.remoteclient.exceptions.WMSException;
41
import org.gvsig.remoteclient.ogc.OGCProtocolHandler;
42
import org.gvsig.remoteclient.ogc.OGCServiceInformation;
43
import org.gvsig.remoteclient.utils.CapabilitiesTags;
44
import org.gvsig.remoteclient.utils.ExceptionTags;
45
import org.gvsig.remoteclient.utils.Utilities;
46
import org.gvsig.remoteclient.wcs.request.WCSDescribeCoverageRequest;
47
import org.gvsig.remoteclient.wcs.request.WCSGetCoverageRequest;
48
import org.kxml2.io.KXmlParser;
49
import org.xmlpull.v1.XmlPullParserException;
50
/**
51
 *
52
 * @author jaume
53
 *
54
 */
55
public abstract class WCSProtocolHandler extends OGCProtocolHandler {
56
        /**
57
         * Encoding used to parse different xml documents.
58
         */
59
        protected String encoding = "UTF-8";
60
        protected Hashtable layerPool = new Hashtable();
61
62
        /**
63
     * WCS metadata
64
     */
65
    protected WCSServiceInformation serviceInfo = new WCSServiceInformation();
66
67
    private static final StringUtils stringUtils = CompatLocator.getStringUtils();
68
69
        /*
70
         * (non-Javadoc)
71
         * @see org.gvsig.remoteClient.OGCProtocolHandler#setHost(java.lang.String)
72
         */
73
        public void setHost(String host) {
74
                try {
75
                        // Validates the URL if doesn't produces an exception
76
                        new URL(host);
77
78
                        int index = host.indexOf("?");
79
80
                        if (index == -1)
81
                                super.setHost(host);
82
                        else
83
                                super.setHost(host.substring(0, index));
84
                }
85
                catch (MalformedURLException m) {
86
                        // Bad URL -> hold it
87
                        super.setHost(host);
88
                }
89
        }
90
91
        /**
92
     * <p>
93
     * Builds a GetCapabilities request that is sent to the WCS
94
     * the response will be parse to extract the data needed by the
95
     * WCS client.
96
     * </p>
97
     * @param override, if true the cache is ignored
98
     */
99
    public void getCapabilities(WCSStatus status, boolean override, ICancellable cancel) {
100
           URL request = null;
101
            try {
102
                request = new URL(buildCapabilitiesRequest(status));
103
            }
104
            catch(Exception e) {
105
                e.printStackTrace();
106
            }
107
            try {
108
                    if (override)
109
                        downloader.removeURL(request);
110
                    File f =  downloader.downloadFile(request,"wcs_capabilities.xml", cancel);
111
                    if (f!=null)
112
                            parseCapabilities(f);
113
            } catch(Exception e) {
114
                    e.printStackTrace();
115
            }
116
    }
117
118
    /**
119
     * Builds a complete URL-string that can be used to send a GetCapabilities request.
120
     * @return String
121
     */
122
    private String buildCapabilitiesRequest(WCSStatus status) {
123
            StringBuffer req = new StringBuffer();
124
                String symbol = null;
125
126
                String onlineResource;
127
                if (status == null || status.getOnlineResource() == null)
128
                        onlineResource = getHost();
129
                else
130
                        onlineResource = status.getOnlineResource();
131
                symbol = getSymbol(onlineResource);
132
133
                req.append(onlineResource).append(symbol).append("REQUEST=GetCapabilities&SERVICE=WCS&");
134
                req.append("VERSION=").append(getVersion()).append("&EXCEPTIONS=XML");
135
                return req.toString();
136
    }
137
138
139
140
    /**
141
     * parses the data retrieved by the DescribeCoverage XML document
142
     */
143
    public abstract boolean parseDescribeCoverage(File f);
144
145
    /**
146
     * Send a DescribeCoverage request using the settings passed in the status argument.
147
     * If status is null, then default settings are used.
148
     * @param override
149
     * @return String
150
     */
151
    public void describeCoverage(WCSStatus status, boolean override, ICancellable cancel) {
152
       try {
153
               WCSDescribeCoverageRequest request = createDescribeCoverageRequest(status);
154
           File f = request.sendRequest(cancel);
155
                if (f!=null)
156
                        parseDescribeCoverage(f);
157
        } catch(Exception e) {
158
                e.printStackTrace();
159
        }
160
    }
161
162
    /**
163
     * Send a GetCoverage request using the settings passed in the status.
164
     * @return String
165
     */
166
    public File getCoverage(WCSStatus status, ICancellable cancel) throws ServerErrorException, WCSException {
167
            try
168
                {
169
                        //TODO:
170
                        //pass this buildXXXRequest to the WCSProtocolHandlerXXX: The request can depend on the WCS version.
171
                        WCSGetCoverageRequest request = createGetCoverageRequest(status);
172
            File f = request.sendRequest(cancel);
173
174
            if (f!=null && Utilities.isTextFile(f)) {
175
                byte[] data = fileToBytes(f);
176
177
                            WCSException wcsEx = null;
178
179
                    String exceptionMessage = parseException(data);
180
                if (exceptionMessage==null)
181
                {
182
                         String error = new String(data);
183
                        int pos = error.indexOf("<?xml");
184
                        if (pos!= -1)
185
                        {
186
                                String xml = error.substring(pos,error.length());
187
                                exceptionMessage = parseException(xml.getBytes());
188
                        }
189
                    if (exceptionMessage == null)
190
                            exceptionMessage = new String(data);
191
192
                }
193
                     wcsEx = new WCSException(exceptionMessage);
194
                    wcsEx.setWCSMessage(new String(data));
195
196
                    // Since it is an error file, It must be deleted from the cache
197
                    downloader.removeURL(request);
198
                throw wcsEx;
199
            }
200
                        return f;
201
                }
202
                catch(IOException e)
203
                {
204
                        e.printStackTrace();
205
            throw new ServerErrorException();
206
                }
207
    }
208
209
    public URL getCoverageURL(WCSStatus status, ICancellable cancel) throws ServerErrorException, WMSException {
210
            try {
211
                        WCSGetCoverageRequest request = createGetCoverageRequest(status);
212
                        return request.getURL();
213
                } catch(IOException e) {
214
                        e.printStackTrace();
215
            throw new ServerErrorException();
216
                }
217
    }
218
219
    /**
220
     * Returns the exception message if the file is a XML instead of a image.
221
     * @param file3
222
     * @return
223
     * @throws IOException
224
     */
225
    public String getExceptionMessage(File f) throws IOException {
226
            if (f == null)
227
                    return null;
228
229
        if (Utilities.isTextFile(f)) {
230
            byte[] data = fileToBytes(f);
231
232
                String exceptionMessage = parseException(data);
233
            if (exceptionMessage == null) {
234
                     String error = new String(data);
235
                    int pos = error.indexOf("<?xml");
236
                    if (pos!= -1) {
237
                            String xml = error.substring(pos,error.length());
238
                            exceptionMessage = parseException(xml.getBytes());
239
                    }
240
                if (exceptionMessage == null)
241
                        exceptionMessage = new String(data);
242
            }
243
                 return exceptionMessage;
244
        }
245
        return null;
246
    }
247
248
    /**
249
     * Parses the WCS Exception document.
250
     * @param bytes, byte[]
251
     * @return
252
     */
253
    private String parseException(byte[] data) {
254
            // TODO: a?? est? fusilat del WMS, comprovar que funciona.
255
            ArrayList errors = new ArrayList();
256
        KXmlParser kxmlParser = new KXmlParser();
257
        boolean end = false;
258
        try
259
        {
260
            kxmlParser.setInput(new ByteArrayInputStream(data), encoding);
261
            kxmlParser.nextTag();
262
            int tag;
263
            if ( kxmlParser.getEventType() != KXmlParser.END_DOCUMENT )
264
            {
265
                kxmlParser.require(KXmlParser.START_TAG, null, ExceptionTags.EXCEPTION_ROOT);
266
                tag = kxmlParser.nextTag();
267
                 while(!end)
268
                 {
269
                     switch(tag)
270
                     {
271
                        case KXmlParser.START_TAG:
272
                            if (kxmlParser.getName().compareTo(ExceptionTags.SERVICE_EXCEPTION)==0){
273
                                String errorCode = kxmlParser.getAttributeValue("", ExceptionTags.CODE);
274
                                errorCode = (errorCode != null) ? "["+errorCode+"] " : "";
275
                                String errorMessage = kxmlParser.nextText();
276
                                errors.add(errorCode+errorMessage);
277
                            }
278
                            break;
279
                        case KXmlParser.END_TAG:
280
                                 if (kxmlParser.getName().compareTo(ExceptionTags.SERVICE_EXCEPTION) == 0 ||
281
                                                 kxmlParser.getName().compareTo(ExceptionTags.EXCEPTION_ROOT) == 0)
282
                                 end = true;
283
                            break;
284
285
                     }
286
                     if (!end)
287
                             tag = kxmlParser.nextTag();
288
                 }
289
                 //kxmlParser.require(KXmlParser.END_DOCUMENT, null, null);
290
            }
291
        }
292
        catch(XmlPullParserException parser_ex){
293
            parser_ex.printStackTrace();
294
        }
295
        catch (IOException ioe) {
296
            ioe.printStackTrace();
297
        }
298
        String message = errors.size()>0? "" : null;
299
        for (int i = 0; i < errors.size(); i++) {
300
            message += (String) errors.get(i)+"\n";
301
        }
302
        return message;
303
        }
304
305
    /**
306
     * Builds the GetCapabilitiesRequest according to the OGC WCS Specifications
307
     * without a VERSION, to get the highest version than a WCS supports.
308
     */
309
    public static String buildCapabilitiesSuitableVersionRequest(String _host, String _version) {
310
                int index = _host.indexOf('?');
311
312
                if (index > -1) {
313
                        String host = _host.substring(0, index + 1);
314
                        String query = _host.substring(index + 1, _host.length());
315
316
                        StringTokenizer tokens = new StringTokenizer(query, "&");
317
                        String newQuery = "", token;
318
319
                        // If there is a field or a value with spaces, (and then it's on different tokens) -> unify them
320
                        while (tokens.hasMoreTokens()) {
321
                                token = tokens.nextToken().trim();
322
323
                                if (token.toUpperCase().compareTo("REQUEST=GETCAPABILITIES") == 0)
324
                                        continue;
325
326
                                if (token.toUpperCase().compareTo("SERVICE=WCS") == 0)
327
                                        continue;
328
329
                                if ((_version != null) && (_version.length() > 0)) {
330
                                    if (token.toUpperCase().compareTo("VERSION=" + _version) == 0)
331
                                            continue;
332
                                }
333
334
                                if (token.toUpperCase().compareTo("EXCEPTIONS=XML") == 0)
335
                                        continue;
336
337
                                newQuery += token + "&";
338
                        }
339
340
                _host = host + newQuery;
341
                }
342
                else {
343
                        _host += "?";
344
                }
345
346
            if ((_version != null) && (_version.compareTo("") != 0))
347
                    _host += "REQUEST=GetCapabilities&SERVICE=WCS&VERSION=" + _version + "&EXCEPTIONS=XML";
348
            else
349
                    _host += "REQUEST=GetCapabilities&SERVICE=WCS&EXCEPTIONS=XML";
350
351
            return stringUtils.replaceAll(_host, " ", "%20");
352
    }
353
354
        public ArrayList getFormats() {
355
                return new ArrayList(serviceInfo.formats);
356
        }
357
358
        public Hashtable getLayers() {
359
                return layerPool;
360
        }
361
362
        public abstract WCSDescribeCoverageRequest createDescribeCoverageRequest(WCSStatus status);
363
364
        public abstract WCSGetCoverageRequest createGetCoverageRequest(WCSStatus status);
365
366
        /* (non-Javadoc)
367
         * @see org.gvsig.remoteclient.ogc.OGCProtocolHandler#getServiceInformation()
368
         */
369
        public OGCServiceInformation getServiceInformation() {
370
                return serviceInfo;
371
        }
372
373
}