Statistics
| Revision:

gvsig-raster / org.gvsig.raster.wms / trunk / org.gvsig.raster.wms / org.gvsig.raster.wms.remoteclient / src / main / java / org / gvsig / remoteclient / wms / WMSProtocolHandlerFactory.java @ 3324

History | View | Annotate | Download (10.3 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24

    
25
package org.gvsig.remoteclient.wms;
26

    
27
import java.io.File;
28
import java.io.IOException;
29
import java.io.StringReader;
30
import java.net.ConnectException;
31
import java.net.URL;
32
import java.util.ArrayList;
33
import java.util.Iterator;
34
import org.apache.commons.io.FileUtils;
35

    
36
import org.gvsig.remoteclient.utils.CapabilitiesTags;
37
import org.gvsig.remoteclient.utils.Utilities;
38
import org.kxml2.io.KXmlParser;
39
import org.slf4j.Logger;
40
import org.slf4j.LoggerFactory;
41
import org.xmlpull.v1.XmlPullParserException;
42

    
43
public class WMSProtocolHandlerFactory {
44
    
45
    private static final Logger logger = LoggerFactory.getLogger(WMSProtocolHandlerFactory.class);
46
    public org.gvsig.remoteclient.wms.WMSProtocolHandler wMSProtocolHandler;
47

    
48
    private static ArrayList supportedVersions = new ArrayList();
49

    
50
    static {
51
        /*
52
         * Se meten en el array versions las distintas versiones
53
         * del protocolo en orden descendente
54
         */
55
            //versions.add(WMSProtocolHandler1_3_0.class);
56
        //versions.add(WMSProtocolHandler1_1_1.class);
57
            supportedVersions.add("1.3.0");
58
            supportedVersions.add("1.1.1");
59
            supportedVersions.add("1.1.0");
60
     }
61

    
62
    /**
63
     * M?todo que dada una respuesta de getCapabilities y un iterador sobre una
64
     * coleccion de WMSClient's ordenada descendentemente devuelve el cliente
65
     * cuya version es igual o inmediatamente inferior
66
     *
67
     * @param caps Capabilities con la respuesta del servidor
68
     * @param clients Iterador de conjunto ordenado descendientemente
69
     *
70
     * @return cliente cuya version es igual o inmediatamente inferior
71
     * @throws IllegalAccessException
72
     * @throws InstantiationException
73
     *
74
     */
75
    private static String getDriverVersion(String version, Iterator clients) throws InstantiationException, IllegalAccessException {
76
        while (clients.hasNext()) {
77
            String clientVersion = (String)clients.next();
78
            int ret = version.compareTo(clientVersion);
79

    
80
            if (ret >= 0) {
81
                return clientVersion;
82
            }
83
        }
84
        return null;
85
    }
86

    
87
    /**
88
     * Establece la versi?n con la que se comunicar? con el servidor y devuelve
89
     * el objeto Capabilities obtenido con dicha versi?n
90
     *
91
     * @param host maquina con la que se negocia
92
     *
93
     * @return instancia de un cliente capaz de negociar con el host que se
94
     *         pasa como par?metro
95
     */
96
     public static WMSProtocolHandler negotiate(String host) throws ConnectException, IOException {
97

    
98
        if (supportedVersions.size() == 0)
99
        {
100
                return null;
101
        }
102

    
103
        try
104
        {
105
                String highestVersionSupportedByServer  = getSuitableWMSVersion(host,"");
106
                if (supportedVersions.contains(highestVersionSupportedByServer))
107
                {
108
                        //we support the highest version supported by the server
109
                        // this is the best case
110
                        return createVersionDriver(highestVersionSupportedByServer);
111
                }
112

    
113

    
114
        else
115
                {
116
                        // in case we dont support the highest version from the server
117
                        // we start the negotiation process in which we have to get the higest version
118
                        // the WMS supports and we are able to read.
119
                        Iterator iVersion = supportedVersions.iterator();
120
                        String wmsVersion;
121
                        String gvSIGVersion;
122

    
123
                        while (iVersion.hasNext()) {
124
                                gvSIGVersion = (String)iVersion.next();
125
                                wmsVersion = getSuitableWMSVersion(host,gvSIGVersion);
126
                                //TODO:
127
                                //compare with the version returned by the WMS!!!!!
128
                                // send GetCapabilities and read the version to compare.
129
                                int res = wmsVersion.compareTo(gvSIGVersion);
130

    
131
                                if (res == 0) { //Si es la misma que nuestra version
132
                                    return createVersionDriver(gvSIGVersion);
133
                                } else if (res > 0) { //Si es mayor que nuestra version
134
                                    throw new Exception("Server Version too high: " + wmsVersion);
135
                                } else { //Si es menor que nuestra version
136
                                         //Obtenemos la primera version menor o igual que tengamos
137
                                    String lowerVersion = WMSProtocolHandlerFactory.getDriverVersion(wmsVersion, iVersion);
138

    
139
                                    if (lowerVersion == null) { //Si no hay ninguna
140
                                        throw new Exception("Lowest server version is " + wmsVersion);
141
                                    } else {
142
                                        if (lowerVersion.equals(wmsVersion)) {
143
                                            return createVersionDriver(lowerVersion);
144
                                        } else { //Si hay una version menor que la que retorno el servidor
145
                                            //iV = lower;
146
                                        }
147
                                    }
148
                                }
149
                        }
150
                }//case we had to start the negotiation process.
151
                return null; // if it did not find any suitable version.
152
        }
153
        catch(ConnectException conEx)
154
        {
155
                throw conEx;
156
        }
157
        catch(IOException ioEx)
158
        {
159
                throw ioEx;
160
        }
161
        catch(Exception e)
162
        {
163
                logger.warn("Can't determine server version",e);
164
                  return null;
165
        }
166
    }
167

    
168
     /**
169
      * Sends a GetCapabilities to the WMS server to get the version
170
      * if the version parameter is null, the WMS will return the highest version supported
171
      * if not it will return the lower highest version than the one requested.
172
      * @param host
173
      * @param version
174
      * @return suitable version supported by the server
175
      */
176
     private static String getSuitableWMSVersion(String host, String _version) throws ConnectException, IOException
177
     {
178
         int sizes[] = new int[] { 1024, 1024*10, 1024*50, 1024*100 };
179
         XmlPullParserException  xmlEx = null;
180
         for( int i=0; i<sizes.length; i++ ) {
181
             String version;
182
             try {
183
                 version = getSuitableWMSVersion(host, _version, sizes[i]);
184
                 return version;
185
             } catch (XmlPullParserException ex) {
186
                 xmlEx = ex;
187
                 // Try with other size
188
             }
189
         }
190
         logger.warn("Can't determine server version",xmlEx);
191
         return "";
192
     }
193
     
194
    private static String readFromUrl(String url_s, int size) throws IOException {
195
            URL url = new URL(url_s);
196
            Utilities.removeURL(url);
197
            File f = Utilities.downloadFile(url, "wms_capabilities.xml", null);
198
            return FileUtils.readFileToString(f);
199
    }
200
    
201
    private static String getSuitableWMSVersion(String host, String _version, int size) throws ConnectException, IOException, XmlPullParserException {
202
        String request = WMSProtocolHandler.buildCapabilitiesSuitableVersionRequest(host, _version);
203
        String version = new String();
204
        StringReader reader = null;
205
        try {
206
            String string = readFromUrl(request, size);
207
            
208
            // patch for ArcIMS + WMS connector > 9.0 bug
209
            int a = string.toLowerCase().indexOf("<?xml");
210
            if ( a != -1 ) {
211
                string = string.substring(a, string.length());
212
            }
213
            // end patch
214

    
215
            reader = new StringReader(string);
216
            KXmlParser kxmlParser = null;
217
            kxmlParser = new KXmlParser();
218
            kxmlParser.setInput(reader);
219
            kxmlParser.nextTag();
220
            if ( kxmlParser.getEventType() != KXmlParser.END_DOCUMENT ) {
221
                if ( (kxmlParser.getName().compareTo(CapabilitiesTags.CAPABILITIES_ROOT1_1_0) == 0)
222
                        || (kxmlParser.getName().compareTo(CapabilitiesTags.CAPABILITIES_ROOT1_1_1) == 0)
223
                        || (kxmlParser.getName().compareTo(CapabilitiesTags.CAPABILITIES_ROOT1_3_0) == 0) ) {
224
                    version = kxmlParser.getAttributeValue("", CapabilitiesTags.VERSION);
225
                }
226
            }
227
            // do not forget to close the Stream.
228
            reader.close();
229
            reader = null;
230
            return version;
231
        } catch (ConnectException conEx) {
232
            throw new ConnectException(conEx.getMessage());
233
        } catch (IOException ioEx) {
234
            throw new IOException(ioEx.getMessage());
235
        } catch (XmlPullParserException xmlEx) {
236
            throw xmlEx;
237
//                    logger.warn("Can't determine server version",xmlEx);
238
//                    return "";
239
        } finally {
240
            if ( reader != null ) {
241
                try {
242
                    reader.close();
243
                } catch (Exception ex) {
244
                    logger.warn("Can't close reader", ex);
245
                }
246
            }
247
        }
248
    }
249

    
250
     /**
251
      * It creates an instance of a WMSDriver class.
252
      *
253
      * @param String, with the version of the driver to be created
254
      * @return WMSDriver.
255
      */
256
       private static WMSProtocolHandler createVersionDriver(String version)
257
       {
258
         try
259
         {
260
           Class driver;
261
           version = version.replace('.', '_');
262
           driver = Class.forName("org.gvsig.remoteclient.wms.wms_"+version+".WMSProtocolHandler" + version);
263
           return (WMSProtocolHandler)driver.newInstance();
264
         }
265
         catch (Exception e)
266
         {
267
                logger.warn("Can't create WMS protocol handler for version '"+version+"'.",e);
268
           //throw new Exception("WMSDriverFactory. Unknown driver version " + e);
269
                 return null;
270
         }
271
       }
272

    
273
 }