Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.remoteclient / src / main / java / org / gvsig / remoteclient / wms / WMSProtocolHandlerFactory.java @ 41817

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.DataInputStream;
28
import java.io.IOException;
29
import java.io.StringReader;
30
import java.net.ConnectException;
31
import java.net.URL;
32
import java.net.URLConnection;
33
import java.util.ArrayList;
34
import java.util.Iterator;
35

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

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

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

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

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

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

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

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

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

    
112

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

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

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

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

    
167
     /**
168
      * Sends a GetCapabilities to the WMS server to get the version
169
      * if the version parameter is null, the WMS will return the highest version supported
170
      * if not it will return the lower highest version than the one requested.
171
      * @param host
172
      * @param version
173
      * @return suitable version supported by the server
174
      */
175
     private static String getSuitableWMSVersion(String host, String _version) throws ConnectException, IOException
176
     {
177
         int sizes[] = new int[] { 1024, 1024*10, 1024*50, 1024*100 };
178
         XmlPullParserException  xmlEx = null;
179
         for( int i=0; i<sizes.length; i++ ) {
180
             String version;
181
             try {
182
                 version = getSuitableWMSVersion(host, _version, sizes[i]);
183
                 return version;
184
             } catch (XmlPullParserException ex) {
185
                 xmlEx = ex;
186
                 // Try with other size
187
             }
188
         }
189
         logger.warn("Can't determine server version",xmlEx);
190
         return "";
191
     }
192
     
193
     private static String getSuitableWMSVersion(String host, String _version, int size) throws ConnectException, IOException, XmlPullParserException
194
     {
195
            String request = WMSProtocolHandler.buildCapabilitiesSuitableVersionRequest(host, _version);
196
            String version = new String();
197
            StringReader reader = null;
198
            DataInputStream dis = null;
199
                try
200
                {
201
                        URL url = new URL(request);
202
            byte[] buffer = new byte[size];
203
            URLConnection conn = url.openConnection();
204
            conn.setRequestProperty("Accept", "text/xml, text/*, */*");
205
            conn.setRequestProperty("User-Agent", "Mozilla/5.0 (gvSIG) like Gecko");
206
            dis = new DataInputStream(conn.getInputStream());
207
            dis.read(buffer);
208
            String string = new String(buffer);
209

    
210
            // patch for ArcIMS + WMS connector > 9.0 bug
211
            int a = string.toLowerCase().indexOf("<?xml");
212
            if (a !=-1)
213
                    string = string.substring(a, string.length());
214
            // end patch
215

    
216

    
217
            reader = new StringReader(string);
218
                    KXmlParser kxmlParser = null;
219
                    kxmlParser = new KXmlParser();
220
                    kxmlParser.setInput(reader);
221
                        kxmlParser.nextTag();
222
                    if ( kxmlParser.getEventType() != KXmlParser.END_DOCUMENT )
223
                    {
224
                            if ((kxmlParser.getName().compareTo(CapabilitiesTags.CAPABILITIES_ROOT1_1_0)==0)
225
                                    ||(kxmlParser.getName().compareTo(CapabilitiesTags.CAPABILITIES_ROOT1_1_1)==0)
226
                                    ||(kxmlParser.getName().compareTo(CapabilitiesTags.CAPABILITIES_ROOT1_3_0)==0))
227
                            {
228
                                    version = kxmlParser.getAttributeValue("", CapabilitiesTags.VERSION);
229
                            }
230
                    }
231
                    // do not forget to close the Stream.
232
                    reader.close();
233
                    dis.close();
234
                        return version;
235
                }
236
                catch(ConnectException conEx)
237
                {
238
                        throw new ConnectException(conEx.getMessage());
239
                }
240
                catch(IOException ioEx)
241
                {
242
                        throw new IOException(ioEx.getMessage());
243
                }
244
                catch(XmlPullParserException xmlEx)
245
                {
246
                    throw  xmlEx;
247
//                    logger.warn("Can't determine server version",xmlEx);
248
//                    return "";
249
                }
250
                finally{
251
                        if (reader != null)
252
                        {
253
                                try{
254
                                        reader.close();
255
                                }catch(Exception ex){
256
                                        logger.warn("Can't close reader",ex);
257
                                }
258
                        }
259
                        if (dis != null)
260
                        {
261
                                try {
262
                                        dis.close();
263
                                } catch(Exception ex) {
264
                                        logger.warn("Can't close input stream",ex);
265
                                }
266
                        }
267
                }
268
     }
269

    
270
     /**
271
      * It creates an instance of a WMSDriver class.
272
      *
273
      * @param String, with the version of the driver to be created
274
      * @return WMSDriver.
275
      */
276
       private static WMSProtocolHandler createVersionDriver(String version)
277
       {
278
         try
279
         {
280
           Class driver;
281
           version = version.replace('.', '_');
282
           driver = Class.forName("org.gvsig.remoteclient.wms.wms_"+version+".WMSProtocolHandler" + version);
283
           return (WMSProtocolHandler)driver.newInstance();
284
         }
285
         catch (Exception e)
286
         {
287
                logger.warn("Can't create WMS protocol handler for version '"+version+"'.",e);
288
           //throw new Exception("WMSDriverFactory. Unknown driver version " + e);
289
                 return null;
290
         }
291
       }
292

    
293
 }