Statistics
| Revision:

root / trunk / libraries / libArcIMS / src / org / gvsig / remoteClient / arcims / ArcImsProtocolHandler.java @ 8109

History | View | Annotate | Download (44.5 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
 *   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

    
44
package org.gvsig.remoteClient.arcims;
45

    
46
import com.iver.cit.gvsig.fmap.core.v02.FConstant;
47
import com.iver.cit.gvsig.fmap.rendering.Legend;
48

    
49
import org.apache.log4j.Logger;
50

    
51
import org.gvsig.remoteClient.arcims.exceptions.ArcImsException;
52
import org.gvsig.remoteClient.arcims.styling.renderers.ArcImsFLegendFactory;
53
import org.gvsig.remoteClient.arcims.styling.renderers.ArcImsRendererFactory;
54
import org.gvsig.remoteClient.arcims.styling.renderers.Renderer;
55
import org.gvsig.remoteClient.arcims.utils.ArcImsDownloadUtils;
56
import org.gvsig.remoteClient.arcims.utils.CatalogInfoTags;
57
import org.gvsig.remoteClient.arcims.utils.FieldInformation;
58
import org.gvsig.remoteClient.arcims.utils.GetVariables;
59
import org.gvsig.remoteClient.arcims.utils.ServiceInfoTags;
60
import org.gvsig.remoteClient.arcims.utils.ServiceInformation;
61
import org.gvsig.remoteClient.arcims.utils.ServiceInformationLayer;
62
import org.gvsig.remoteClient.arcims.utils.ServiceInformationLayerFeatures;
63
import org.gvsig.remoteClient.arcims.utils.ServiceInformationLayerImage;
64
import org.gvsig.remoteClient.utils.BoundaryBox;
65

    
66
import org.kxml2.io.KXmlParser;
67

    
68
import org.xmlpull.v1.XmlPullParserException;
69

    
70
import java.awt.geom.Rectangle2D;
71

    
72
import java.io.BufferedReader;
73
import java.io.File;
74
import java.io.FileInputStream;
75
import java.io.FileNotFoundException;
76
import java.io.FileReader;
77
import java.io.IOException;
78
import java.io.InputStreamReader;
79
import java.io.Reader;
80
import java.io.UnsupportedEncodingException;
81

    
82
import java.net.ConnectException;
83
import java.net.HttpURLConnection;
84
import java.net.MalformedURLException;
85
import java.net.URL;
86

    
87
import java.text.DecimalFormatSymbols;
88

    
89
import java.util.ArrayList;
90
import java.util.Locale;
91
import java.util.TreeMap;
92
import java.util.Vector;
93

    
94

    
95
/**
96
 * Abstract class that represents handlers to comunicate via ArcIms protocol
97
 *
98
 * @author jsanz
99
 * @author jcarrasco
100
 *
101
 */
102
public abstract class ArcImsProtocolHandler {
103
    public static final double INCHES = .02540005;
104
    private static Logger logger = Logger.getLogger(ArcImsProtocolHandler.class.getName());
105

    
106
    /**
107
     * Protocol handler name
108
     */
109
    protected String name;
110

    
111
    /**
112
     * protocol handler version
113
     */
114
    protected String version;
115

    
116
    /**
117
     * host of the ArcIms to connect
118
     */
119
    protected String host;
120

    
121
    /**
122
     * port number of the comunication channel of the ArcIms to connect
123
     */
124
    protected String port;
125
    protected String service;
126

    
127
    /**
128
     * ArcIms metadata
129
     */
130
    protected ServiceInformation serviceInfo;
131
    public TreeMap layers;
132

    
133
    //public ArcImsLayer rootLayer;
134
    public Vector srs;
135

    
136
    public ArcImsProtocolHandler() {
137
        this.version = "4.0.1";
138
        this.name = "ArcIms4.0.1";
139
        this.serviceInfo = new ServiceInformation();
140
        this.layers = new TreeMap();
141
    }
142

    
143
    /**
144
     * Parse the xml data retrieved from the ArcIms, it will parse the ArcIms Capabilities
145
     * @param f the XML file to parse to obtain the ServiceInfo
146
     * @throws ArcImsException
147
     *
148
     */
149
    public ServiceInformation parseServiceInfo(ServiceInformation si,File f) throws ArcImsException {
150
        Reader reader = null;
151
        
152
        ServiceInformation my_si = si;
153
        
154
        try {
155
            FileInputStream fis = new FileInputStream(f);
156
            InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
157
            BufferedReader br = new BufferedReader(isr);
158
            reader = br;
159
        } catch (FileNotFoundException e) {
160
            logger.error(e.getMessage(), e);
161
        } catch (UnsupportedEncodingException e) {
162
            logger.error(e.getMessage(), e);
163
        }
164

    
165
        int tag;
166
        KXmlParser kxmlParser = null;
167
        kxmlParser = new KXmlParser();
168

    
169
        try {
170
            kxmlParser.setInput(reader);
171
            kxmlParser.nextTag();
172

    
173
            if (kxmlParser.getEventType() != KXmlParser.END_DOCUMENT) {
174
                kxmlParser.require(KXmlParser.START_TAG, null,
175
                    ServiceInfoTags.tARCXML);
176
                tag = kxmlParser.nextTag();
177

    
178
                while (tag != KXmlParser.END_DOCUMENT) {
179
                    switch (tag) {
180
                    case KXmlParser.START_TAG:
181

    
182
                        String name = kxmlParser.getName();
183

    
184
                        if (name.compareTo(ServiceInfoTags.tENVIRONMENT) == 0) {
185
                            parseEnvironmentTag(my_si,kxmlParser);
186
                        } else if (name.compareTo(ServiceInfoTags.tPROPERTIES) == 0) {
187
                            parsePropertiesTag(my_si,kxmlParser);
188
                        } else if (name.compareTo(ServiceInfoTags.tLAYERINFO) == 0) {
189
                            parseLayerInfoTag(my_si,kxmlParser);
190
                        } else if (name.compareTo(ServiceInfoTags.tERROR) == 0) {
191
                            logger.error("Error parsing GET_SERVICE_INFO:\r\n" +
192
                                kxmlParser.nextText());
193
                            throw new ArcImsException("arcims_catalog_error");
194
                        }
195

    
196
                        break;
197

    
198
                    case KXmlParser.END_TAG:
199
                        break;
200

    
201
                    case KXmlParser.TEXT:
202
                        break;
203
                    }
204

    
205
                    tag = kxmlParser.next();
206
                }
207

    
208
                kxmlParser.require(KXmlParser.END_DOCUMENT, null, null);
209

    
210
                //System.out.println(serviceInfo.layers);
211
            }
212
        } catch (XmlPullParserException parser_ex) {
213
            logger.error("Parser error", parser_ex);
214
            throw new ArcImsException("parse_error");
215
        } catch (FileNotFoundException fe) {
216
            logger.error("FileNotFound Error", fe);
217
            throw new ArcImsException("arcims_server_error");
218
        } catch (IOException e) {
219
            logger.error("IO Error", e);
220
            throw new ArcImsException("arcims_server_error");
221
        } catch (NumberFormatException nfe) {
222
            logger.warn("NumberFormat Error");
223

    
224
            char dsTemp = my_si.getSeparators().getDs();
225

    
226
            if (dsTemp == '.') {
227
                logger.warn("NumberFormat Error, changing . by ,");
228
                my_si.getSeparators().setDs(',');
229
                my_si = this.parseServiceInfo(my_si,f);
230
            } else {
231
                if (dsTemp == ',') {
232
                    logger.warn("NumberFormat Error, changing , by .");
233
                    my_si.getSeparators().setDs('.');
234
                    my_si = this.parseServiceInfo(my_si,f);
235
                } else {
236
                    logger.warn(
237
                        "NumberFormat Error: No Decimal Separator found");
238
                    throw new ArcImsException("arcims_decimal_error");
239
                }
240
            }
241

    
242
            //                           throw new ArcImsException("arcims_server_error");
243
        } finally {
244
        }
245
        
246
        return my_si;
247
    }
248

    
249
    /**
250
    * <p>Parses the Environment Information </p>
251
     * @param my_si 
252
    * @param parser A KXmlParser object to parse
253
    * @throws IOException
254
    * @throws XmlPullParserException
255
    */
256
    private void parseEnvironmentTag(ServiceInformation my_si, KXmlParser parser)
257
        throws IOException, XmlPullParserException {
258
        int currentTag;
259
        boolean end = false;
260
        ServiceInformation serviceInfo = my_si;
261
        
262
        parser.require(KXmlParser.START_TAG, null, ServiceInfoTags.tENVIRONMENT);
263
        currentTag = parser.next();
264

    
265
        while (!end) {
266
            switch (currentTag) {
267
            case KXmlParser.START_TAG:
268

    
269
                /*
270
                 * Parse the LOCALE tag
271
                 */
272
                if (parser.getName().compareTo(ServiceInfoTags.tLOCALE) == 0) {
273
                    String language = null;
274
                    language = parser.getAttributeValue("",
275
                            ServiceInfoTags.aLANGUAGE);
276

    
277
                    if (language != null) {
278
                        serviceInfo.getLocale().setLanguage(language);
279
                    }
280

    
281
                    String country = null;
282
                    country = parser.getAttributeValue("",
283
                            ServiceInfoTags.aCOUNTRY);
284

    
285
                    if (country != null) {
286
                        serviceInfo.getLocale().setCountry(country);
287
                    }
288
                }
289
                /*
290
                 * Parse the UIFONT tag
291
                 */
292
                else if (parser.getName().compareTo(ServiceInfoTags.tUIFONT) == 0) {
293
                    String name = null;
294
                    name = parser.getAttributeValue("", ServiceInfoTags.aNAME);
295

    
296
                    if (name != null) {
297
                        serviceInfo.getUifont().setName(name);
298
                    }
299

    
300
                    String color = null;
301
                    color = parser.getAttributeValue("", ServiceInfoTags.aCOLOR);
302

    
303
                    if (color != null) {
304
                        serviceInfo.getUifont().setColor(color);
305
                    }
306

    
307
                    String size = null;
308
                    size = parser.getAttributeValue("", ServiceInfoTags.aSIZE);
309

    
310
                    if (name != null) {
311
                        serviceInfo.getUifont().setSize(size);
312
                    }
313

    
314
                    String style = null;
315
                    style = parser.getAttributeValue("", ServiceInfoTags.aSTYLE);
316

    
317
                    if (style != null) {
318
                        serviceInfo.getUifont().setStyle(style);
319
                    }
320
                }
321
                /*
322
                 * Parse the SEPARATORS tag
323
                 */
324
                else if (parser.getName().compareTo(ServiceInfoTags.tSEPARATORS) == 0) {
325
                    String ts = null;
326
                    ts = parser.getAttributeValue("", ServiceInfoTags.aTS);
327

    
328
                    if (ts != null) {
329
                        serviceInfo.getSeparators().setTs(ts);
330
                    }
331

    
332
                    String cs = null;
333
                    cs = parser.getAttributeValue("", ServiceInfoTags.aCS);
334

    
335
                    if (cs != null) {
336
                        serviceInfo.getSeparators().setCs(cs);
337
                    }
338
                }
339
                /*
340
                 * Parse the SCREEN tag
341
                 */
342
                else if (parser.getName().compareTo(ServiceInfoTags.tSCREEN) == 0) {
343
                    String dpi = null;
344
                    dpi = parser.getAttributeValue("", ServiceInfoTags.aDPI);
345

    
346
                    if (dpi != null) {
347
                        serviceInfo.setScreen_dpi(Integer.parseInt(dpi));
348
                        serviceInfo.setDpiAssumed(false);
349
                    }
350
                }
351
                /*
352
                 * Parse the IMAGELIMIT tag
353
                 */
354
                else if (parser.getName().compareTo(ServiceInfoTags.tIMAGELIMIT) == 0) {
355
                    String pixelcount = null;
356
                    pixelcount = parser.getAttributeValue("",
357
                            ServiceInfoTags.aPIXELCOUNT);
358

    
359
                    if (pixelcount != null) {
360
                        serviceInfo.setImagelimit_pixelcount(pixelcount);
361
                    }
362
                }
363

    
364
                break;
365

    
366
            case KXmlParser.END_TAG:
367

    
368
                if (parser.getName().compareTo(ServiceInfoTags.tENVIRONMENT) == 0) {
369
                    end = true;
370
                }
371

    
372
                break;
373

    
374
            case KXmlParser.TEXT:
375
                break;
376
            }
377

    
378
            if (!end) {
379
                currentTag = parser.next();
380
            }
381
        }
382

    
383
        /*
384
             * Sets de decimal separator
385
             */
386
        if (serviceInfo.getSeparators().getDs() == 'c') {
387
            String lang = this.serviceInfo.getLocale().getLanguage();
388
            String coun = this.serviceInfo.getLocale().getCountry();
389
            Locale local = new Locale(lang, coun);
390
            DecimalFormatSymbols dfs = new DecimalFormatSymbols(local);
391
            serviceInfo.getSeparators().setDs(dfs.getDecimalSeparator());
392
        }
393

    
394
        parser.require(KXmlParser.END_TAG, null, ServiceInfoTags.tENVIRONMENT);
395
    }
396

    
397
    /**
398
     * <p>Parses the Properties Information </p>
399
     * @param my_si 
400
     * @param parser A KXmlParser object to parse
401
     * @throws IOException
402
     * @throws XmlPullParserException
403
     */
404
    private void parsePropertiesTag(ServiceInformation my_si, KXmlParser parser)
405
        throws IOException, XmlPullParserException, NumberFormatException {
406
        int currentTag;
407
        boolean end = false;
408
        
409
        ServiceInformation serviceInfo = my_si;
410
        
411
        parser.require(KXmlParser.START_TAG, null, ServiceInfoTags.tPROPERTIES);
412
        currentTag = parser.next();
413

    
414
        char ds = my_si.getSeparators().getDs();
415

    
416
        while (!end) {
417
            switch (currentTag) {
418
            case KXmlParser.START_TAG:
419

    
420
                /*
421
                 * Parse the ENVELOPE tag
422
                 */
423
                if (parser.getName().compareTo(ServiceInfoTags.tENVELOPE) == 0) {
424
                    BoundaryBox parseEnvelope = new BoundaryBox();
425

    
426
                    String value = null;
427
                    value = parser.getAttributeValue("", ServiceInfoTags.aMINX);
428

    
429
                    if (value != null) {
430
                        if (ds != '.') {
431
                            value = value.replace(ds, '.');
432
                        }
433

    
434
                        parseEnvelope.setXmin(Double.parseDouble(value));
435
                    }
436

    
437
                    value = null;
438
                    value = parser.getAttributeValue("", ServiceInfoTags.aMINY);
439

    
440
                    if (value != null) {
441
                        if (ds != '.') {
442
                            value = value.replace(ds, '.');
443
                        }
444

    
445
                        parseEnvelope.setYmin(Double.parseDouble(value));
446
                    }
447

    
448
                    value = null;
449
                    value = parser.getAttributeValue("", ServiceInfoTags.aMAXY);
450

    
451
                    if (value != null) {
452
                        if (ds != '.') {
453
                            value = value.replace(ds, '.');
454
                        }
455

    
456
                        parseEnvelope.setYmax(Double.parseDouble(value));
457
                    }
458

    
459
                    value = null;
460
                    value = parser.getAttributeValue("", ServiceInfoTags.aMAXX);
461

    
462
                    if (value != null) {
463
                        if (ds != '.') {
464
                            value = value.replace(ds, '.');
465
                        }
466

    
467
                        parseEnvelope.setXmax(Double.parseDouble(value));
468
                    }
469

    
470
                    /**
471
                     * The envelope could be a Initial_Extent or Extent_limit,
472
                     * @see ServiceInformation#envelope and @see ServiceInformation#envelopeEL
473
                     */
474
                    if ((parser.getAttributeValue("", ServiceInfoTags.aNAME) != null) &&
475
                            (parser.getAttributeValue("", ServiceInfoTags.aNAME)
476
                                       .compareTo(ServiceInfoTags.aENVELOPEEL) == 0)) {
477
                        serviceInfo.setEnvelopeEL(parseEnvelope);
478
                    } else {
479
                        serviceInfo.setEnvelope(parseEnvelope);
480
                    }
481
                }
482
                /*
483
                 * Parse the MAPUNITS tag
484
                 */
485
                else if (parser.getName().compareTo(ServiceInfoTags.tMAPUNITS) == 0) {
486
                    String value = null;
487
                    value = parser.getAttributeValue("", ServiceInfoTags.aUNITS);
488

    
489
                    if (value != null) {
490
                        serviceInfo.setMapunits(value);
491
                    }
492
                }
493
                /*
494
                 * Parse the FEATURECOORDSYS tag
495
                 */
496
                else if (parser.getName()
497
                                   .compareTo(ServiceInfoTags.tFEATURECOORDSYS) == 0) {
498
                    String value = null;
499
                    value = parser.getAttributeValue("", ServiceInfoTags.aID);
500

    
501
                    if (value != null) {
502
                        serviceInfo.setFeaturecoordsys(value);
503
                        serviceInfo.setSrsAssumed(false);
504
                    }
505
                }
506

    
507
                break;
508

    
509
            case KXmlParser.END_TAG:
510

    
511
                if (parser.getName().compareTo(ServiceInfoTags.tPROPERTIES) == 0) {
512
                    end = true;
513
                }
514

    
515
                break;
516

    
517
            case KXmlParser.TEXT:
518
                break;
519
            }
520

    
521
            if (!end) {
522
                currentTag = parser.next();
523
            }
524
        }
525

    
526
        parser.require(KXmlParser.END_TAG, null, ServiceInfoTags.tPROPERTIES);
527

    
528
        if (serviceInfo.getFeaturecoordsys().compareTo("") == 0) {
529
            serviceInfo.setSrsAssumed(true);
530
        }
531

    
532
        //else
533
        //System.out.println("JS\t"+serviceInfo.featurecoordsys);
534
    }
535

    
536
    /**
537
     * <p>Parses the LayerInfo Information </p>
538
     * @param my_si 
539
     * @param parser A KXmlParser object to parse
540
     * @throws IOException
541
     * @throws XmlPullParserException
542
     * @throws ArcImsException
543
     */
544
    private void parseLayerInfoTag(ServiceInformation my_si, KXmlParser parser)
545
        throws IOException, XmlPullParserException, NumberFormatException, 
546
            ArcImsException {
547
        String value = null;
548
        String type = null;
549
        
550
        ServiceInformation serviceInfo = my_si;
551
        
552
        char ds = serviceInfo.getSeparators().getDs();
553

    
554
        // double ratio =
555
        // serviceInfo.screen_dpi/ArcImsProtocolHandler.INCHES;
556
        ServiceInformationLayer sil;
557

    
558
        type = parser.getAttributeValue("", ServiceInfoTags.aTYPE);
559

    
560
        /**
561
         * This way, we can instantiate the proper class
562
         */
563
        if (type.compareToIgnoreCase(ServiceInfoTags.vLAYERTYPE_F) == 0) {
564
            sil = new ServiceInformationLayerFeatures("");
565
        } else {
566
            sil = new ServiceInformationLayerImage();
567
        }
568

    
569
        /**
570
         * A this time we can continue parsing
571
         */
572
        value = parser.getAttributeValue("", ServiceInfoTags.aID);
573

    
574
        if (value != null) {
575
            sil.setId(value);
576
        }
577

    
578
        value = parser.getAttributeValue("", ServiceInfoTags.aVISIBLE);
579

    
580
        if (value != null) {
581
            sil.setVisible(value);
582
        }
583

    
584
        value = parser.getAttributeValue("", ServiceInfoTags.aMAXSCALE);
585

    
586
        if (value != null) {
587
            if (ds != '.') {
588
                value = value.replace(ds, '.');
589
            }
590

    
591
            sil.setMaxscale(Double.parseDouble(value));
592
        }
593

    
594
        value = parser.getAttributeValue("", ServiceInfoTags.aMINSCALE);
595

    
596
        if (value != null) {
597
            if (ds != '.') {
598
                value = value.replace(ds, '.');
599
            }
600

    
601
            sil.setMinscale(Double.parseDouble(value));
602
        }
603

    
604
        value = parser.getAttributeValue("", ServiceInfoTags.aNAME);
605

    
606
        if (value != null) {
607
            sil.setName(value);
608
        }
609

    
610
        /**
611
         * At this time, we can go inside the element to retrieve other child
612
         * elements as ENVELOPE
613
         */
614
        int currentTag;
615
        boolean end = false;
616

    
617
        currentTag = parser.next();
618

    
619
        while (!end) {
620
            switch (currentTag) {
621
            case KXmlParser.START_TAG:
622

    
623
                /**
624
                 * Parse the ENVELOPE child element
625
                 */
626
                if (parser.getName().compareTo(ServiceInfoTags.tENVELOPE) == 0) {
627
                    value = null;
628
                    value = parser.getAttributeValue("", ServiceInfoTags.aMINX);
629

    
630
                    if (value != null) {
631
                        if (ds != '.') {
632
                            value = value.replace(ds, '.');
633
                        }
634

    
635
                        sil.getEnvelope().setXmin(Double.parseDouble(value));
636
                    }
637

    
638
                    value = null;
639
                    value = parser.getAttributeValue("", ServiceInfoTags.aMINY);
640

    
641
                    if (value != null) {
642
                        if (ds != '.') {
643
                            value = value.replace(ds, '.');
644
                        }
645

    
646
                        sil.getEnvelope().setYmin(Double.parseDouble(value));
647
                    }
648

    
649
                    value = null;
650
                    value = parser.getAttributeValue("", ServiceInfoTags.aMAXX);
651

    
652
                    if (value != null) {
653
                        if (ds != '.') {
654
                            value = value.replace(ds, '.');
655
                        }
656

    
657
                        sil.getEnvelope().setXmax(Double.parseDouble(value));
658
                    }
659

    
660
                    value = null;
661
                    value = parser.getAttributeValue("", ServiceInfoTags.aMAXY);
662

    
663
                    if (value != null) {
664
                        if (ds != '.') {
665
                            value = value.replace(ds, '.');
666
                        }
667

    
668
                        sil.getEnvelope().setYmax(Double.parseDouble(value));
669
                    }
670
                }
671

    
672
                /**
673
                 * Parse FCLASS and FIELD child element if Layer is of type
674
                 * LAYERTYPE_F
675
                 *
676
                 * @see org.gvsig.remoteClient.arcims.utils.ServiceInfoTags#LAYERTYPE_F
677
                 */
678
                if (type.compareToIgnoreCase(ServiceInfoTags.vLAYERTYPE_F) == 0) {
679
                    ServiceInformationLayerFeatures silf = (ServiceInformationLayerFeatures) sil;
680

    
681
                    if (parser.getName().compareTo(ServiceInfoTags.tFCLASS) == 0) {
682
                        // FCLASS element
683
                        value = null;
684
                        value = parser.getAttributeValue("",
685
                                ServiceInfoTags.aTYPE);
686

    
687
                        if (value != null) {
688
                            silf.setFclasstype(value);
689
                        }
690
                    } else if (parser.getName().compareTo(ServiceInfoTags.tFIELD) == 0) {
691
                        // FIELD element
692
                        FieldInformation fieldInfo = new FieldInformation();
693

    
694
                        value = null;
695
                        value = parser.getAttributeValue("",
696
                                ServiceInfoTags.aNAME);
697

    
698
                        if (value != null) {
699
                            fieldInfo.setName(value);
700
                        }
701

    
702
                        value = null;
703
                        value = parser.getAttributeValue("",
704
                                ServiceInfoTags.aTYPE);
705

    
706
                        if (value != null) {
707
                            fieldInfo.setType(Integer.parseInt(value));
708
                        }
709

    
710
                        value = null;
711
                        value = parser.getAttributeValue("",
712
                                ServiceInfoTags.aPRECISION);
713

    
714
                        if (value != null) {
715
                            fieldInfo.setPrecision(Integer.parseInt(value));
716
                        }
717

    
718
                        value = null;
719
                        value = parser.getAttributeValue("",
720
                                ServiceInfoTags.aSIZE);
721

    
722
                        if (value != null) {
723
                            fieldInfo.setSize(Integer.parseInt(value));
724
                        }
725

    
726
                        /*
727
                         * Now we can add the Field Information into the vector
728
                         */
729
                        silf.addFieldInformation(fieldInfo);
730
                    }
731
                    /**
732
                     * Parse ArcIMS Symbology definition in a separate private method
733
                     */
734
                    else if (ArcImsRendererFactory.isRenderer(parser.getName())) {
735
                        //Get FConstant type
736
                        String fclasstype = silf.getFclasstype();
737
                        int ftype = getFType(fclasstype);
738

    
739
                        //Get a factory instance
740
                        ArcImsRendererFactory airf = new ArcImsRendererFactory(ftype);
741

    
742
                        //Get the main render
743
                        Renderer render = airf.getRenderer(parser);
744

    
745
                        //Assign it to the layer
746
                        silf.setLayerMainRenderer(render);
747
                    }
748
                }
749

    
750
                break;
751

    
752
            case KXmlParser.END_TAG:
753

    
754
                if (parser.getName().compareTo(ServiceInfoTags.tLAYERINFO) == 0) {
755
                    end = true;
756
                }
757

    
758
                break;
759

    
760
            case KXmlParser.TEXT:
761
                break;
762
            }
763

    
764
            if (!end) {
765
                currentTag = parser.next();
766
            }
767
        }
768

    
769
        /**
770
         * At the end, we can add the layer to the vector of ServicInformation
771
         * layers
772
         */
773
        serviceInfo.addLayer(sil);
774
    }
775

    
776
    /**
777
     * Converts ArcIMS feature type to a FConstant value
778
     * @param fclasstype
779
     * @return
780
     */
781
    public static int getFType(String fclasstype) {
782
        if (fclasstype.equals(ServiceInfoTags.aPOLYGON)) {
783
            return FConstant.SHAPE_TYPE_POLYGON;
784
        }
785

    
786
        if (fclasstype.equals(ServiceInfoTags.aPOLYLINE)) {
787
            return FConstant.SHAPE_TYPE_POLYLINE;
788
        }
789

    
790
        if (fclasstype.equals(ServiceInfoTags.aMULTIPOINT)) {
791
            return FConstant.SHAPE_TYPE_MULTIPOINT;
792
        }
793

    
794
        return FConstant.SHAPE_TYPE_NULL;
795
    }
796

    
797
    /**
798
     * Method to parse a request to obtain the Extent of a Service
799
     * @param reader
800
     * @param ds the Decimal Separator
801
     * @return Rectangle with the boundary box of the Service
802
       * @throws ArcImsException
803
     */
804
    protected Rectangle2D parseEnvelopeTag(FileReader reader, char ds)
805
        throws ArcImsException {
806
        BoundaryBox parseEnvelope = new BoundaryBox();
807

    
808
        //char ds = this.serviceInfo.separators.ds;
809
        try {
810
            KXmlParser parser = new KXmlParser();
811
            parser.setInput(reader);
812

    
813
            int currentTag;
814
            boolean end = false;
815

    
816
            // parser.require(KXmlParser.START_TAG, null,
817
            // ServiceInfoTags.ARCXML);
818
            currentTag = parser.next();
819

    
820
            while (!end) {
821
                switch (currentTag) {
822
                case KXmlParser.START_TAG:
823

    
824
                    /*
825
                     * Parse the ENVELOPE tag
826
                     */
827
                    if (parser.getName().compareTo(ServiceInfoTags.tENVELOPE) == 0) {
828
                        parseEnvelope = parseEnvelope(parser, ds);
829
                    } else if (parser.getName().compareTo(ServiceInfoTags.tERROR) == 0) {
830
                        logger.error("Error requesting Service Extent:\r\n" +
831
                            parser.nextText());
832
                        throw new ArcImsException("arcims_extent_error");
833
                    }
834

    
835
                    break;
836

    
837
                case KXmlParser.END_TAG:
838

    
839
                    if (parser.getName().compareTo(ServiceInfoTags.tARCXML) == 0) {
840
                        end = true;
841
                    }
842

    
843
                    break;
844

    
845
                case KXmlParser.TEXT:
846
                    break;
847
                }
848

    
849
                if (!end) {
850
                    currentTag = parser.next();
851
                }
852
            }
853
        } catch (XmlPullParserException parser_ex) {
854
            parser_ex.printStackTrace();
855
        } catch (ConnectException ce) {
856
            logger.error("Timed out error", ce);
857
            throw new ArcImsException("arcims_server_timeout");
858
        } catch (FileNotFoundException fe) {
859
            logger.error("FileNotFound Error", fe);
860
            throw new ArcImsException("arcims_server_error");
861
        } catch (IOException e) {
862
            logger.error("IO Error", e);
863
            throw new ArcImsException("arcims_server_error");
864
        }
865

    
866
        /*
867
         * At the end, we convert the BoundaryBox to a Rectangle2D
868
         */
869
        Rectangle2D rect = new Rectangle2D.Double();
870

    
871
        rect.setFrameFromDiagonal(parseEnvelope.getXmin(),
872
            parseEnvelope.getYmin(), parseEnvelope.getXmax(),
873
            parseEnvelope.getYmax());
874

    
875
        return rect;
876
    }
877

    
878
    /**
879
     * Static method to create a BoundaryBox from a ENVELOPE tag.
880
     * @param parser
881
     * @param ds
882
     * @return
883
     */
884
    protected static BoundaryBox parseEnvelope(KXmlParser parser, char ds) {
885
        BoundaryBox parseEnvelope = new BoundaryBox();
886

    
887
        String value = null;
888
        value = parser.getAttributeValue("", ServiceInfoTags.aMINX);
889

    
890
        if (value != null) {
891
            if (ds != '.') {
892
                value = value.replace(ds, '.');
893
            }
894

    
895
            parseEnvelope.setXmin(Double.parseDouble(value));
896
        }
897

    
898
        value = null;
899
        value = parser.getAttributeValue("", ServiceInfoTags.aMINY);
900

    
901
        if (value != null) {
902
            if (ds != '.') {
903
                value = value.replace(ds, '.');
904
            }
905

    
906
            parseEnvelope.setYmin(Double.parseDouble(value));
907
        }
908

    
909
        value = null;
910
        value = parser.getAttributeValue("", ServiceInfoTags.aMAXY);
911

    
912
        if (value != null) {
913
            if (ds != '.') {
914
                value = value.replace(ds, '.');
915
            }
916

    
917
            parseEnvelope.setYmax(Double.parseDouble(value));
918
        }
919

    
920
        value = null;
921
        value = parser.getAttributeValue("", ServiceInfoTags.aMAXX);
922

    
923
        if (value != null) {
924
            if (ds != '.') {
925
                value = value.replace(ds, '.');
926
            }
927

    
928
            parseEnvelope.setXmax(Double.parseDouble(value));
929
        }
930

    
931
        return parseEnvelope;
932
    }
933

    
934
    /**
935
    * Abstract method to retrieve a valid XML of a Query By Point request
936
    * @param status
937
    * @return Vallid XML to build the Element Info GUI
938
    * @throws ArcImsException
939
    */
940

    
941
    //public abstract void getMap(ArcImsStatus status);
942
    public abstract String getElementInfo(ArcImsStatus status, int x, int y,
943
        int featureCount) throws ArcImsException;
944

    
945
    public String getName() {
946
        return name;
947
    }
948

    
949
    public String getVersion() {
950
        return version;
951
    }
952

    
953
    public ServiceInformation getServiceInformation() {
954
        return this.serviceInfo;
955
    }
956

    
957
    public String getHost() {
958
        return host;
959
    }
960

    
961
    public void setHost(String _host) {
962
        host = _host;
963
    }
964

    
965
    public String getPort() {
966
        return port;
967
    }
968

    
969
    public void setPort(String _port) {
970
        port = _port;
971
    }
972

    
973
    /**
974
     * Method to request a GET_SERVICE_INFO to an ArcIMS Server
975
     * @param status
976
     * @throws ArcImsException
977
     */
978
    public void getCapabilities(ArcImsStatus status) throws ArcImsException {
979
        try {
980
            String request = ArcXML.getServiceInfoRequest(getVersion());
981

    
982
            URL url = new URL(buildCapabilitiesRequest(status));
983
            logger.info("Requesting ArcIMS Service Information");
984

    
985
            File f = ArcImsDownloadUtils.doRequestPost(url, request,
986
                    "serviceInfo.xml");
987

    
988
            this.serviceInfo = parseServiceInfo(this.serviceInfo,f);
989
        } catch (MalformedURLException e) {
990
            logger.error(e.getMessage(), e);
991
            throw new ArcImsException("arcims_server_error");
992
        }
993
    }
994

    
995
    /**
996
     * Builds the GetCapabilitiesRequest according to the ArcIms Specifications stored in
997
     * a @see ArcImsStatus object
998
     * @param status
999
     * @return string A convenient request
1000
     */
1001
    protected String buildCapabilitiesRequest(ArcImsStatus status) {
1002
        StringBuffer req = new StringBuffer();
1003

    
1004
        String onlineResource;
1005
        String service;
1006

    
1007
        if ((status == null) || (status.getOnlineResource() == null)) {
1008
            onlineResource = getHost();
1009
            service = getService();
1010
        } else {
1011
            onlineResource = status.getOnlineResource();
1012
            service = status.getService();
1013
        }
1014

    
1015
        //String symbol = getSymbol(onlineResource);
1016
        req.append(onlineResource);
1017
        req.append("?" + GetVariables.SERVICENAME + "=");
1018

    
1019
        req.append(service);
1020

    
1021
        return req.toString();
1022
    }
1023

    
1024
    /**
1025
     * Builds the GetFeatureInfo according to the ArcIms Specifications stored in
1026
     * a @see ArcImsStatus object
1027
     * @param status
1028
     * @param _type of ArcIMS service
1029
     * @return string A convenient request
1030
     */
1031
    protected String buildGetFeatureInfoRequest(ArcImsStatus status,
1032
        String _type) {
1033
        StringBuffer req = new StringBuffer();
1034

    
1035
        String onlineResource;
1036
        String service;
1037
        onlineResource = getHost();
1038

    
1039
        if ((status == null) || (status.getOnlineResource() == null)) {
1040
            onlineResource = getHost();
1041
            service = getService();
1042
        } else {
1043
            onlineResource = status.getOnlineResource();
1044
            service = status.getService();
1045
        }
1046

    
1047
        //String symbol = getSymbol(onlineResource);
1048
        req.append(onlineResource);
1049
        req.append("?" + GetVariables.SERVICENAME + "=");
1050

    
1051
        req.append(service);
1052

    
1053
        /**
1054
         * This GET variable is needed when an ImageService
1055
         * is requested
1056
         */
1057
        if ((this.serviceInfo.getType().equals(ServiceInfoTags.vIMAGESERVICE)) &&
1058
                _type.equals(ServiceInfoTags.vLAYERTYPE_F)) {
1059
            req.append("&" + GetVariables.CUSTOMSERVICE + "=" +
1060
                GetVariables.QUERY);
1061
        }
1062

    
1063
        return req.toString();
1064
    }
1065

    
1066
    public void close() {
1067
        // your code here
1068
    }
1069

    
1070
    public String getService() {
1071
        return service;
1072
    }
1073

    
1074
    public void setService(String service) {
1075
        this.service = service;
1076
    }
1077

    
1078
    /**
1079
     * Method that retrieves a catalog from the ArcIMS Server and returns an ArrayList
1080
     * of name, type and status of every service offered by the server
1081
     * @param url
1082
     * @return ArrayList
1083
     * @throws ArcImsException
1084
     */
1085
    public static ArrayList getCatalog(URL url, boolean override)
1086
        throws ArcImsException {
1087
        //                if (!ArcImsProtocolHandler.getPing(url)){
1088
        //                        throw new ArcImsException("arcims_no_server");
1089
        //                }
1090
        ArrayList services = new ArrayList();
1091

    
1092
        try {
1093
            URL urlComplete = new URL(url.toString() + "?" +
1094
                    GetVariables.SERVICENAME + "=" + GetVariables.CATALOG);
1095

    
1096
            String request = ArcXML.getClientServices();
1097

    
1098
            logger.info("Requesting ArcIMS Catalog");
1099

    
1100
            File f = ArcImsDownloadUtils.doRequestPost(urlComplete, request,
1101
                    "getClientServices.xml", override);
1102

    
1103
            services = parseClientServices(f);
1104
        } catch (MalformedURLException e) {
1105
            logger.error(e.getMessage(), e);
1106
            throw new ArcImsException("arcims_server_error");
1107
        }
1108

    
1109
        return services;
1110
    }
1111

    
1112
    /**
1113
     * Gets the catalog without setting the override boolean
1114
     * @see #getCatalog(URL, boolean)
1115
     * @param url
1116
     * @return ArrayList with the Catalgo of the Service
1117
     * @throws ArcImsException
1118
     */
1119
    public static ArrayList getCatalog(URL url) throws ArcImsException {
1120
        return getCatalog(url, false);
1121
    }
1122

    
1123
    /**
1124
     * Method that parses a ArcXML response for the GETCLIENTSERVICES request
1125
     * @param f
1126
     * @return ArrayList of ArrayLists with name, type and status
1127
     * @throws ArcImsException
1128
     */
1129
    private static ArrayList parseClientServices(File f)
1130
        throws ArcImsException {
1131
        ArrayList services = new ArrayList();
1132
        ArrayList service;
1133

    
1134
        try {
1135
            KXmlParser parser = new KXmlParser();
1136
            parser.setInput(new FileReader(f));
1137

    
1138
            int currentTag;
1139
            boolean end = false;
1140

    
1141
            //parser.require(KXmlParser.START_TAG, null, ServiceInfoTags.ARCXML);
1142
            currentTag = parser.next();
1143

    
1144
            while (!end) {
1145
                switch (currentTag) {
1146
                case KXmlParser.START_TAG:
1147

    
1148
                    /*
1149
                     * Parse the SERVICE tag
1150
                     */
1151
                    if (parser.getName().compareTo(CatalogInfoTags.SERVICE) == 0) {
1152
                        //Initialize metadata
1153
                        String servName = new String();
1154
                        String servType = new String();
1155
                        String servStatus = new String();
1156

    
1157
                        String value = null;
1158
                        value = parser.getAttributeValue("",
1159
                                CatalogInfoTags.SERVICE_ATT_NAME);
1160

    
1161
                        if (value != null) {
1162
                            servName = value;
1163
                        }
1164

    
1165
                        value = null;
1166
                        value = parser.getAttributeValue("",
1167
                                CatalogInfoTags.SERVICE_ATT_TYPE);
1168

    
1169
                        if (value != null) {
1170
                            servType = value;
1171
                        }
1172

    
1173
                        value = null;
1174
                        value = parser.getAttributeValue("",
1175
                                CatalogInfoTags.SERVICE_ATT_STATUS);
1176

    
1177
                        if (value != null) {
1178
                            servStatus = value;
1179
                        }
1180

    
1181
                        //First add an ArrayList with these data
1182
                        service = new ArrayList();
1183
                        service.add(servName);
1184
                        service.add(servType);
1185
                        service.add(servStatus);
1186

    
1187
                        //Now add this object to the services ArrayList
1188
                        services.add(service);
1189
                        service = null;
1190
                    }
1191

    
1192
                    break;
1193

    
1194
                case KXmlParser.END_TAG:
1195

    
1196
                    if (parser.getName().compareTo(ServiceInfoTags.tARCXML) == 0) {
1197
                        end = true;
1198
                    }
1199

    
1200
                    break;
1201

    
1202
                case KXmlParser.TEXT:
1203
                    break;
1204
                }
1205

    
1206
                if (!end) {
1207
                    currentTag = parser.next();
1208
                }
1209
            }
1210
        } catch (XmlPullParserException parser_ex) {
1211
            parser_ex.printStackTrace();
1212
        } catch (ConnectException ce) {
1213
            logger.error("Timed out error", ce);
1214
            throw new ArcImsException("arcims_server_timeout");
1215
        } catch (FileNotFoundException fe) {
1216
            logger.error("FileNotFound Error", fe);
1217
            throw new ArcImsException("arcims_server_error");
1218
        } catch (IOException e) {
1219
            logger.error("IO Error", e);
1220
            throw new ArcImsException("arcims_server_error");
1221
        }
1222

    
1223
        return services;
1224
    }
1225

    
1226
    /**
1227
     * Method that does a Ping to an ArcIMS Server
1228
     * @param url
1229
     * @return true when server exits, false otherwise
1230
     * @throws ArcImsException
1231
     */
1232
    public static boolean getPing(URL url) throws ArcImsException {
1233
        try {
1234
            URL urlWithPing = new URL(url.toString() + "?" +
1235
                    GetVariables.COMMAND + "=" + GetVariables.PING);
1236
            HttpURLConnection conn = (HttpURLConnection) urlWithPing.openConnection();
1237
            conn.setDoOutput(true);
1238
            conn.setRequestMethod("GET");
1239

    
1240
            logger.info("Trying connect to: " + conn.getURL().toString());
1241
            conn.connect();
1242

    
1243
            Reader isr = new InputStreamReader(conn.getInputStream());
1244
            BufferedReader reader = new BufferedReader(isr);
1245

    
1246
            String line = reader.readLine();
1247

    
1248
            //If the connection was succesful and this line starts with IMS, the server is OK
1249
            if ((conn.getResponseCode() == HttpURLConnection.HTTP_OK) &&
1250
                    line.startsWith("IMS")) {
1251
                logger.info("Connection succeeded");
1252

    
1253
                return true;
1254
            } else {
1255
                return false;
1256
            }
1257
        } catch (MalformedURLException e) {
1258
            e.printStackTrace();
1259
            logger.warn("Malformed url", e);
1260

    
1261
            return false;
1262
        } catch (ConnectException ce) {
1263
            logger.error("Timed out error", ce);
1264
            throw new ArcImsException("arcims_server_timeout");
1265
        } catch (NullPointerException npe) {
1266
            logger.error("NullPointerException", npe);
1267
            throw new ArcImsException("arcims_server_error");
1268
        } catch (IOException e) {
1269
            return false;
1270
        }
1271
    }
1272

    
1273
    /**
1274
     * Method that pings with several SERVLETS trying to find a correct one.
1275
     * @param url to start searching
1276
     * @return Correct URL
1277
     * @throws ArcImsException
1278
     */
1279
    public static URL getUrlWithServlet(URL url) throws ArcImsException {
1280
        /*
1281
         * Url with the servlet
1282
         */
1283
        URL urlTemp;
1284
        URL urlWithServlet = null;
1285

    
1286
        /*
1287
         * If url ends with a slash, we remove it
1288
         */
1289
        if (url.toString().endsWith("/")) {
1290
            String strUrl = url.toString();
1291
            int size = strUrl.length();
1292
            strUrl = strUrl.substring(0, size - 1);
1293

    
1294
            try {
1295
                url = new URL(strUrl);
1296
            } catch (MalformedURLException e) {
1297
                e.printStackTrace();
1298
                logger.error(e.getMessage(), e);
1299
                throw new ArcImsException("wrong_url");
1300
            }
1301
        }
1302

    
1303
        int n = GetVariables.SERVLETS.length;
1304

    
1305
        //Loop over the SERVLETS to find a valid one.
1306
        logger.info("Start searching correct servlet");
1307

    
1308
        for (int i = 0; i < n; i++) {
1309
            try {
1310
                urlTemp = new URL(url.toString() + GetVariables.SERVLETS[i]);
1311
            } catch (MalformedURLException e) {
1312
                //The url is "Malformed" so, we continue with the next block
1313
                continue;
1314
            }
1315

    
1316
            if (ArcImsProtocolHandler.getPing(urlTemp)) {
1317
                urlWithServlet = urlTemp;
1318

    
1319
                break;
1320
            }
1321
        }
1322

    
1323
        if (urlWithServlet == null) {
1324
            throw new ArcImsException("arcims_no_server");
1325
        }
1326

    
1327
        logger.info("Complete ArcIMS URL: " + urlWithServlet.toString());
1328

    
1329
        return urlWithServlet;
1330
    }
1331

    
1332
    public static String[] getVersion(URL url) throws ArcImsException {
1333
        String[] getV = new String[2];
1334
        Reader isr;
1335
        URL urlCmd;
1336
        HttpURLConnection conn;
1337

    
1338
        try {
1339
            //Build the url with the proper command
1340
            urlCmd = new URL(url.toString() + "?" + GetVariables.COMMAND + "=" +
1341
                    GetVariables.GETVERSION);
1342
        } catch (MalformedURLException e) {
1343
            e.printStackTrace();
1344
            logger.error(e.getMessage(), e);
1345
            throw new ArcImsException("arcims_no_server");
1346
        }
1347

    
1348
        try {
1349
            //Stablish the connection
1350
            conn = (HttpURLConnection) urlCmd.openConnection();
1351
            conn.setDoOutput(true);
1352
            conn.setRequestMethod("GET");
1353
            conn.connect();
1354

    
1355
            //Get the reader and asign the first two lines of the response
1356
            isr = new InputStreamReader(conn.getInputStream());
1357

    
1358
            BufferedReader reader = new BufferedReader(isr);
1359
            String strTemp = new String();
1360
            strTemp = reader.readLine();
1361
            getV[0] = strTemp.substring(strTemp.indexOf("=") + 1);
1362
            strTemp = reader.readLine();
1363
            getV[1] = strTemp.substring(strTemp.indexOf("=") + 1);
1364

    
1365
            conn.disconnect();
1366
        } catch (ConnectException ce) {
1367
            logger.error("Timed out error", ce);
1368
            throw new ArcImsException("arcims_server_timeout");
1369
        } catch (IOException e) {
1370
            logger.error(e.getMessage(), e);
1371
            throw new ArcImsException("arcims_no_server");
1372
        }
1373

    
1374
        return getV;
1375
    }
1376

    
1377
    /**
1378
     * This method returns a Legend to the client requested by
1379
     * layerId string
1380
     * @param layerId
1381
     * @return Legend with layer simbology
1382
     * @throws ArcImsException
1383
     */
1384
    public Legend getLegend(String layerId) throws ArcImsException {
1385
        ArcImsFLegendFactory aiff = new ArcImsFLegendFactory(this.serviceInfo,
1386
                layerId);
1387

    
1388
        return aiff.getMainLegend();
1389
    }
1390
}