Statistics
| Revision:

root / branches / v2_0_0_prep / libraries / libRemoteServices / src / org / gvsig / remoteclient / wcs / WCSProtocolHandler.java @ 34026

History | View | Annotate | Download (10.7 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.kxml2.io.KXmlParser;
53
import org.xmlpull.v1.XmlPullParserException;
54

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

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

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

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

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

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

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

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

    
154

    
155

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

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

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

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

    
193
                            WCSException wcsEx = null;
194

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

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

    
212
                    // Since it is an error file, It must be deleted from the cache
213
                    downloader.removeURL(request);
214
                throw wcsEx;
215
            }
216
                        return f;
217
                }
218
                catch(IOException e)
219
                {
220
                        e.printStackTrace();
221
            throw new ServerErrorException();
222
                }
223
    }
224

    
225

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

    
259
                     }
260
                     tag = kxmlParser.nextTag();
261
                 }
262
                 //kxmlParser.require(KXmlParser.END_DOCUMENT, null, null);
263
            }
264
        }
265
        catch(XmlPullParserException parser_ex){
266
            parser_ex.printStackTrace();
267
        }
268
        catch (IOException ioe) {
269
            ioe.printStackTrace();
270
        }
271
        String message = errors.size()>0? "" : null;
272
        for (int i = 0; i < errors.size(); i++) {
273
            message += (String) errors.get(i)+"\n";
274
        }
275
        return message;
276
        }        
277

    
278
    /**
279
     * Builds the GetCapabilitiesRequest according to the OGC WCS Specifications
280
     * without a VERSION, to get the highest version than a WCS supports.
281
     */
282
    public static String buildCapabilitiesSuitableVersionRequest(String _host, String _version) {
283
                int index = _host.indexOf('?');
284
                
285
                if (index > -1) {
286
                        String host = _host.substring(0, index + 1);
287
                        String query = _host.substring(index + 1, _host.length());
288
                        
289
                        StringTokenizer tokens = new StringTokenizer(query, "&");
290
                        String newQuery = "", token;
291

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

    
296
                                if (token.toUpperCase().compareTo("REQUEST=GETCAPABILITIES") == 0)
297
                                        continue;
298

    
299
                                if (token.toUpperCase().compareTo("SERVICE=WCS") == 0)
300
                                        continue;
301

    
302
                                if ((_version != null) && (_version.length() > 0)) {
303
                                    if (token.toUpperCase().compareTo("VERSION=" + _version) == 0)
304
                                            continue;
305
                                }
306

    
307
                                if (token.toUpperCase().compareTo("EXCEPTIONS=XML") == 0)
308
                                        continue;
309

    
310
                                newQuery += token + "&";
311
                        }
312

    
313
                _host = host + newQuery;
314
                }
315
                else {
316
                        _host += "?";
317
                }
318

    
319
            if ((_version != null) && (_version.compareTo("") != 0))
320
                    _host += "REQUEST=GetCapabilities&SERVICE=WCS&VERSION=" + _version + "&EXCEPTIONS=XML";
321
            else
322
                    _host += "REQUEST=GetCapabilities&SERVICE=WCS&EXCEPTIONS=XML";
323

    
324
            return stringUtils.replaceAll(_host, " ", "%20");
325
    }
326

    
327
        public ArrayList getFormats() {
328
                return new ArrayList(serviceInfo.formats);
329
        }       
330

    
331
        public Hashtable getLayers() {
332
                return layerPool;
333
        }
334
        
335
        public abstract WCSDescribeCoverageRequest createDescribeCoverageRequest(WCSStatus status);
336
        
337
        public abstract WCSGetCoverageRequest createGetCoverageRequest(WCSStatus status);
338

    
339
        /* (non-Javadoc)
340
         * @see org.gvsig.remoteclient.ogc.OGCProtocolHandler#getServiceInformation()
341
         */        
342
        public OGCServiceInformation getServiceInformation() {
343
                return serviceInfo;
344
        }        
345
        
346
}