svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.remoteclient / src / main / java / org / gvsig / remoteclient / wfs / WFSProtocolHandler.java @ 40559
History | View | Annotate | Download (14.2 KB)
1 | 40559 | jjdelcerro | /**
|
---|---|---|---|
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 | 40435 | jjdelcerro | package org.gvsig.remoteclient.wfs; |
25 | |||
26 | import java.io.File; |
||
27 | import java.net.URL; |
||
28 | import java.util.ArrayList; |
||
29 | import java.util.Hashtable; |
||
30 | import java.util.StringTokenizer; |
||
31 | |||
32 | import org.gvsig.compat.net.ICancellable; |
||
33 | import org.gvsig.remoteclient.ogc.OGCProtocolHandler; |
||
34 | import org.gvsig.remoteclient.ogc.OGCServiceInformation; |
||
35 | import org.gvsig.remoteclient.utils.CapabilitiesTags; |
||
36 | import org.gvsig.remoteclient.wfs.exceptions.WFSException; |
||
37 | import org.gvsig.remoteclient.wfs.request.WFSDescribeFeatureTypeRequest; |
||
38 | import org.gvsig.remoteclient.wfs.request.WFSGetFeatureRequest; |
||
39 | import org.gvsig.remoteclient.wfs.request.WFSTLockFeatureRequest; |
||
40 | import org.gvsig.remoteclient.wfs.request.WFSTransactionRequest; |
||
41 | import org.gvsig.remoteclient.wfs.schema.GMLTags; |
||
42 | import org.kxml2.io.KXmlParser; |
||
43 | |||
44 | /* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
|
||
45 | *
|
||
46 | * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
|
||
47 | *
|
||
48 | * This program is free software; you can redistribute it and/or
|
||
49 | * modify it under the terms of the GNU General Public License
|
||
50 | * as published by the Free Software Foundation; either version 2
|
||
51 | * of the License, or (at your option) any later version.
|
||
52 | *
|
||
53 | * This program is distributed in the hope that it will be useful,
|
||
54 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
55 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
56 | * GNU General Public License for more details.
|
||
57 | *
|
||
58 | * You should have received a copy of the GNU General Public License
|
||
59 | * along with this program; if not, write to the Free Software
|
||
60 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,USA.
|
||
61 | *
|
||
62 | * For more information, contact:
|
||
63 | *
|
||
64 | * Generalitat Valenciana
|
||
65 | * Conselleria d'Infraestructures i Transport
|
||
66 | * Av. Blasco Ib??ez, 50
|
||
67 | * 46010 VALENCIA
|
||
68 | * SPAIN
|
||
69 | *
|
||
70 | * +34 963862235
|
||
71 | * gvsig@gva.es
|
||
72 | * www.gvsig.gva.es
|
||
73 | *
|
||
74 | * or
|
||
75 | *
|
||
76 | * IVER T.I. S.A
|
||
77 | * Salamanca 50
|
||
78 | * 46005 Valencia
|
||
79 | * Spain
|
||
80 | *
|
||
81 | * +34 963163400
|
||
82 | * dac@iver.es
|
||
83 | */
|
||
84 | /* CVS MESSAGES:
|
||
85 | *
|
||
86 | * $Id: WFSProtocolHandler.java 34402 2011-01-13 16:47:02Z nbrodin $
|
||
87 | * $Log$
|
||
88 | * Revision 1.11 2007-09-20 09:30:12 jaume
|
||
89 | * removed unnecessary imports
|
||
90 | *
|
||
91 | * Revision 1.10 2007/02/09 14:11:01 jorpiell
|
||
92 | * Primer piloto del soporte para WFS 1.1 y para WFS-T
|
||
93 | *
|
||
94 | * Revision 1.9 2007/01/12 13:09:42 jorpiell
|
||
95 | * added searches by area
|
||
96 | *
|
||
97 | * Revision 1.8 2006/10/10 12:52:28 jorpiell
|
||
98 | * Soporte para features complejas.
|
||
99 | *
|
||
100 | * Revision 1.7 2006/06/21 12:53:03 jorpiell
|
||
101 | * Se tienen en cuanta el n?mero de features
|
||
102 | *
|
||
103 | * Revision 1.6 2006/06/14 08:46:07 jorpiell
|
||
104 | * Se tiene en cuanta la opcion para refrescar las capabilities
|
||
105 | *
|
||
106 | * Revision 1.5 2006/06/14 07:54:18 jorpiell
|
||
107 | * Se parsea el online resource que antes se ignoraba
|
||
108 | *
|
||
109 | * Revision 1.4 2006/05/30 13:58:03 jaume
|
||
110 | * cancelable downloads
|
||
111 | *
|
||
112 | * Revision 1.3 2006/05/23 13:23:13 jorpiell
|
||
113 | * Se ha cambiado el final del bucle de parseado y se tiene en cuenta el online resource
|
||
114 | *
|
||
115 | * Revision 1.2 2006/04/20 16:39:16 jorpiell
|
||
116 | * A?adida la operacion de describeFeatureType y el parser correspondiente.
|
||
117 | *
|
||
118 | * Revision 1.1 2006/04/19 12:51:35 jorpiell
|
||
119 | * A?adidas algunas de las clases del servicio WFS
|
||
120 | *
|
||
121 | *
|
||
122 | */
|
||
123 | /**
|
||
124 | * @author Jorge Piera Llodr? (piera_jor@gva.es)
|
||
125 | */
|
||
126 | public abstract class WFSProtocolHandler extends OGCProtocolHandler { |
||
127 | //protected static Logger LOG = LoggerFactory.getLogger(WFSProtocolHandler.class);
|
||
128 | |||
129 | /**
|
||
130 | * WFS metadata
|
||
131 | */
|
||
132 | protected WFSServiceInformation serviceInfo = new WFSServiceInformation(); |
||
133 | protected Hashtable features = new Hashtable(); |
||
134 | protected String currentFeature = null; |
||
135 | private int numberOfErrors = 0; |
||
136 | |||
137 | /**
|
||
138 | * This class contains all the data that the library is able
|
||
139 | * to retrieve of the server for all the requests.
|
||
140 | */
|
||
141 | protected ArrayList wfsRequestInformations = new ArrayList(); |
||
142 | |||
143 | /**
|
||
144 | * Clear the connection
|
||
145 | */
|
||
146 | private void clear() { |
||
147 | features.clear(); |
||
148 | serviceInfo.clear(); |
||
149 | } |
||
150 | |||
151 | /**
|
||
152 | * <p>Builds a GetCapabilities request that is sent to the WFS
|
||
153 | * the response will be parse to extract the data needed by the
|
||
154 | * WFS client</p>
|
||
155 | */
|
||
156 | public void getCapabilities(WFSStatus status,boolean override, ICancellable cancel) throws WFSException { |
||
157 | URL request = null; |
||
158 | try {
|
||
159 | request = new URL(buildCapabilitiesRequest(status)); |
||
160 | if (override){
|
||
161 | downloader.removeURL(request); |
||
162 | } |
||
163 | File f = downloader.downloadFile(request,"wfs_capabilities.xml", cancel); |
||
164 | if (f == null) |
||
165 | return;
|
||
166 | clear(); |
||
167 | parseCapabilities(f); |
||
168 | } catch (Exception e){ |
||
169 | throw new WFSException(e); |
||
170 | } |
||
171 | } |
||
172 | |||
173 | /**
|
||
174 | * @return
|
||
175 | */
|
||
176 | private String buildCapabilitiesRequest(WFSStatus status) { |
||
177 | StringBuffer req = new StringBuffer(); |
||
178 | String symbol = null; |
||
179 | |||
180 | String onlineResource;
|
||
181 | if (status == null || status.getOnlineResource() == null) |
||
182 | onlineResource = getHost(); |
||
183 | else
|
||
184 | onlineResource = status.getOnlineResource(); |
||
185 | symbol = getSymbol(onlineResource); |
||
186 | |||
187 | req.append(onlineResource).append(symbol).append("REQUEST=GetCapabilities&SERVICE=WFS&");
|
||
188 | req.append("VERSION=").append(getVersion()).append("&EXCEPTIONS=XML"); |
||
189 | return req.toString();
|
||
190 | } |
||
191 | |||
192 | /**
|
||
193 | * Builds the GetCapabilitiesRequest according to the OGC WFS Specifications
|
||
194 | * without a VERSION, to get the highest version than a WFS supports.
|
||
195 | */
|
||
196 | public static String buildCapabilitiesSuitableVersionRequest(String _host, String _version) |
||
197 | { |
||
198 | int index = _host.indexOf('?'); |
||
199 | |||
200 | if (index > -1) { |
||
201 | String host = _host.substring(0, index + 1); |
||
202 | String query = _host.substring(index + 1, _host.length()); |
||
203 | |||
204 | StringTokenizer tokens = new StringTokenizer(query, "&"); |
||
205 | String newQuery = "", token; |
||
206 | |||
207 | // If there is a field or a value with spaces, (and then it's on different tokens) -> unify them
|
||
208 | while (tokens.hasMoreTokens()) {
|
||
209 | token = tokens.nextToken().trim(); |
||
210 | |||
211 | if (token.toUpperCase().compareTo("REQUEST=GETCAPABILITIES") == 0) |
||
212 | continue;
|
||
213 | |||
214 | if (token.toUpperCase().compareTo("SERVICE=WFS") == 0) |
||
215 | continue;
|
||
216 | |||
217 | if ((_version != null) && (_version.length() > 0)) { |
||
218 | if (token.toUpperCase().compareTo("VERSION=" + _version) == 0) |
||
219 | continue;
|
||
220 | } |
||
221 | |||
222 | if (token.toUpperCase().compareTo("EXCEPTIONS=XML") == 0) |
||
223 | continue;
|
||
224 | |||
225 | newQuery += token + "&";
|
||
226 | } |
||
227 | |||
228 | _host = host + newQuery; |
||
229 | } |
||
230 | else {
|
||
231 | _host += "?";
|
||
232 | } |
||
233 | |||
234 | if ((_version != null) && (_version.compareTo("") != 0)) |
||
235 | _host += "REQUEST=GetCapabilities&SERVICE=WFS&VERSION=" + _version + "&EXCEPTIONS=XML"; |
||
236 | else
|
||
237 | _host += "REQUEST=GetCapabilities&SERVICE=WFS&EXCEPTIONS=XML";
|
||
238 | |||
239 | return _host;
|
||
240 | } |
||
241 | |||
242 | /**
|
||
243 | * <p>Builds a describeFeatureType request that is sent to the WFS
|
||
244 | * the response will be parse to extract the data needed by the
|
||
245 | * WFS client</p>
|
||
246 | * @param status
|
||
247 | * WFS client status. Contains all the information to create
|
||
248 | * the query. In this case, the only the feature name is needed.
|
||
249 | */
|
||
250 | public File describeFeatureType(WFSStatus status,boolean override, ICancellable cancel)throws WFSException { |
||
251 | this.currentFeature = status.getFeatureFullName();
|
||
252 | //sets the namespace URI
|
||
253 | if ((status.getNamespacePrefix() != null) && (status.getNamespaceLocation() == null)){ |
||
254 | String namespaceURI = serviceInfo.getNamespace(status.getNamespacePrefix());
|
||
255 | if (namespaceURI != null){ |
||
256 | status.setNamespaceLocation(namespaceURI); |
||
257 | } |
||
258 | } |
||
259 | try {
|
||
260 | WFSDescribeFeatureTypeRequest request = createDescribeFeatureTypeRequest(status); |
||
261 | File f = request.sendRequest(cancel);
|
||
262 | return f;
|
||
263 | } catch (Exception e){ |
||
264 | throw new WFSException(e); |
||
265 | } |
||
266 | } |
||
267 | |||
268 | /**
|
||
269 | * <p>Builds a getFeature request that is sent to the WFS
|
||
270 | * the response will be parse to extract the data needed by the
|
||
271 | * WFS client</p>
|
||
272 | * @param status
|
||
273 | * WFS client status. Contains all the information to create
|
||
274 | * the query.
|
||
275 | * @return File
|
||
276 | * GML file
|
||
277 | */
|
||
278 | public File getFeature(WFSStatus status,boolean override, ICancellable cancel) throws WFSException{ |
||
279 | try{
|
||
280 | WFSGetFeatureRequest request = createGetFeatureRequest(status); |
||
281 | File f = request.sendRequest(cancel);
|
||
282 | parseGetFeature(f, status.getNamespacePrefix()); |
||
283 | return f;
|
||
284 | } catch (Exception e){ |
||
285 | throw new WFSException(e); |
||
286 | } |
||
287 | } |
||
288 | |||
289 | /**
|
||
290 | * parses the data retrieved by the GetFeature XML document. It is
|
||
291 | * used just to find errors
|
||
292 | */
|
||
293 | protected abstract boolean parseGetFeature(File f,String nameSpace) throws WFSException; |
||
294 | |||
295 | |||
296 | /**
|
||
297 | * <p>Builds a transaction request that is sent to the WFS
|
||
298 | * the response will be parse to extract the data needed by the
|
||
299 | * WFS client</p>
|
||
300 | * @param status
|
||
301 | * WFS client status. Contains all the information to create
|
||
302 | * the query.
|
||
303 | */
|
||
304 | public void transaction(WFSStatus status,boolean override, ICancellable cancel) throws WFSException { |
||
305 | try {
|
||
306 | WFSTransactionRequest request = createTransactionRequest(status); |
||
307 | File f = request.sendRequest(cancel);
|
||
308 | parseTransaction(f, status); |
||
309 | } catch (Exception e){ |
||
310 | throw new WFSException(e); |
||
311 | } |
||
312 | } |
||
313 | |||
314 | /**
|
||
315 | * <p>Builds a transaction request that is sent to the WFS
|
||
316 | * the response will be parse to extract the data needed by the
|
||
317 | * WFS client</p>
|
||
318 | * @param status
|
||
319 | * WFS client status. Contains all the information to create
|
||
320 | * the query.
|
||
321 | */
|
||
322 | private String buildTransactionRequest(WFSStatus status){ |
||
323 | StringBuffer req = new StringBuffer(); |
||
324 | String symbol = null; |
||
325 | |||
326 | String onlineResource;
|
||
327 | if(serviceInfo.getOnlineResource(CapabilitiesTags.WFS_TRANSACTION) != null){ |
||
328 | onlineResource = serviceInfo.getOnlineResource(CapabilitiesTags.WFS_TRANSACTION); |
||
329 | }else {
|
||
330 | onlineResource = getHost(); |
||
331 | } |
||
332 | symbol = getSymbol(onlineResource); |
||
333 | |||
334 | req.append(onlineResource); |
||
335 | return req.toString();
|
||
336 | } |
||
337 | |||
338 | /**
|
||
339 | * parses the data retrieved by the transaction operation
|
||
340 | * @param f
|
||
341 | * The retrieved file
|
||
342 | * @param nameSpace
|
||
343 | * The namespace
|
||
344 | */
|
||
345 | protected abstract boolean parseTransaction(File f, WFSStatus status) throws WFSException; |
||
346 | |||
347 | /**
|
||
348 | * <p>Builds a lockFeature request that is sent to the WFS
|
||
349 | * the response will be parse to extract the data needed by the
|
||
350 | * WFS client</p>
|
||
351 | * @param status
|
||
352 | * WFS client status. Contains all the information to create
|
||
353 | * the query.
|
||
354 | */
|
||
355 | public void lockFeature(WFSStatus status,boolean override, ICancellable cancel) throws WFSException { |
||
356 | try {
|
||
357 | WFSTLockFeatureRequest request = createLockFeatureRequest(status); |
||
358 | File f = request.sendRequest(cancel);
|
||
359 | parseLockFeature(f,status.getNamespacePrefix(),status); |
||
360 | } catch(WFSException e) {
|
||
361 | throw e;
|
||
362 | } catch (Exception e){ |
||
363 | throw new WFSException(e); |
||
364 | } |
||
365 | } |
||
366 | |||
367 | /**
|
||
368 | * parses the data retrieved by the LockFeature operation
|
||
369 | */
|
||
370 | protected abstract boolean parseLockFeature(File f,String nameSpace, WFSStatus status) throws WFSException; |
||
371 | |||
372 | /**
|
||
373 | * @return Returns the features.
|
||
374 | */
|
||
375 | public Hashtable getFeatures() { |
||
376 | return features;
|
||
377 | } |
||
378 | |||
379 | /**
|
||
380 | * @return Returns the currentFeature.
|
||
381 | */
|
||
382 | public String getCurrentFeature() { |
||
383 | return currentFeature;
|
||
384 | } |
||
385 | |||
386 | /**
|
||
387 | * @param currentFeature The currentFeature to set.
|
||
388 | */
|
||
389 | public void setCurrentFeature(String currentFeature) { |
||
390 | this.currentFeature = currentFeature;
|
||
391 | } |
||
392 | |||
393 | /**
|
||
394 | * It parses the attributes of the current KXMLParser
|
||
395 | * and add the new namespaces to the service information
|
||
396 | * @param parser
|
||
397 | * The KXML parser
|
||
398 | */
|
||
399 | protected void parseNamespaces(KXmlParser parser){ |
||
400 | for (int i=0 ; i<parser.getAttributeCount() ; i++){ |
||
401 | String attName = parser.getAttributeName(i);
|
||
402 | if (attName.startsWith(GMLTags.XML_NAMESPACE)){
|
||
403 | int index = attName.indexOf(":"); |
||
404 | if (index > 0){ |
||
405 | serviceInfo.addNamespace(attName.substring(index+1, attName.length()),
|
||
406 | parser.getAttributeValue(i)); |
||
407 | } |
||
408 | } |
||
409 | } |
||
410 | } |
||
411 | |||
412 | /* (non-Javadoc)
|
||
413 | * @see org.gvsig.remoteClient.ogc.OGCProtocolHandler#getServiceInformation()
|
||
414 | */
|
||
415 | public OGCServiceInformation getServiceInformation() {
|
||
416 | return serviceInfo;
|
||
417 | } |
||
418 | |||
419 | /**
|
||
420 | * @param status
|
||
421 | * The WFS status
|
||
422 | * @param protocolHandler
|
||
423 | * The handler to parse the requests
|
||
424 | * @return an object to send the DescribeFeatureType requests
|
||
425 | */
|
||
426 | protected abstract WFSDescribeFeatureTypeRequest createDescribeFeatureTypeRequest(WFSStatus status); |
||
427 | |||
428 | /**
|
||
429 | * @param status
|
||
430 | * The WFS status
|
||
431 | * @param protocolHandler
|
||
432 | * The handler to parse the requests
|
||
433 | * @return an object to send the GetFeature requests
|
||
434 | */
|
||
435 | protected abstract WFSGetFeatureRequest createGetFeatureRequest(WFSStatus status); |
||
436 | |||
437 | /**
|
||
438 | * @param status
|
||
439 | * The WFS status
|
||
440 | * @param protocolHandler
|
||
441 | * The handler to parse the requests
|
||
442 | * @return an object to send the LockFeature requests
|
||
443 | */
|
||
444 | protected abstract WFSTLockFeatureRequest createLockFeatureRequest(WFSStatus status); |
||
445 | |||
446 | /**
|
||
447 | * @param status
|
||
448 | * The WFS status
|
||
449 | * @param protocolHandler
|
||
450 | * The handler to parse the requests
|
||
451 | * @return an object to send the Transaction request
|
||
452 | */
|
||
453 | protected abstract WFSTransactionRequest createTransactionRequest(WFSStatus status); |
||
454 | |||
455 | /**
|
||
456 | * @return the wfsRequestInformations
|
||
457 | */
|
||
458 | ArrayList getWfsRequestInformations() {
|
||
459 | return wfsRequestInformations;
|
||
460 | } |
||
461 | |||
462 | /**
|
||
463 | * Adds a new WFSRequestInformation
|
||
464 | * @param wfsRequestInformation
|
||
465 | */
|
||
466 | public void addLastWfsRequestInformation( |
||
467 | WFSRequestInformation wfsRequestInformation) { |
||
468 | wfsRequestInformations.add(wfsRequestInformation); |
||
469 | } |
||
470 | |||
471 | /**
|
||
472 | * @return the lastWfsRequestInformation
|
||
473 | */
|
||
474 | public WFSRequestInformation getLastWfsRequestInformation() {
|
||
475 | if (wfsRequestInformations.size() > 0){ |
||
476 | return (WFSRequestInformation)wfsRequestInformations.get(wfsRequestInformations.size() - 1); |
||
477 | } |
||
478 | return null; |
||
479 | } |
||
480 | } |