Statistics
| Revision:

root / branches / Mobile_Compatible_Hito_1 / libFMap / src / es / prodevelop / gvsig / mobile / fmap / driver / raster / wms / WMSProtocolHandler.java @ 21606

History | View | Annotate | Download (24 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2006 Prodevelop 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
 *   http://www.gvsig.gva.es
30
 *
31
 *    or
32
 *
33
 *   Prodevelop Integraci?n de Tecnolog?as SL
34
 *   Conde Salvatierra de ?lava , 34-10
35
 *   46004 Valencia
36
 *   Spain
37
 *
38
 *   +34 963 510 612
39
 *   +34 963 510 968
40
 *   gis@prodevelop.es
41
 *   http://www.prodevelop.es
42
 *
43
 *    or
44
 *
45
 *   Instituto de Rob?tica
46
 *   Apartado de correos 2085
47
 *   46071 Valencia
48
 *   (Spain)
49
 *   
50
 *   +34 963 543 577
51
 *   jjordan@robotica.uv.es
52
 *   http://robotica.uv.es
53
 *   
54
 */
55

    
56
package es.prodevelop.gvsig.mobile.fmap.driver.raster.wms;
57

    
58
import java.awt.geom.Rectangle2D;
59
import java.io.ByteArrayInputStream;
60
import java.io.File;
61
import java.io.FileInputStream;
62
import java.io.FileReader;
63
import java.io.IOException;
64
import java.io.StringReader;
65
import java.net.URL;
66
import java.util.ArrayList;
67

    
68
import org.apache.log4j.Logger;
69
import org.kxml2.io.KXmlParser;
70
import org.xmlpull.v1.XmlPullParserException;
71

    
72
import es.prodevelop.gvsig.mobile.fmap.util.download.DownloadTask;
73
import es.prodevelop.gvsig.mobile.fmap.util.download.Downloader;
74
import es.prodevelop.gvsig.mobile.fmap.util.string.StringUtilities;
75

    
76
/**
77
 * 
78
 * This is the class that interacts with the WMS drivers. Sends requests
79
 * (capabilities, images, etc) and
80
 * starts the parsing process. It also instantiates the root of the layer descriptions
81
 * tree, and provides a getter used by the WMS dialog to show the results.
82
 * 
83
 * @see es.prodevelop.gvsig.mobile.fmap.driver.raster.wms.WmsRasterDriver
84
 * @see es.prodevelop.gvsig.mobile.fmap.driver.raster.wms.WMSLayerDescription
85
 * 
86
 * @author iver
87
 * @author jldominguez
88
 *
89
 */
90
public class WMSProtocolHandler {
91

    
92
        private static Logger logger = Logger.getLogger(WMSProtocolHandler.class);
93

    
94
        public static final String DEFAULT_WMS_VERSION = "1.1.1";
95
        private String encoding = "UTF-8";
96
        private String host;
97
        // private String port;
98
        private String version = "";
99
        private String symbol = "";
100

    
101
        public WMSLayerDescription root;
102
        private boolean infoable = false;
103
        private ArrayList formats = new ArrayList();
104
        private ArrayList infoFormats = new ArrayList();
105

    
106
        /**
107
         * @return the root of the layer descriptions tree
108
         */
109
        public WMSLayerDescription getRoot() {
110
                return root;
111
        }
112

    
113
        /**
114
         * Removes all the objects owned by this object. This is used when the WMS dialog closes,
115
         * in order to prevent memory leaks. 
116
         *
117
         */
118
        public void delete() {
119

    
120
                if (root != null) root.delete();
121
                formats.clear();
122
                formats = null;
123
                infoFormats.clear();
124
                infoFormats = null;
125
        }
126
        
127
        /**
128
         * Sets the WMS protocol version (1.1.1, etc)
129
         * 
130
         * @param v the WMS protocol version
131
         */
132
        public void setVersion(String v) {
133
                version = v;
134
        }
135
        
136
        /**
137
         * Sets the path separator symbol to use with the current WMS server
138
         * @param s the path separator symbol to use with the current WMS server
139
         */
140
        public void setSymbol(String s) {
141
                symbol = s;
142
        }
143
        
144
        /**
145
         * 
146
         * @return the WMS protocol version (1.1.1, etc)
147
         */
148
        public String getVersion() {
149
                return version;
150
        }
151
        
152
        /**
153
         * 
154
         * @return the path separator symbol to use with the current WMS server
155
         */
156
        public String getSymbol() {
157
                return symbol;
158
        }
159
        
160

    
161
        /**
162
         * 
163
         * @return an array with the image formats supoprted by the current WMS server
164
         */
165
        public ArrayList getFormats() {
166
                return formats;
167
        }
168

    
169
        /**
170
         * 
171
         * @return an array with the image formats supported by the current WMS server
172
         */
173
        public ArrayList getInfoFormats() {
174
                return infoFormats;
175
        }
176

    
177
        /**
178
         * 
179
         * @return whether the layer described by this object is declared as infoable by
180
         * the server in the getcapabilities response
181
         */
182
        public boolean isInfoable() {
183
                return infoable;
184
        }
185

    
186
            
187
        /**
188
         * 
189
         * @return the host url
190
         */
191
        public String getHost() {
192
                return host;
193
        }
194

    
195
        /**
196
         * Sets the host url
197
         * @param _host the new host url
198
         */
199
        public void setHost(String _host) {
200
                host = _host;
201
        }
202

    
203
        /**
204
         * This method starts the get capabilities request process and parses the result.
205
         * 
206
         * @param version the WMS protocol version to be used
207
         * @param sym the path separator symbol to be used when building requests
208
         * @return whether the get capabilities request was completed successfully
209
         */
210
        public boolean getCapabilities(String version, String sym) {
211

    
212
                URL request = null;
213
                try {
214
                        request = new URL(buildCapabilitiesRequest(host, version, sym));
215
                } catch (Exception e) {
216
                        logger.error("Bad capabilities request URL: " + e.getMessage());
217
                }
218

    
219
                try {
220
                        // File f = Downloader.get(request, "cap");
221

    
222
                        File f = (File) Downloader.downloadObjectCancel(request, "cap",
223
                                        DownloadTask.FILE, "wms", null, true);
224

    
225
                        if (f == null) {
226
                                logger.error("capabilities file is null");
227
                                return false;
228
                        }
229
                        clear();
230
                        parse(f);
231
                } catch (Exception e) {
232
                        logger.error("While downloading/parsing WMS capabilities file: "
233
                                        + e.getMessage());
234
                        return false;
235
                }
236

    
237
                // in case root has no SRS:
238
                avoidEmptySRSInRoot();
239

    
240
                return true;
241
        }
242

    
243
        private void avoidEmptySRSInRoot() {
244

    
245
                if (root == null)
246
                        return;
247
                if (root.getAvailableSRS().length > 0)
248
                        return;
249

    
250
                logger
251
                                .debug("Root layer has no SRS array. Those of its first-level children will be added...");
252

    
253
                int cnt = root.getChildrenCount();
254
                for (int i = (cnt - 1); i >= 0; i--) {
255
                        WMSLayerDescription desc = root.getChild(i);
256
                        String[] ava_srs = desc.getAvailableSRS();
257
                        for (int j = 0; j < ava_srs.length; j++) {
258
                                String item_srs = ava_srs[j];
259
                                Rectangle2D ext = desc.getExtentForSRS(item_srs);
260
                                root.increaseExtentForSRS(item_srs, ext);
261
                        }
262
                }
263
        }
264

    
265
        private String buildCapabilitiesRequest(String h, String v, String sym) {
266
                return h + sym + "REQUEST=GetCapabilities&SERVICE=WMS&VERSION=" + v
267
                                + "&EXCEPTIONS=XML";
268
        }
269

    
270
        private void clear() {
271
                infoable = false;
272
                root = new WMSLayerDescription(0, null);
273
                formats.clear();
274
                infoFormats.clear();
275
        }
276

    
277
        protected String parseException(byte[] data) {
278
                ArrayList errors = new ArrayList();
279
                KXmlParser kxmlParser = new KXmlParser();
280
                try {
281
                        kxmlParser.setInput(new ByteArrayInputStream(data), encoding);
282
                        kxmlParser.nextTag();
283
                        int tag;
284
                        if (kxmlParser.getEventType() != KXmlParser.END_DOCUMENT) {
285
                                kxmlParser.require(KXmlParser.START_TAG, null,
286
                                                EXCEPTION_TAGS_EXCEPTION_ROOT);
287
                                tag = kxmlParser.nextTag();
288
                                while (tag != KXmlParser.END_DOCUMENT) {
289
                                        switch (tag) {
290
                                        case KXmlParser.START_TAG:
291
                                                if (kxmlParser.getName().compareTo(
292
                                                                EXCEPTION_TAGS_SERVICE_EXCEPTION) == 0) {
293
                                                        String errorCode = kxmlParser.getAttributeValue("",
294
                                                                        EXCEPTION_TAGS_CODE);
295
                                                        errorCode = (errorCode != null) ? "[" + errorCode
296
                                                                        + "] " : "";
297
                                                        String errorMessage = kxmlParser.nextText();
298
                                                        errors.add(errorCode + errorMessage);
299
                                                }
300
                                                break;
301
                                        case KXmlParser.END_TAG:
302
                                                break;
303

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

    
321
        /**
322
         * Closes the protocol handler. Currently empty.
323
         *
324
         */
325
        public void close() {
326
                // your code here
327
        }
328

    
329
        /**
330
         * Tag used when parsing WMS responses 
331
         */
332
        public final static String EXCEPTION_TAGS_EXCEPTION_ROOT = "ServiceExceptionReport";
333
        /**
334
         * Tag used when parsing WMS responses 
335
         */
336
        public final static String EXCEPTION_TAGS_SERVICE_EXCEPTION = "ServiceException";
337
        /**
338
         * Tag used when parsing WMS responses 
339
         */
340
        public final static String EXCEPTION_TAGS_CODE = "code";
341

    
342
        /**
343
         * Main parse method.
344
         * 
345
         * @param f file to be parsed
346
         */
347
        private void parse(File f) {
348

    
349
                FileReader reader = null;
350
                try {
351
                        reader = new FileReader(f);
352

    
353
                        //                            FileInputStream fis = new FileInputStream(f);
354
                        //                            InputStreamReader reader = new InputStreamReader(fis,"ISO-8859-1");
355
                        // BufferedReader br = new BufferedReader(reader);
356

    
357
                        char[] buffer = new char[100];
358
                        reader.read(buffer);
359
                        StringBuffer strBuff = new StringBuffer();
360
                        strBuff.append(buffer);
361
                        String auxStr = strBuff.toString().toLowerCase();
362
                        int a = auxStr.toLowerCase().indexOf("<?xml");
363
                        if (a != -1)
364
                                auxStr = auxStr.substring(a, auxStr.length());
365

    
366
                        StringBuffer st = new StringBuffer(auxStr);
367
                        String searchText = "encoding=\"";
368
                        int index = st.indexOf(searchText);
369

    
370
                        if (index > -1) {
371
                                st.delete(0, index + searchText.length());
372
                                encoding = st.substring(0, st.indexOf("\""));
373
                        }
374
                        
375
                        reader.close();
376
                        
377
                } catch (Exception ex) {
378
                        logger.error("In main parse method: " + ex.getMessage());
379
                }
380

    
381
                int tag;
382
                KXmlParser kxmlParser = null;
383
                kxmlParser = new KXmlParser();
384
                try {
385
//                        reader = new FileReader(f);
386
//                        //                            FileInputStream fis = new FileInputStream(f);
387
//                        //                            InputStreamReader reader = new InputStreamReader(fis,"ISO-8859-1");
388
//                        // BufferedReader br = new BufferedReader(reader);
389
//                        // patch for ArcIMS + WMS connector > 9.0 bug
390
//                        
391
//                        char[] buffer = new char[(int) f.length()];
392
//                        
393
//                        logger.debug("PHONEME - buffer.len = " + buffer.length);
394
//                        
395
//                        reader.read(buffer);
396
//                        
397
//                        StringBuffer strBuff = new StringBuffer();
398
//                        strBuff.append(buffer);
399
//                        String auxStr = strBuff.toString();
400
//                        
401
//                        logger.debug("PHONEME - auxStr = " + auxStr);
402
//                        // String string = new String(buffer);
403
//                        
404
//                        int a = auxStr.toLowerCase().indexOf("<?xml");
405
//                        
406
//                        logger.debug("PHONEME - a = " + a);
407
//                        
408
//                        if (a != -1) {
409
//                                auxStr = auxStr.substring(a, auxStr.length());
410
//                                logger.debug("PHONEME - auxStr = " + auxStr);
411
//                                kxmlParser.setInput(new StringReader(auxStr));
412
//                        } else
413
//                                // end patch
414
//                                kxmlParser.setInput(new FileInputStream(f), encoding);
415

    
416
                        
417
                        FileInputStream fir = new FileInputStream(f);
418
                        kxmlParser.setInput(fir, encoding);
419
                        
420
                        
421
                        logger.debug("PHONEME - kxmlParser.nextTag();");
422
                        
423
                        kxmlParser.nextTag();
424
                        if (kxmlParser.getEventType() != KXmlParser.END_DOCUMENT) {
425
                                kxmlParser.require(KXmlParser.START_TAG, null,
426
                                                CapabilitiesTags.CAPABILITIES_ROOT1_1_1);
427
                                tag = kxmlParser.nextTag();
428
                                while (tag != KXmlParser.END_DOCUMENT) {
429
                                        switch (tag) {
430

    
431
                                        case KXmlParser.START_TAG:
432
                                                if (kxmlParser.getName().compareTo(
433
                                                                CapabilitiesTags.SERVICE) == 0) {
434
                                                        // parseServiceTag(kxmlParser);
435
                                                } else if (kxmlParser.getName().compareTo(
436
                                                                CapabilitiesTags.CAPABILITY) == 0) {
437
                                                        parseCapabilityTag(kxmlParser);
438
                                                }
439
                                                break;
440
                                        case KXmlParser.END_TAG:
441
                                                break;
442
                                        case KXmlParser.TEXT:
443
                                                break;
444
                                        }
445
                                        tag = kxmlParser.next();
446
                                }
447
                                kxmlParser.require(KXmlParser.END_DOCUMENT, null, null);
448
                                fir.close();
449
                        }
450
                } catch (XmlPullParserException parser_ex) {
451
                        logger.error("Parser exception: " + parser_ex.getMessage());
452
                } catch (IOException ioe) {
453
                        logger.error("IO exception: " + ioe.getMessage());
454
                } finally {
455

    
456
                }
457
                // In the parsing process the layer has been filled
458
        }
459

    
460
        /**
461
         * <p>Parses the Service Information </p>
462
         */
463

    
464
        /*
465
         private void parseServiceTag(KXmlParser parser) throws IOException, XmlPullParserException
466
         {
467
         int currentTag;
468
         boolean end = false;
469

470
         parser.require(KXmlParser.START_TAG, null, CapabilitiesTags.SERVICE);
471
         currentTag = parser.next();
472

473
         while (!end)
474
         {
475
         switch(currentTag)
476
         {
477
         case KXmlParser.START_TAG:
478
         if (parser.getName().compareTo(CapabilitiesTags.NAME)==0)
479
         {
480
         serviceInfo.name = parser.nextText();
481
         }
482
         else if (parser.getName().compareTo(CapabilitiesTags.TITLE)==0)
483
         {
484
         serviceInfo.title = parser.nextText();
485
         }
486
         else if (parser.getName().compareTo(CapabilitiesTags.ABSTRACT)==0)
487
         {
488
         serviceInfo.abstr = parser.nextText();
489
         }
490
         else if (parser.getName().compareTo(CapabilitiesTags.ONLINERESOURCE)==0)
491
         {
492
         String value = new String();
493
         value = parser.getAttributeValue("", CapabilitiesTags.XLINK_HREF);
494
         if (value != null){
495
         serviceInfo.online_resource = value;
496
         }
497
         }
498
         else if ((parser.getName().compareTo(CapabilitiesTags.KEYWORDLIST)==0) ||
499
         (parser.getName().compareTo(CapabilitiesTags.CONTACTINFORMATION)==0))
500
         {
501
         parser.skipSubTree();
502
         }
503
         break;
504
         case KXmlParser.END_TAG:
505
         if (parser.getName().compareTo(CapabilitiesTags.SERVICE) == 0)
506
         end = true;
507
         break;
508
         case KXmlParser.TEXT:
509
         break;
510
         }
511
         if (!end)
512
         currentTag = parser.next();
513
         }
514
         parser.require(KXmlParser.END_TAG, null, CapabilitiesTags.SERVICE);
515
         }
516
         */
517

    
518
        /**
519
         * <p>Parses the Capability Tag </p>
520
         */
521
        private void parseCapabilityTag(KXmlParser parser) throws IOException,
522
                        XmlPullParserException {
523
                int currentTag;
524
                boolean end = false;
525

    
526
                parser.require(KXmlParser.START_TAG, null, CapabilitiesTags.CAPABILITY);
527
                currentTag = parser.next();
528

    
529
                while (!end) {
530
                        switch (currentTag) {
531
                        case KXmlParser.START_TAG:
532
                                if (parser.getName().compareTo(CapabilitiesTags.REQUEST) == 0) {
533
                                        parseRequestTag(parser);
534
                                } else if (parser.getName().compareTo(
535
                                                CapabilitiesTags.EXCEPTION) == 0) {
536
                                        //TODO:
537
                                        //Add to serviceInfo the supported formats for the exceptions????
538
                                } else if (parser.getName().compareTo(CapabilitiesTags.LAYER) == 0) {
539
                                        int curr_tag = root.parseAsRoot(parser);
540
                                        end = ((parser.getName().compareTo(
541
                                                        CapabilitiesTags.CAPABILITY) == 0) && (curr_tag == KXmlParser.END_TAG));
542
                                } else if ((parser.getName().compareTo(
543
                                                CapabilitiesTags.VENDORSPECIFICCAPABILITIES) == 0)
544
                                                || (parser.getName().compareTo(
545
                                                                CapabilitiesTags.USERDEFINEDSYMBOLIZATION) == 0)
546
                                                || (parser.getName().compareTo(CapabilitiesTags.STYLE) == 0))
547

    
548
                                {
549
                                        parser.skipSubTree();
550
                                }
551
                                break;
552
                        case KXmlParser.END_TAG:
553
                                if (parser.getName().compareTo(CapabilitiesTags.CAPABILITY) == 0)
554
                                        end = true;
555
                                break;
556
                        case KXmlParser.TEXT:
557
                                break;
558
                        }
559
                        if (!end)
560
                                currentTag = parser.next();
561
                }
562
                //parser.require(KXmlParser.END_TAG, null, CapabilitiesTags.CAPABILITY);
563
        }
564

    
565
        /**
566
         * <p>Parses the Request tag </p>
567
         */
568
        private void parseRequestTag(KXmlParser parser) throws IOException,
569
                        XmlPullParserException {
570
                int currentTag;
571
                boolean end = false;
572

    
573
                parser.require(KXmlParser.START_TAG, null, CapabilitiesTags.REQUEST);
574
                currentTag = parser.next();
575

    
576
                while (!end) {
577
                        switch (currentTag) {
578
                        case KXmlParser.START_TAG:
579
                                if (parser.getName().compareTo(CapabilitiesTags.GETMAP) == 0) {
580
                                        parseGetMapTag(parser);
581
                                } else if (parser.getName().compareTo(
582
                                                CapabilitiesTags.GETFEATUREINFO) == 0) {
583
                                        infoable = true;
584
                                        parseGetFeatureInfoTag(parser);
585
                                }
586
                                break;
587
                        case KXmlParser.END_TAG:
588
                                if (parser.getName().compareTo(CapabilitiesTags.REQUEST) == 0)
589
                                        end = true;
590
                                break;
591
                        case KXmlParser.TEXT:
592
                                break;
593
                        }
594
                        if (!end)
595
                                currentTag = parser.next();
596
                }
597
                // TODO: does not get such a tag when arrives here!!!!!!
598
                //parser.require(KXmlParser.END_TAG, null, CapabilitiesTags.REQUEST);
599
        }
600

    
601
        /**
602
         * <p>Parses the GetMap tag </p>
603
         */
604
        private void parseGetMapTag(KXmlParser parser) throws IOException,
605
                        XmlPullParserException {
606
                int currentTag;
607
                boolean end = false;
608

    
609
                parser.require(KXmlParser.START_TAG, null, CapabilitiesTags.GETMAP);
610
                currentTag = parser.next();
611

    
612
                while (!end) {
613
                        switch (currentTag) {
614
                        case KXmlParser.START_TAG:
615
                                if (parser.getName().compareTo(CapabilitiesTags.FORMAT) == 0) {
616
                                        String f = parser.nextText();
617
                                        if (validFormat(f)) {
618
                                                formats.add(f);
619
                                        }
620

    
621
                                }
622
                                /*
623
                                 else if (parser.getName().compareTo(CapabilitiesTags.DCPTYPE)==0)
624
                                 {
625
                                 currentTag = parser.nextTag();
626
                                 if(parser.getName().compareTo(CapabilitiesTags.HTTP)==0)
627
                                 {
628
                                 currentTag = parser.nextTag();
629
                                 if(parser.getName().compareTo(CapabilitiesTags.GET)==0)
630
                                 {
631
                                 currentTag = parser.nextTag();
632
                                 if (parser.getName().compareTo(CapabilitiesTags.ONLINERESOURCE)==0)
633
                                 {
634
                                 String value = new String();
635
                                 value = parser.getAttributeValue("", CapabilitiesTags.XLINK_HREF);
636
                                 if (value != null){
637
                                 serviceInfo.operations.put(CapabilitiesTags.GETMAP, value);
638
                                 }
639
                                 }
640
                                 }
641
                                 }
642
                                 }
643
                                 */
644
                                break;
645
                        case KXmlParser.END_TAG:
646
                                if (parser.getName().compareTo(CapabilitiesTags.GETMAP) == 0)
647
                                        end = true;
648
                                break;
649
                        case KXmlParser.TEXT:
650
                                break;
651
                        }
652
                        if (!end)
653
                                currentTag = parser.next();
654
                }
655
        }
656

    
657
        private boolean validFormat(String f) {
658

    
659
                String format = f.toLowerCase();
660
                if (format.indexOf("jpg") != -1)
661
                        return true;
662
                if (format.indexOf("jpeg") != -1)
663
                        return true;
664
                if (format.indexOf("gif") != -1)
665
                        return true;
666
                if (format.indexOf("png") != -1)
667
                        return true;
668
                return false;
669
        }
670

    
671
        /**
672
         * <p>Parses the GetFeatureInfoTag tag </p>
673
         */
674

    
675
        private void parseGetFeatureInfoTag(KXmlParser parser) throws IOException,
676
                        XmlPullParserException {
677
                int currentTag;
678
                boolean end = false;
679

    
680
                parser.require(KXmlParser.START_TAG, null,
681
                                CapabilitiesTags.GETFEATUREINFO);
682
                currentTag = parser.next();
683

    
684
                while (!end) {
685
                        switch (currentTag) {
686
                        case KXmlParser.START_TAG:
687
                                if (parser.getName().compareTo(CapabilitiesTags.FORMAT) == 0) {
688
                                        //TODO:
689
                                        // add the supported formats by the GetFeatureInfo request
690
                                        infoFormats.add(parser.nextText());
691
                                        //serviceInfo.formats.add(parser.nextText());
692
                                }
693
                                /*
694
                                 else if (parser.getName().compareTo(CapabilitiesTags.DCPTYPE)==0)
695
                                 {
696
                                 currentTag = parser.nextTag();
697
                                 if(parser.getName().compareTo(CapabilitiesTags.HTTP)==0)
698
                                 {
699
                                 currentTag = parser.nextTag();
700
                                 if(parser.getName().compareTo(CapabilitiesTags.GET)==0)
701
                                 {
702
                                 currentTag = parser.nextTag();
703
                                 if (parser.getName().compareTo(CapabilitiesTags.ONLINERESOURCE)==0)
704
                                 {
705
                                 String value = new String();
706
                                 value = parser.getAttributeValue("", CapabilitiesTags.XLINK_HREF);
707
                                 if (value != null){
708
                                 serviceInfo.operations.put(CapabilitiesTags.GETFEATUREINFO, value);
709
                                 }
710
                                 }
711
                                 }
712
                                 }
713
                                 }
714
                                 */
715
                                break;
716
                        case KXmlParser.END_TAG:
717
                                if (parser.getName().compareTo(CapabilitiesTags.GETFEATUREINFO) == 0)
718
                                        end = true;
719
                                break;
720
                        case KXmlParser.TEXT:
721
                                break;
722
                        }
723
                        if (!end)
724
                                currentTag = parser.next();
725
                }
726
        }
727

    
728
        /**
729
         * Utility method to find out the convenient path separator symbol for a given url string.
730
         * @param url the URL of interest
731
         * @return the convenient path separator symbol
732
         */
733
        public static String getSymbol(String url) {
734

    
735
                String symbol;
736

    
737
                if (url.indexOf("?") == -1)
738
                        symbol = "?";
739
                else if (url.indexOf("?") != url.length() - 1)
740
                        symbol = "&";
741
                else
742
                        symbol = "";
743

    
744
                return symbol;
745
        }
746

    
747
        private static String getVersionQueryRequest(String _host) {
748

    
749
                String req = "";
750
                String symbol = getSymbol(_host);
751
                req = req + _host + symbol + "REQUEST=GetCapabilities&SERVICE=WMS&";
752
                req += ("&EXCEPTIONS=XML");
753
                return req;
754
        }
755

    
756
        /**
757
         * Sends a GetCapabilities to the WMS server to get the version
758
         * if the version parameter is null, the WMS will return the highest version supported
759
         * if not it will return the lower highest version than the one requested.
760
         * @param host host URL
761
         * @return suitable version supported by the server 
762
         */
763
        public static String getSuitableWMSVersion(URL host)
764
                        throws BadWMSResponseException {
765

    
766
                String request = getVersionQueryRequest(host.toString());
767
                String version = "";
768

    
769
                byte[] version_bytes = null;
770

    
771
                try {
772

    
773
                        URL req_url = new URL(request);
774

    
775
                        version_bytes = (byte[]) Downloader.downloadObjectCancel(req_url,
776
                                        "", DownloadTask.BYTE_ARRAY, "", "", false);
777

    
778
                } catch (Exception ex) {
779

    
780
                        logger.error("While getting version request response: "
781
                                        + ex.getMessage());
782
                        throw new BadWMSResponseException(ex.getMessage());
783
                }
784

    
785
                String response = new String(version_bytes);
786

    
787
                int a = response.toLowerCase().indexOf("<?xml");
788
                if (a != -1) {
789
                        response = response.substring(a, response.length());
790
                }
791

    
792
                StringReader reader = new StringReader(response);
793
                KXmlParser kxmlParser = null;
794
                kxmlParser = new KXmlParser();
795

    
796
                try {
797
                        kxmlParser.setInput(reader);
798
                        kxmlParser.nextTag();
799

    
800
                        if (kxmlParser.getEventType() != KXmlParser.END_DOCUMENT) {
801
                                if ((kxmlParser.getName().compareTo(
802
                                                CapabilitiesTags.CAPABILITIES_ROOT1_1_0) == 0)
803
                                                || (kxmlParser.getName().compareTo(
804
                                                                CapabilitiesTags.CAPABILITIES_ROOT1_1_1) == 0)
805
                                                || (kxmlParser.getName().compareTo(
806
                                                                CapabilitiesTags.CAPABILITIES_ROOT1_3_0) == 0)) {
807
                                        version = kxmlParser.getAttributeValue("",
808
                                                        CapabilitiesTags.VERSION);
809
                                }
810
                        }
811
                        // do not forget to close the Stream.                    
812
                        reader.close();
813

    
814
                        if (version.length() == 0) {
815
                                throw new BadWMSResponseException("No WMS version found.");
816
                        }
817

    
818
                        return version;
819

    
820
                } catch (Exception ex) {
821
                        logger.error("While parsing version request response: "
822
                                        + ex.getMessage());
823
                        throw new BadWMSResponseException(ex.getMessage());
824
                } finally {
825
                        if (reader != null) {
826
                                reader.close();
827
                        }
828
                }
829
        }
830

    
831
        /**
832
         * This method excludes from a comma separated string of IDs, the ones that are not infoable.
833
         * It is used for querying only on queriable layers, and prevents empty responses on some
834
         * WMS servers.
835
         *  
836
         * @param all_csv comma separated string of all layers requested by the user
837
         * @param root the layer description object of the root layer
838
         * @param getname whether we wanrt to get the names or the IDs of the layers
839
         * @return a comma separated string with the IDs or names of the queryable layers
840
         */
841
        public static String leaveInfoable(String all_csv,
842
                        WMSLayerDescription root, boolean getname) {
843

    
844
                String[] all_array = StringUtilities.split(all_csv, ",");
845
                ArrayList resp = new ArrayList();
846
                addRecursiveYourselfIfPresent(root, all_array, resp, getname);
847

    
848
                String _resp = null;
849
                int sz = resp.size();
850
                if (sz > 0) {
851
                        _resp = "";
852
                        for (int i = 0; i < sz; i++)
853
                                _resp = _resp + "," + ((String) resp.get(i));
854
                        _resp = _resp.substring(1);
855
                }
856
                return _resp;
857

    
858
        }
859

    
860
        private static void addRecursiveYourselfIfPresent(WMSLayerDescription desc,
861
                        String[] sel, ArrayList resp, boolean getname) {
862

    
863
                if (desc.isInfoable() && isOneOf(desc.getLayerId(), sel)) {
864
                        if (getname) {
865
                                // name
866
                                resp.add(desc.getLayerName());
867
                        } else {
868
                                // id
869
                                resp.add(desc.getLayerId());
870
                        }
871

    
872
                }
873

    
874
                for (int i = 0; i < desc.getChildrenCount(); i++) {
875
                        addRecursiveYourselfIfPresent(desc.getChild(i), sel, resp, getname);
876
                }
877
        }
878
        
879
        
880
        
881
        private static void addRecursiveYourselfIfPresentNew(WMSLayerDescription desc,
882
                        String[] sel, ArrayList resp, boolean getname) {
883

    
884
                if (isOneOf(desc.getLayerId(), sel)) {
885
                        
886
                        if (desc.isInfoable()) {
887
                                if (getname) {
888
                                        resp.add(desc.getLayerName()); // name
889
                                } else {
890
                                        resp.add(desc.getLayerId()); // id
891
                                }
892
                        }
893
                        addAllInfoableChildren(desc, resp, getname);
894

    
895
                } else {
896
                        
897
                        // ---------- search children
898
                        for (int i = 0; i < desc.getChildrenCount(); i++) {
899
                                addRecursiveYourselfIfPresentNew(desc.getChild(i), sel, resp, getname);
900
                        }
901
                        
902
                }
903

    
904
        }
905
        
906
        private static void addAllInfoableChildren(
907
                        WMSLayerDescription desc,
908
                        ArrayList resp,
909
                        boolean getname) {
910

    
911
                for (int i = 0; i < desc.getChildrenCount(); i++) {
912

    
913
                        WMSLayerDescription ch = desc.getChild(i);
914
                        if (ch.isInfoable()) {
915
                                if (getname) {
916
                                        resp.add(ch.getLayerName());
917
                                } else {
918
                                        resp.add(ch.getLayerId());
919
                                }
920
                        }
921
                        addAllInfoableChildren(ch, resp, getname);
922
                }
923
        }
924

    
925
        private static boolean isOneOf(String str, String[] arr) {
926

    
927
                for (int i = 0; i < arr.length; i++) {
928
                        if (str.compareTo(arr[i]) == 0)
929
                                return true;
930
                }
931
                return false;
932

    
933
        }
934

    
935
}
936