Statistics
| Revision:

gvsig-raster / org.gvsig.raster.wmts / trunk / org.gvsig.raster.wmts / org.gvsig.raster.wmts.ogc / org.gvsig.raster.wmts.ogc.impl / src / main / java / org / gvsig / raster / wmts / ogc / impl / base / WMTSProtocolHandler.java @ 4175

History | View | Annotate | Download (24.3 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
*
3
* Copyright (C) 2007-2008 Infrastructures and Transports Department
4
* of the Valencian Government (CIT)
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 2
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
*/
22
package org.gvsig.raster.wmts.ogc.impl.base;
23

    
24
import java.io.BufferedOutputStream;
25
import java.io.ByteArrayInputStream;
26
import java.io.DataInputStream;
27
import java.io.DataOutputStream;
28
import java.io.File;
29
import java.io.FileInputStream;
30
import java.io.FileOutputStream;
31
import java.io.FileReader;
32
import java.io.IOException;
33
import java.net.HttpURLConnection;
34
import java.net.MalformedURLException;
35
import java.net.URL;
36
import java.nio.ByteBuffer;
37
import java.nio.channels.FileChannel;
38
import java.security.KeyManagementException;
39
import java.security.NoSuchAlgorithmException;
40
import java.util.ArrayList;
41
import java.util.Hashtable;
42
import java.util.List;
43
import java.util.StringTokenizer;
44
import java.util.prefs.Preferences;
45

    
46
import javax.net.ssl.HttpsURLConnection;
47
import javax.net.ssl.SSLContext;
48
import javax.net.ssl.TrustManager;
49
import javax.net.ssl.X509TrustManager;
50

    
51
import org.gvsig.compat.CompatLocator;
52
import org.gvsig.compat.net.Downloader;
53
import org.gvsig.compat.net.ICancellable;
54
import org.gvsig.gui.beans.incrementabletask.IncrementableProcess;
55
import org.gvsig.raster.wmts.ogc.WMTSStatus;
56
import org.gvsig.raster.wmts.ogc.exception.DownloadException;
57
import org.gvsig.raster.wmts.ogc.exception.ServerErrorException;
58
import org.gvsig.raster.wmts.ogc.exception.WMTSException;
59
import org.gvsig.raster.wmts.ogc.impl.Tags;
60
import org.gvsig.raster.wmts.ogc.impl.Utilities;
61
import org.gvsig.raster.wmts.ogc.impl.request.WMTSGetCapabilitiesRequest;
62
import org.gvsig.raster.wmts.ogc.impl.request.WMTSGetFeatureInfoRequest;
63
import org.gvsig.raster.wmts.ogc.impl.request.WMTSGetTileRequest;
64
import org.gvsig.raster.wmts.ogc.struct.WMTSLayer;
65
import org.gvsig.raster.wmts.ogc.struct.WMTSOperationsMetadata;
66
import org.gvsig.raster.wmts.ogc.struct.WMTSStyle;
67
import org.kxml2.io.KXmlParser;
68
import org.slf4j.Logger;
69
import org.slf4j.LoggerFactory;
70
import org.xmlpull.v1.XmlPullParserException;
71

    
72
/**
73
 * <p> Abstract class that represents handlers to comunicate via WMS protocol.</p>
74
 * 
75
 * @author Nacho Brodin (nachobrodin@gmail.com)
76
 */
77
public abstract class WMTSProtocolHandler {
78
    private static final Logger logger = LoggerFactory
79
            .getLogger(WMTSProtocolHandler.class);
80

    
81
        protected static final Downloader downloader = CompatLocator.getDownloader();
82
        /**
83
         * Encoding used to parse different xml documents.
84
         */
85
        protected String                 encoding                     = "UTF-8";
86
        private static int               count                        = 0;
87
        final String                     tempDirectoryPath            = System.getProperty("java.io.tmpdir")+"/tmp-andami";
88
        protected boolean                forceChangeAxisOrder         = false;
89
    protected String                 name;
90
    protected String                 version;
91
    protected String                 host;
92
    protected String                 port;  
93
    private WMTSServerDescription    serverDescription            = null;
94
        
95
    protected abstract WMTSGetFeatureInfoRequest createGetFeatureInfoRequest(WMTSStatusImpl status, int x, int y);
96

    
97
    protected abstract WMTSGetTileRequest createGetTileRequest(WMTSStatusImpl status);
98
    
99
    protected abstract WMTSGetCapabilitiesRequest createGetCapabilitiesRequest();
100
    
101
    /**
102
     * parses the data retrieved by the Capabilities XML document
103
     */
104
    public abstract boolean parseCapabilities(File f);
105
    
106
        public WMTSServerDescription getServerDescription() {
107
                if(serverDescription == null) {
108
                        serverDescription = new WMTSServerDescription(getVersion());
109
                }
110
                return this.serverDescription;
111
        }
112

    
113
    /**
114
     * @return Returns the host.
115
     */
116
    public String getHost() {
117
        return host;
118
    }
119
    /**
120
     * @param host The host to set.
121
     */
122
    public void setHost(String host) {
123
        this.host = host;
124
    }
125
    /**
126
     * @return Returns the name.
127
     */
128
    public String getName() {
129
        return name;
130
    }
131
    /**
132
     * @param name The name to set.
133
     */
134
    public void setName(String name) {
135
        this.name = name;
136
    }
137
    /**
138
     * @return Returns the port.
139
     */
140
    public String getPort() {
141
        return port;
142
    }
143
    /**
144
     * @param port The port to set.
145
     */
146
    public void setPort(String port) {
147
        this.port = port;
148
    }
149
    /**
150
     * @return Returns the version.
151
     */
152
    public String getVersion() {
153
        return version;
154
    }
155
    /**
156
     * @param version The version to set.
157
     */
158
    public void setVersion(String version) {
159
        this.version = version;
160
    }
161

    
162
    /**
163
     * Just for not repeat code. Gets the correct separator according 
164
     * to the server URL
165
     * @param h
166
     * @return
167
     */
168
    public String getSymbol(String h) {
169
        String symbol;
170
        if (h.indexOf("?")==-1) 
171
            symbol = "?";
172
        else if (h.indexOf("?")!=h.length()-1)
173
            symbol = "&";
174
        else
175
            symbol = "";
176
        return symbol;
177
    }  
178

    
179
    /**
180
     * Copy the file in a byte array
181
     * @param file
182
     * The file to copy
183
     * @return
184
     * An array of bytes
185
     * @throws IOException
186
     */
187
    protected byte[] fileToBytes(File file) throws IOException {
188
        FileInputStream fis = null;
189
        byte[] bytes = null;
190
        try{
191
            fis = new FileInputStream(file);
192

    
193
            //long length = file.length(); 
194
            bytes = new byte[(int)file.length()];
195

    
196
            int offset = 0;
197
            int numRead = 0; 
198
            while (offset < bytes.length && 
199
                    (numRead = fis.read(bytes, offset, bytes.length-offset)) >= 0) { 
200
                offset += numRead; 
201
            }
202
        } catch (IOException e) {
203
            throw e;
204
        } finally {
205
            if (fis != null) {
206
                fis.close();
207
            }
208
        }         
209
        return bytes;
210
    }
211
    
212
    /**
213
         * Sets longitude first in the axis order read from the capabilities file
214
         * @param force
215
         */
216
        public void setForceChangeAxisOrder(boolean force) {
217
                this.forceChangeAxisOrder = force;
218
        }
219
        
220
    //**************************************************************
221
    //Esto es temporal hasta que est? la cach?
222
    
223
        private Hashtable<URL, String>                downloadedFiles;
224
    /**
225
         * Returns the content of a URL as a file from the file system.<br>
226
         * <p>
227
         * If the URL has been already downloaded in this session and notified
228
         * to the system using the static <b>Utilities.addDownloadedURL(URL)</b>
229
         * method, it can be restored faster from the file system avoiding to
230
         * download it again.
231
         * </p>
232
         * @param url
233
         * @return File containing this URL's content or null if no file was found.
234
         */
235
        private File getPreviousDownloaded(Object object) {
236
                File f = null;
237
                if (downloadedFiles != null && downloadedFiles.containsKey(object)) {
238
                        String filePath = (String) downloadedFiles.get(object);
239
                        f = new File(filePath);
240
                        if (!f.exists())
241
                                return null;
242
                }
243
                return f;
244
        }
245

    
246
        /**
247
         * Adds an URL to the table of downloaded files for further uses. If the URL
248
         * already exists in the table its filePath value is updated to the new one and
249
         * the old file itself is removed from the file system.
250
         *
251
         * @param url
252
         * @param filePath
253
         */
254
        void addDownloadedURL(URL url, String filePath) {
255
                if (downloadedFiles == null)
256
                        downloadedFiles = new Hashtable<URL, String>();
257
                downloadedFiles.put(url, filePath);
258
        }
259
        
260
        //Fin del c?digo temporal hasta que est? la cach?
261
        //**************************************************************
262
    
263
    public synchronized File getTile(WMTSStatusImpl status, ICancellable cancel, File file) throws ServerErrorException, WMTSException {
264
            try {
265
                        WMTSGetTileRequest request = createGetTileRequest(status);
266
                        request.sendRequest(cancel, file);
267
                        try {
268
                                checkFileError(file);
269
                        } catch(WMTSException e) {
270
                                file.delete();
271
                                throw new WMTSException("This tile is not available:" + file.getAbsoluteFile().toString(), e);
272
                        } catch(IOException e) {
273
                                file.delete();
274
                                throw new WMTSException("This tile is not available:" + file.getAbsoluteFile().toString(), e);
275
                        }
276
                        return file;
277
                } catch(IOException e) {
278
            throw new WMTSException(e);
279
                }
280
    }
281
    
282
    public synchronized File getTile(WMTSStatus status, ICancellable cancel) throws ServerErrorException, WMTSException {
283
            try {
284
                        WMTSGetTileRequest request = createGetTileRequest((WMTSStatusImpl)status);
285
                        File f = request.sendRequest(cancel);
286
                        try {
287
                                checkFileError(f);
288
                        } catch(WMTSException e) {
289
                                downloader.removeURL(request);
290
                    throw new ServerErrorException();
291
                        }
292
                        return f;
293
                } catch(IOException e) {
294
                        e.printStackTrace();
295
            throw new ServerErrorException();
296
                }
297
    }
298
    
299
    public synchronized File getTile(String url, ICancellable cancel, File file) throws ServerErrorException, WMTSException {
300
            try {
301
                        downloadFile(new URL(url), cancel, file);
302
                        try {
303
                                checkFileError(file);
304
                        } catch(WMTSException e) {
305
                                file.delete();
306
                                throw new WMTSException("This tile is not available:" + file.getAbsoluteFile().toString(), e);
307
                        } catch(IOException e) {
308
                                file.delete();
309
                                throw new WMTSException("This tile is not available:" + file.getAbsoluteFile().toString(), e);
310
                        }
311
                        return file;
312
                } catch(IOException e) {
313
            throw new WMTSException(e);
314
                } catch (DownloadException e1) {
315
                        throw new WMTSException(e1);
316
                }
317
    }
318
    
319
    /**
320
     * Checks if the file downloaded is correct or doesn't
321
     * @param f
322
     * @throws WMTSException
323
     * @throws IOException
324
     */
325
    private void checkFileError(File f) throws WMTSException, IOException {
326
                if (f == null)
327
                    return;
328
            if (Utilities.isTextFile(f)) {
329
            byte[] data = fileToBytes(f);
330

    
331
                String exceptionMessage = parseException(data);
332
            if (exceptionMessage == null) {
333
                     String error = new String(data);
334
                    int pos = error.indexOf("<?xml");
335
                    if (pos!= -1) {
336
                            String xml = error.substring(pos,error.length());
337
                            exceptionMessage = parseException(xml.getBytes());
338
                    }
339
                if (exceptionMessage == null)
340
                        exceptionMessage = new String(data);
341

    
342
            }
343
            throw new WMTSException(exceptionMessage);
344
        }
345
    }
346
    
347
    public synchronized URL getTileURL(WMTSStatusImpl status) throws MalformedURLException {
348
            String onlineResource = getBaseURL(Tags.GETTILE);
349

    
350
                StringBuffer req = new StringBuffer();
351
                req.append(onlineResource)
352
                .append("REQUEST=GetTile&SERVICE=WMTS&VERSION=").append(getVersion()).append("&")
353
                .append("Layer=" + status.getLayer())
354
        .append("&Style=" + status.getStyle())
355
        .append("&Format=" + status.getFormat())
356
        .append("&TileMatrixSet=" + status.getTileMatrixSet())
357
        .append("&TileMatrix=" + status.getTileMatrix())
358
        .append("&TileRow=" + status. getTileRow())
359
        .append("&TileCol=" + status.getTileCol());
360
                
361
                return new URL(req.toString());
362
    }
363
    
364
    /**
365
     * Gets the URL base for a operation (GetCapabilities, GetTile, ...)
366
     * @param operation
367
     * @return the base URL for the GET protocol or the host passed by the user 
368
     * if it does not exists. 
369
     */
370
    public String getBaseURL(String operation) {
371
            String onlineResource = null;
372
            WMTSServerDescription svDescription = getServerDescription();
373
            if(svDescription != null) {
374
                    WMTSOperationsMetadata opMetadata = svDescription.getOperationsMetadata();
375
                    if(opMetadata != null)
376
                            onlineResource = opMetadata.getOnlineResource(operation);
377
            }
378
            if(onlineResource == null)
379
                    onlineResource = getHost();
380
                String symbol = getSymbol(onlineResource);
381
                onlineResource = onlineResource + symbol;
382
                return onlineResource;
383
    }
384
    
385
    /**
386
     * Gets the URL base for a operation (GetCapabilities, GetTile, ...) and 
387
     * a protocol GET or POST
388
     * @param operation
389
     * @return the base URL for this protocol or null if it does not exists. 
390
     */
391
    public String getBaseURL(String operation, int protocol) {
392
            String onlineResource = null;
393
            WMTSServerDescription svDescription = getServerDescription();
394
            if(svDescription != null) {
395
                    WMTSOperationsMetadata opMetadata = svDescription.getOperationsMetadata();
396
                    if(opMetadata != null) {
397
                            onlineResource = opMetadata.getOnlineResource(operation, protocol);
398
                            if(onlineResource != null) {
399
                                    String symbol = getSymbol(onlineResource);
400
                                    return onlineResource + symbol;
401
                            }
402
                    }
403
            }
404
                return null;
405
    }
406
    
407
    /**
408
     * Gets a file name to download. I
409
     * @param url
410
     * @return
411
     */
412
    private File getFile() {
413
            count ++;
414
                int index = name.lastIndexOf(".");
415
                if (index > 0){
416
                        return new File(tempDirectoryPath + "/" + name.substring(0,index) + System.currentTimeMillis() + count + 
417
                                name.substring(index, name.length()));
418
                }
419
                return new File(tempDirectoryPath + "/" + name + System.currentTimeMillis() + count);
420
    }
421
    
422
    public synchronized File downloadFile(URL url, ICancellable cancel, File forceFile) throws DownloadException {
423
            if(forceFile == null) {
424
                    File f = null;
425
                    if((f = getPreviousDownloaded(url)) != null)
426
                            return f;
427
            }
428
                    
429
            Preferences prefs = Preferences.userRoot().node( "gvsig.downloader" );
430
            int IO_BUFFER_SIZE = 8 * 1024;
431
                int timeout = prefs.getInt("timeout", 60000);
432
                
433
                File dstFile = forceFile;
434
                if(dstFile == null)
435
                        dstFile = getFile();
436
                
437
                DataOutputStream dos;
438
                try {
439
                        DataInputStream is;
440
                        //OutputStreamWriter os = null;
441
                        HttpURLConnection connection = null;
442

    
443
                        if (url.getProtocol().equals("https")) {
444
                                disableHttsValidation();
445
                        }
446
                        connection = (HttpURLConnection)url.openConnection();
447
                        connection.setConnectTimeout(timeout);
448
                        
449
                        is = new DataInputStream(url.openStream());
450
                        
451
                        dos = new DataOutputStream( new BufferedOutputStream(new FileOutputStream(dstFile)));
452
                        byte[] buffer = new byte[IO_BUFFER_SIZE];
453

    
454
                        int read;
455
                        while ((read = is.read(buffer)) != -1) {
456
                                dos.write(buffer, 0, read);
457
                        }
458
                        
459
                        /*if(os != null) {
460
                                os.close();
461
                        }*/
462
                        dos.close();
463
                        is.close();
464
                        is = null;
465
                        dos = null;
466
                        if (cancel != null && cancel.isCanceled()) {
467
                                dstFile.delete();
468
                                dstFile = null;
469
                                return null;
470
                        }
471
                } catch (Exception e) {
472
                        logger.error("[WMTSProtocolHandler.java:473] " + e);
473
                        throw new DownloadException(e);
474
                }
475
                addDownloadedURL(url, dstFile.getAbsolutePath());
476
                return dstFile;
477
    }
478
    
479
    /**
480
         * This method disables the Https certificate validation.
481
         * @throws KeyManagementException
482
         * @throws NoSuchAlgorithmException
483
         */
484
        private void disableHttsValidation() throws KeyManagementException, NoSuchAlgorithmException{
485
                // Create a trust manager that does not validate certificate chains
486
                TrustManager[] trustAllCerts = new TrustManager[] {
487
                                new X509TrustManager() {
488
                                        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
489
                                                return null;
490
                                        }
491
                                        public void checkClientTrusted(
492
                                                        java.security.cert.X509Certificate[] certs, String authType) {
493
                                        }
494
                                        public void checkServerTrusted(
495
                                                        java.security.cert.X509Certificate[] certs, String authType) {
496
                                        }
497
                                }
498
                };
499

    
500
                // Install the all-trusting trust manager
501
                SSLContext sc = SSLContext.getInstance("SSL");
502
                sc.init(null, trustAllCerts, new java.security.SecureRandom());
503
                HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
504
        }
505
        
506
        /**
507
     * @return string that represents the url for getting the wms legend
508
     * If the layer has the object layer-->style-->legendurl that url will be returned 
509
     * otherwise builds the getLegendGraphic according to the OGC WMS Specifications
510
     * 
511
     */
512
    /*private String buildGetLegendGraphicRequest(WMTSLayer layer, WMTSStyle style) {
513
            String onlineResource = style.getLegendURL().getHref();
514
                String symbol = getSymbol(onlineResource);
515
                String layerName = layer.getTitle();
516
                
517
                if(onlineResource == null || onlineResource.equals(""))
518
                        return null;
519

520
                StringBuffer req = new StringBuffer();
521
                req.append(onlineResource + symbol + "REQUEST=GetLegendGraphic&SERVICE=WMS&VERSION=").append(getVersion());
522
        req.append("&LAYER=" + layerName).append("&TRANSPARENT=TRUE").append("&FORMAT=image/png");
523
        String aux = req.toString().replaceAll(" ", "%20");
524
        System.out.println("GetLegendGraphic url:" + aux);
525
                return aux;
526
    }*/
527

    
528
        public File getLegendGraphic(WMTSLayer layer, WMTSStyle style, ICancellable cancel) 
529
                        throws ServerErrorException, WMTSException, DownloadException {
530
                URL request = null;
531
                try {
532
                        String requestStr = style.getLegendURL().getHref();
533
                        if(requestStr == null || requestStr.equals(""))
534
                                return null;
535
                        request = new URL(requestStr);
536
                        System.out.println(requestStr);
537
                        
538
                        File f = downloadFile(request, cancel, null);
539
                        if (f== null)
540
                                return null;
541
                        if (Utilities.isTextFile(f)) {
542
                                FileInputStream fis = new FileInputStream(f);
543
                                FileChannel fc = fis.getChannel();
544
                                byte[] data = new byte[(int)fc.size()];
545
                                ByteBuffer bb = ByteBuffer.wrap(data);
546
                                fc.read(bb);
547

    
548
                                WMTSException wmsEx = null;
549

    
550
                                String exceptionMessage = parseException(data);
551
                                if (exceptionMessage == null) {
552
                                        String error = new String(data);
553
                                        int pos = error.indexOf("<?xml");
554
                                        if (pos!= -1) {
555
                                                String xml = error.substring(pos,error.length());
556
                                                exceptionMessage = parseException(xml.getBytes());
557
                                        }
558
                                        if (exceptionMessage == null)
559
                                                exceptionMessage = new String(data);
560

    
561
                                }
562
                                wmsEx = new WMTSException(exceptionMessage);
563
                                wmsEx.setWMTSMessage(new String(data));
564
                                Utilities.removeURL(request);
565
                                fis.close();
566
                                throw wmsEx;
567
                        }
568
                        return f;
569
                } catch(IOException e) {
570
                        e.printStackTrace();
571
                        throw new ServerErrorException();
572
                }
573
        }
574

    
575
        /**
576
         * <p>It will send a GetFeatureInfo request to the WMTS
577
     * Parsing the response and redirecting the info to the WMTS client</p>
578
     * TODO: return a stored file instead a String.
579
     */
580
    public String getFeatureInfo(WMTSStatusImpl status, int x, int y, ICancellable cancel) {
581
            StringBuffer output = new StringBuffer();
582
            String outputFormat = new String();
583
            String ServiceException = "ServiceExceptionReport";
584
            StringBuffer sb = new StringBuffer();
585
            sb.append("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");
586
                try {
587
                        WMTSGetFeatureInfoRequest request = createGetFeatureInfoRequest(status, x, y);
588
                        URL url = request.getURL();
589
                    outputFormat = url.openConnection().getContentType();
590
                    File f = request.sendRequest(cancel);
591
                        if (f == null) {
592
                                return "";
593
                        }
594

    
595
                        FileReader fReader = new FileReader(f);
596
                        char[] buffer = new char[1024*256];
597
                        for (int i = fReader.read(buffer);i > 0;i = fReader.read(buffer)) {
598
                            String str = new String(buffer, 0, i);
599
                            output.append(str);
600
                    }
601
                        fReader.close();
602
                    if ( (outputFormat == null) || (outputFormat.indexOf("xml") != -1)
603
                                    ||output.toString().toLowerCase().startsWith("<?xml")
604
                                    ||(outputFormat.indexOf("gml") != -1)) {
605
                            KXmlParser kxmlParser = null;
606
                            kxmlParser = new KXmlParser();
607
                            //kxmlParser.setInput(new StringReader(output.toString()));
608
                            kxmlParser.setInput(new FileReader(f));
609

    
610
                            kxmlParser.nextTag();
611
                            if (kxmlParser.getName().compareTo(ServiceException) == 0) {
612
                                    sb.append("<INFO>").append(parseException( output.toString().getBytes())).append("</INFO>");
613
                                    return sb.toString();
614
                                } else if (kxmlParser.getName().compareToIgnoreCase("ERROR") == 0) {
615
                                        return output.toString();
616
                                } else {
617
                                        return output.toString();
618
                                }
619
                    } else {                  
620
                             return output.toString();
621
                    }
622
                } catch(XmlPullParserException parserEx) {
623
                    if (output.toString().toLowerCase().indexOf("xml") != -1) {
624
                            return output.toString().trim();
625
                    } else {
626
                               sb.append("<INFO>").append("Info format not supported").append("</INFO>");
627
                        return sb.toString();
628
                    }
629
            } catch(Exception e) {
630
                    e.printStackTrace();
631
                    sb.append("<INFO>").append("Info format not supported").append("</INFO>");
632
                    return sb.toString();
633
            }
634
    }
635

    
636
    /**
637
         * <p>Builds a GetCapabilities request that is sent to the WMS
638
         * the response will be parse to extract the data needed by the
639
         * WMS client</p>
640
         * @param override, if true the previous downloaded data will be overridden
641
         */
642
    public void getCapabilities(WMTSServerDescription status, boolean override, ICancellable cancel) {
643
            try {
644
                    serverDescription = status;
645
                        WMTSGetCapabilitiesRequest request = createGetCapabilitiesRequest();
646
                        File f = request.sendRequest(cancel);                        
647
        
648
                        if (f == null)
649
                                return;
650
                        parseCapabilities(f);
651
            } catch(Exception e) {
652
                        e.printStackTrace();
653
                }
654
    }
655
    
656
    
657
    /**
658
     * Builds the GetCapabilitiesRequest according to the OGC WMS Specifications
659
     * without a VERSION, to get the highest version than a WMS supports.
660
     */
661
    public static String buildCapabilitiesSuitableVersionRequest(String _host, String _version) {
662
                int index = _host.indexOf('?');
663
                
664
                if (index > -1) {
665
                        String host = _host.substring(0, index + 1);
666
                        String query = _host.substring(index + 1, _host.length());
667
                        
668
                        StringTokenizer tokens = new StringTokenizer(query, "&");
669
                        String newQuery = "", token;
670

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

    
675
                                if (token.toUpperCase().compareTo("REQUEST=GETCAPABILITIES") == 0)
676
                                        continue;
677

    
678
                                if (token.toUpperCase().compareTo("SERVICE=WMTS") == 0)
679
                                        continue;
680

    
681
                                if ((_version != null) && (_version.length() > 0)) {
682
                                    if (token.toUpperCase().compareTo("VERSION=" + _version) == 0)
683
                                            continue;
684
                                }
685

    
686
                                if (token.toUpperCase().compareTo("EXCEPTIONS=XML") == 0)
687
                                        continue;
688

    
689
                                newQuery += token + "&";
690
                        }
691

    
692
                _host = host + newQuery;
693
                }
694
                else {
695
                        _host += "?";
696
                }
697

    
698
            if ((_version != null) && (_version.compareTo("") != 0))
699
                    _host += "REQUEST=GetCapabilities&SERVICE=WMTS&VERSION=" + _version;
700
            else
701
                    _host += "REQUEST=GetCapabilities&SERVICE=WMTS";
702

    
703
            return _host;
704
    }
705
    
706
        protected String parseException(byte[] data) throws IOException {
707
        List<String> errors = new ArrayList<String>();
708
        KXmlParser kxmlParser = new KXmlParser();
709
        try
710
        {
711
            kxmlParser.setInput(new ByteArrayInputStream(data), encoding);
712
            kxmlParser.nextTag();
713
            int tag;
714
            if ( kxmlParser.getEventType() != KXmlParser.END_DOCUMENT )
715
            {
716
                kxmlParser.require(KXmlParser.START_TAG, null, Tags.EXCEPTION_ROOT);
717
                tag = kxmlParser.nextTag();
718
                 while(tag != KXmlParser.END_DOCUMENT)
719
                 {
720
                     switch(tag)
721
                     {
722
                        case KXmlParser.START_TAG:
723
                            if (kxmlParser.getName().compareTo(Tags.SERVICE_EXCEPTION)==0){
724
                                String errorCode = kxmlParser.getAttributeValue("", Tags.CODE);
725
                                errorCode = (errorCode != null) ? "["+errorCode+"] " : "";
726
                                String errorMessage = kxmlParser.nextText();
727
                                errors.add(errorCode + errorMessage);
728
                            }
729
                            break;
730
                        case KXmlParser.END_TAG:
731
                            break;
732

    
733
                     }
734
                     tag = kxmlParser.nextTag();
735
                 }
736
                 //kxmlParser.require(KXmlParser.END_DOCUMENT, null, null);
737
            }
738
        }
739
        catch(XmlPullParserException parser_ex){
740
            throw new IOException(parser_ex.getMessage());
741
        }
742
       
743
        String message = errors.size() > 0? "" : null;
744
        for (int i = 0; i < errors.size(); i++) {
745
            message += (String) errors.get(i)+"\n";
746
        }
747
        return message;
748
    }
749
    
750
 }