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 @ 41877

History | View | Annotate | Download (12.1 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
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
 * as published by the Free Software Foundation; either version 3
9
 * 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
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
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
    public URL getCoverageURL(WCSStatus status, ICancellable cancel) throws ServerErrorException {
211
            try {
212
                        WCSGetCoverageRequest request = createGetCoverageRequest(status);
213
                        return request.getURL();
214
                } catch(IOException e) {
215
                        e.printStackTrace();
216
            throw new ServerErrorException();
217
                }
218
    }
219
    
220
    /**
221
     * Returns the exception message if the file is a XML instead of a image.
222
     * @param file3
223
     * @return
224
     * @throws IOException 
225
     */
226
    public String getExceptionMessage(File f) throws IOException {
227
            if (f == null)
228
                    return null;
229
            
230
        if (Utilities.isTextFile(f)) {
231
            byte[] data = fileToBytes(f);
232

    
233
                String exceptionMessage = parseException(data);
234
            if (exceptionMessage == null) {
235
                     String error = new String(data);
236
                    int pos = error.indexOf("<?xml");
237
                    if (pos!= -1) {
238
                            String xml = error.substring(pos,error.length());
239
                            exceptionMessage = parseException(xml.getBytes());
240
                    }
241
                if (exceptionMessage == null)
242
                        exceptionMessage = new String(data);
243
            }
244
                 return exceptionMessage;
245
        }
246
        return null;
247
    }
248

    
249
    /**
250
     * Parses the WCS Exception document.
251
     * @param bytes, byte[]
252
     * @return
253
     */
254
    private String parseException(byte[] data) {
255
            // TODO: a?? est? fusilat del WMS, comprovar que funciona.
256
            ArrayList errors = new ArrayList();
257
        KXmlParser kxmlParser = new KXmlParser();
258
        boolean end = false;
259
        try
260
        {
261
            kxmlParser.setInput(new ByteArrayInputStream(data), encoding);
262
            kxmlParser.nextTag();
263
            int tag;
264
            if ( kxmlParser.getEventType() != KXmlParser.END_DOCUMENT )
265
            {
266
                kxmlParser.require(KXmlParser.START_TAG, null, ExceptionTags.EXCEPTION_ROOT);
267
                tag = kxmlParser.nextTag();
268
                 while(!end)
269
                 {
270
                     switch(tag)
271
                     {
272
                        case KXmlParser.START_TAG:
273
                            if (kxmlParser.getName().compareTo(ExceptionTags.SERVICE_EXCEPTION)==0){
274
                                String errorCode = kxmlParser.getAttributeValue("", ExceptionTags.CODE);
275
                                errorCode = (errorCode != null) ? "["+errorCode+"] " : "";
276
                                String errorMessage = kxmlParser.nextText();
277
                                errors.add(errorCode+errorMessage);
278
                            }
279
                            break;
280
                        case KXmlParser.END_TAG:
281
                                 if (kxmlParser.getName().compareTo(ExceptionTags.SERVICE_EXCEPTION) == 0 ||
282
                                                 kxmlParser.getName().compareTo(ExceptionTags.EXCEPTION_ROOT) == 0)
283
                                 end = true;
284
                            break;
285

    
286
                     }
287
                     if (!end)
288
                             tag = kxmlParser.nextTag();
289
                 }
290
                 //kxmlParser.require(KXmlParser.END_DOCUMENT, null, null);
291
            }
292
        }
293
        catch(XmlPullParserException parser_ex){
294
            parser_ex.printStackTrace();
295
        }
296
        catch (IOException ioe) {
297
            ioe.printStackTrace();
298
        }
299
        String message = errors.size()>0? "" : null;
300
        for (int i = 0; i < errors.size(); i++) {
301
            message += (String) errors.get(i)+"\n";
302
        }
303
        return message;
304
        }        
305

    
306
    /**
307
     * Builds the GetCapabilitiesRequest according to the OGC WCS Specifications
308
     * without a VERSION, to get the highest version than a WCS supports.
309
     */
310
    public static String buildCapabilitiesSuitableVersionRequest(String _host, String _version) {
311
                int index = _host.indexOf('?');
312
                
313
                if (index > -1) {
314
                        String host = _host.substring(0, index + 1);
315
                        String query = _host.substring(index + 1, _host.length());
316
                        
317
                        StringTokenizer tokens = new StringTokenizer(query, "&");
318
                        String newQuery = "", token;
319

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

    
324
                                if (token.toUpperCase().compareTo("REQUEST=GETCAPABILITIES") == 0)
325
                                        continue;
326

    
327
                                if (token.toUpperCase().compareTo("SERVICE=WCS") == 0)
328
                                        continue;
329

    
330
                                if ((_version != null) && (_version.length() > 0)) {
331
                                    if (token.toUpperCase().compareTo("VERSION=" + _version) == 0)
332
                                            continue;
333
                                }
334

    
335
                                if (token.toUpperCase().compareTo("EXCEPTIONS=XML") == 0)
336
                                        continue;
337

    
338
                                newQuery += token + "&";
339
                        }
340

    
341
                _host = host + newQuery;
342
                }
343
                else {
344
                        _host += "?";
345
                }
346

    
347
            if ((_version != null) && (_version.compareTo("") != 0))
348
                    _host += "REQUEST=GetCapabilities&SERVICE=WCS&VERSION=" + _version + "&EXCEPTIONS=XML";
349
            else
350
                    _host += "REQUEST=GetCapabilities&SERVICE=WCS&EXCEPTIONS=XML";
351

    
352
            return stringUtils.replaceAll(_host, " ", "%20");
353
    }
354

    
355
        public ArrayList getFormats() {
356
                return new ArrayList(serviceInfo.formats);
357
        }       
358

    
359
        public Hashtable getLayers() {
360
                return layerPool;
361
        }
362
        
363
        public abstract WCSDescribeCoverageRequest createDescribeCoverageRequest(WCSStatus status);
364
        
365
        public abstract WCSGetCoverageRequest createGetCoverageRequest(WCSStatus status);
366

    
367
        /* (non-Javadoc)
368
         * @see org.gvsig.remoteclient.ogc.OGCProtocolHandler#getServiceInformation()
369
         */        
370
        public OGCServiceInformation getServiceInformation() {
371
                return serviceInfo;
372
        }        
373
        
374
}