Statistics
| Revision:

root / org.gvsig.wfs.app / trunk / org.gvsig.wfs.app / org.gvsig.wfs.app.mainplugin / src / main / java / org / gvsig / remoteclient / wfs / WFSProtocolHandlerFactory.java @ 112

History | View | Annotate | Download (9.01 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
package org.gvsig.remoteclient.wfs;
25

    
26
import java.io.File;
27
import java.io.FileReader;
28
import java.io.IOException;
29
import java.io.Reader;
30
import java.net.ConnectException;
31
import java.net.URL;
32
import java.util.ArrayList;
33
import java.util.Iterator;
34
import java.util.List;
35

    
36
import org.kxml2.io.KXmlParser;
37
import org.xmlpull.v1.XmlPullParserException;
38

    
39
import org.gvsig.compat.CompatLocator;
40
import org.gvsig.compat.lang.StringUtils;
41
import org.gvsig.remoteclient.utils.CapabilitiesTags;
42
import org.gvsig.remoteclient.utils.EncodingXMLParser;
43
import org.gvsig.remoteclient.utils.Utilities;
44
import org.slf4j.Logger;
45
import org.slf4j.LoggerFactory;
46

    
47
/**
48
 * @author Jorge Piera Llodr? (piera_jor@gva.es)
49
 */
50
public class WFSProtocolHandlerFactory {
51
        private static Logger logger = LoggerFactory.getLogger(WFSProtocolHandlerFactory.class);
52

    
53
        public WFSProtocolHandler wFSProtocolHandler;
54
        private static final StringUtils stringUtils = CompatLocator.getStringUtils();
55
        private static ArrayList supportedVersions = new ArrayList();
56
        
57
        static {
58
        supportedVersions.add("1.1.0");
59
                supportedVersions.add("1.0.0");
60
        }
61
        
62
        /**
63
         * M?todo que dada una respuesta de getCapabilities y un iterador sobre una
64
         * coleccion de WFSClient'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 WFSProtocolHandler negotiate(String host, boolean ignoreCache) throws ConnectException, IOException {
97
                
98
                if (supportedVersions.size() == 0){
99
                        return null;
100
                }
101
                
102
                try        {                
103
                        String highestVersionSupportedByServer  = getSuitableWFSVersion(host,"", ignoreCache);
104
                        if (supportedVersions.contains(highestVersionSupportedByServer))
105
                        {
106
                                // we support the highest version supported by the server
107
                                // this is the best case 
108
                                return createVersionDriver(highestVersionSupportedByServer);
109
                        }
110
                        else
111
                        {
112
                                // in case we dont support the highest version from the server
113
                                // we start the negotiation process in which we have to get the higest version
114
                                // the WFS supports and we are able to read.
115
                                Iterator iVersion = supportedVersions.iterator();
116
                                String wfsVersion;
117
                                String gvSIGVersion;
118
                                
119
                                while (iVersion.hasNext()) { 
120
                                        gvSIGVersion = (String)iVersion.next();
121
                                        wfsVersion = getSuitableWFSVersion(host,gvSIGVersion, ignoreCache);
122
                                        //TODO:
123
                                        //compare with the version returned by the WMS!!!!!
124
                                        // send GetCapabilities and read the version to compare.
125
                                        int res = wfsVersion.compareTo(gvSIGVersion);
126
                                        
127
                                        if (res == 0) { //Si es la misma que nuestra version                
128
                                                return createVersionDriver(gvSIGVersion);
129
                                        } else if (res > 0) { //Si es mayor que nuestra version
130
                                                throw new Exception("Server Version too high: " + wfsVersion);
131
                                        } else { //Si es menor que nuestra version
132
                                                //Obtenemos la primera version menor o igual que tengamos
133
                                                String lowerVersion = WFSProtocolHandlerFactory.getDriverVersion(wfsVersion, iVersion);
134
                                                
135
                                                if (lowerVersion == null) { //Si no hay ninguna
136
                                                        throw new Exception("Lowest server version is " + wfsVersion);
137
                                                } else {
138
                                                        if (lowerVersion.equals(wfsVersion)) { 
139
                                                                return createVersionDriver(lowerVersion);
140
                                                        } else { //Si hay una version menor que la que retorno el servidor
141
                                                                //iV = lower;
142
                                                        }
143
                                                }
144
                                        }
145
                                }
146
                        }//case we had to start the negotiation process.
147
                        return null; // if it did not find any suitable version.        
148
                }
149
                catch(ConnectException conEx)
150
                {
151
                        throw conEx;
152
                }
153
                catch(IOException ioEx)
154
                {
155
                        throw ioEx;
156
                }        
157
                catch(Exception e)
158
                {
159
                        logger.warn("Can't negotiate version for host '"+host+"'.",e);
160
                        return null;
161
                }
162
        }
163
        
164
        /**
165
         * Sends a GetCapabilities to the WFS server to get the version
166
         * if the version parameter is null, the WFS will return the highest version supported
167
         * if not it will return the lower highest version than the one requested.
168
         * @param host
169
         * @param version
170
         * @return suitable version supported by the server 
171
         */
172
        private static String getSuitableWFSVersion(String host, String _version, boolean ignoreCache) throws ConnectException, IOException {             
173
                String request = WFSProtocolHandler.buildCapabilitiesSuitableVersionRequest(host, _version);
174
                String version = new String(); 
175
                Reader reader = null;
176
                File file = null;
177
                try {           
178
                        URL url = new URL(request);
179
                        if( ignoreCache ) {
180
                            Utilities.removeURL(url);
181
                        }
182
                        file = Utilities.downloadFile(url, "wfs-suitable-version", null);
183
                                                
184
                        reader = new FileReader(file);
185
                        EncodingXMLParser kxmlParser = new EncodingXMLParser();
186
                        kxmlParser.setInput(reader);                
187
                        kxmlParser.nextTag();
188
                        if ( kxmlParser.getEventType() != KXmlParser.END_DOCUMENT ) {                    
189
                                String tag = kxmlParser.getName();
190
                                if (stringUtils.split(tag, ":").length == 2){
191
                                        tag = stringUtils.split(tag, ":")[1];
192
                                }
193
                                if ((tag.compareTo(CapabilitiesTags.WFS_CAPABILITIES_ROOT1_0_0)==0)) {
194
                                        version = kxmlParser.getAttributeValue("", CapabilitiesTags.VERSION);
195
                                }
196
                        }
197
                        // do not forget to close the Stream.                    
198
                        reader.close();                         
199
                        return version;                
200
                } catch(ConnectException conEx) {
201
                        throw new ConnectException(conEx.getMessage());                         
202
                } catch(IOException ioEx) {
203
                        throw new IOException(ioEx.getMessage());         
204
                } catch(XmlPullParserException xmlEx) {
205
                        String fname = "";
206
                        if( file != null ) {
207
                            fname = file.getAbsolutePath();
208
                        }
209
                        logger.warn("Can't get suitable WFS version for host '"+host+"' from file '"+fname+"'.",xmlEx);
210
                        return "";
211
                } finally {                
212
                        if (reader != null) {
213
                                try {
214
                                        reader.close();
215
                                } catch(Exception ex) {
216
                                        logger.warn("Can't close reader.",ex);
217
                                }
218
                        }
219
                } 
220
        }
221
        
222
        /**
223
         * Gets the intersection between the versions supported by the server
224
         * and the versions supported by the application 
225
         * @throws IOException 
226
         * @throws ConnectException 
227
         */
228
        public static List getRequestableVersions(String host, boolean ignoreCache) throws
229
        ConnectException, IOException {
230
            
231
            Iterator iVersion = supportedVersions.iterator();
232
        String wfsVersion;
233
        String gvSIGVersion;
234
        
235
        ArrayList resp = new ArrayList();
236
        
237
        while (iVersion.hasNext()) { 
238
            gvSIGVersion = (String)iVersion.next();
239
            wfsVersion = getSuitableWFSVersion(host,gvSIGVersion, ignoreCache);
240
            if (gvSIGVersion.compareTo(wfsVersion) == 0) {
241
                resp.add(gvSIGVersion);
242
            }
243
        }
244
        return resp;
245
        }
246
        
247
        /**
248
         * It creates an instance of a WFSDriver class.
249
         *
250
         * @param String, with the version of the driver to be created
251
         * @return WFSDriver.
252
         */
253
        public static WFSProtocolHandler createVersionDriver(String version) {               
254
                try {
255
                        Class driver;
256
                        version = version.replace('.', '_');
257
                        driver = Class.forName("org.gvsig.remoteclient.wfs.wfs_"+version+".WFSProtocolHandler" + version);
258
                        return (WFSProtocolHandler)driver.newInstance();
259
                } catch (Exception e) {
260
                        logger.warn("Can't create driver for WFS version '"+version+"'.",e);
261
                        return null;
262
                }
263
        }    
264
        
265
        
266
        
267
}