001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/portal/standard/wfs/control/WFSClientListener.java $ 002 /*---------------------------------------------------------------------------- 003 This file is part of deegree, http://deegree.org/ 004 Copyright (C) 2001-2009 by: 005 Department of Geography, University of Bonn 006 and 007 lat/lon GmbH 008 009 This library is free software; you can redistribute it and/or modify it under 010 the terms of the GNU Lesser General Public License as published by the Free 011 Software Foundation; either version 2.1 of the License, or (at your option) 012 any later version. 013 This library is distributed in the hope that it will be useful, but WITHOUT 014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 016 details. 017 You should have received a copy of the GNU Lesser General Public License 018 along with this library; if not, write to the Free Software Foundation, Inc., 019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 020 021 Contact information: 022 023 lat/lon GmbH 024 Aennchenstr. 19, 53177 Bonn 025 Germany 026 http://lat-lon.de/ 027 028 Department of Geography, University of Bonn 029 Prof. Dr. Klaus Greve 030 Postfach 1147, 53001 Bonn 031 Germany 032 http://www.geographie.uni-bonn.de/deegree/ 033 034 e-mail: info@deegree.org 035 ----------------------------------------------------------------------------*/ 036 037 package org.deegree.portal.standard.wfs.control; 038 039 import java.io.BufferedReader; 040 import java.io.File; 041 import java.io.FileReader; 042 import java.io.IOException; 043 import java.io.InputStream; 044 import java.io.InputStreamReader; 045 import java.net.URL; 046 047 import javax.servlet.http.HttpServletRequest; 048 import javax.servlet.http.HttpSession; 049 050 import org.apache.commons.httpclient.HttpClient; 051 import org.apache.commons.httpclient.methods.PostMethod; 052 import org.apache.commons.httpclient.methods.StringRequestEntity; 053 import org.deegree.enterprise.WebUtils; 054 import org.deegree.enterprise.control.AbstractListener; 055 import org.deegree.enterprise.control.FormEvent; 056 import org.deegree.enterprise.control.RPCMember; 057 import org.deegree.enterprise.control.RPCParameter; 058 import org.deegree.enterprise.control.RPCStruct; 059 import org.deegree.enterprise.control.RPCWebEvent; 060 import org.deegree.framework.log.ILogger; 061 import org.deegree.framework.log.LoggerFactory; 062 import org.deegree.framework.util.CharsetUtils; 063 import org.deegree.framework.util.StringTools; 064 import org.deegree.framework.xml.XMLFragment; 065 import org.deegree.model.feature.FeatureCollection; 066 import org.deegree.model.feature.GMLFeatureAdapter; 067 import org.deegree.model.feature.GMLFeatureCollectionDocument; 068 import org.deegree.portal.context.AbstractFrontend; 069 import org.deegree.portal.context.GeneralExtension; 070 import org.deegree.portal.context.Module; 071 import org.deegree.portal.context.ViewContext; 072 import org.deegree.portal.standard.wfs.WFSClientException; 073 074 /** 075 * The WFSClientListener 1. receives an RPC request, 2. builds a request to a WFS service using the values given in the 076 * RPC request, 3. sends the request to the specified WFS, 4. receives the result from the WFS and 5. forwards the 077 * result to the WFSClient. 078 * 079 * @author <a href="mailto:mays@lat-lon.de">Judit Mays</a> 080 * @author last edited by: $Author: mschneider $ 081 * 082 * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $ 083 */ 084 public class WFSClientListener extends AbstractListener { 085 086 private static final ILogger LOG = LoggerFactory.getLogger( WFSClientListener.class ); 087 088 protected static final String INIT_TARGETSRS = "TARGETSRS"; 089 090 protected static final String INIT_XSLT = "XSLT"; 091 092 /* 093 * (non-Javadoc) 094 * 095 * @see org.deegree.enterprise.control.WebListener#actionPerformed(org.deegree.enterprise.control.FormEvent) 096 */ 097 @Override 098 public void actionPerformed( FormEvent event ) { 099 100 RPCWebEvent rpcEvent = (RPCWebEvent) event; 101 102 try { 103 validateRequest( rpcEvent ); 104 } catch ( Exception e ) { 105 LOG.logError( e.getMessage(), e ); 106 gotoErrorPage( "Invalid rpc request: \n" + e.getMessage() ); 107 108 return; 109 } 110 111 try { 112 doGetFeature( rpcEvent ); 113 } catch ( Exception e ) { 114 LOG.logError( e.getMessage(), e ); 115 gotoErrorPage( "doGetFeature not successful: \n" + e.getMessage() ); 116 117 return; 118 } 119 120 } 121 122 /** 123 * TODO check validation: are all elements checked? which elements are mandatory? ...? 124 * 125 * @param rpcEvent 126 * @throws WFSClientException 127 */ 128 private void validateRequest( RPCWebEvent rpcEvent ) 129 throws WFSClientException { 130 131 RPCParameter[] params = rpcEvent.getRPCMethodCall().getParameters(); 132 if ( params.length != 1 ) { 133 134 throw new WFSClientException( "Request/Method Call must contain one parameter, not: " + params.length ); 135 } 136 137 RPCStruct rpcStruct = (RPCStruct) params[0].getValue(); 138 139 if ( rpcStruct.getMember( "MODULE" ) == null ) { 140 141 throw new WFSClientException( "Request does not contain mandatory element MODULE." ); 142 } 143 144 String tmp = (String) rpcStruct.getMember( "MODULE" ).getValue(); 145 if ( tmp == null || tmp.length() < 1 ) { 146 147 throw new WFSClientException( "Mandatory element MODULE must be set." ); 148 } 149 try { 150 if ( rpcStruct.getMember( "FEATURETYPES" ) != null ) { 151 tmp = (String) rpcStruct.getMember( "FEATURETYPES" ).getValue(); 152 // LOG.logDebug( "FEATURETYPES: " + tmp ); 153 } 154 if ( rpcStruct.getMember( "QUERYTEMPLATE" ) != null ) { 155 tmp = (String) rpcStruct.getMember( "QUERYTEMPLATE" ).getValue(); 156 // LOG.logDebug( "QUERYTEMPLATE: " + tmp ); 157 } 158 if ( rpcStruct.getMember( "FILTER" ) != null ) { 159 tmp = (String) rpcStruct.getMember( "FILTER" ).getValue(); 160 // LOG.logDebug( "FILTER: " + tmp ); 161 } 162 if ( rpcStruct.getMember( "FILTERPROPERTIES" ) != null ) { 163 tmp = (String) rpcStruct.getMember( "FILTERPROPERTIES" ).getValue(); 164 // LOG.logDebug( "FILTERPROPERTIES: " + tmp ); 165 } 166 if ( rpcStruct.getMember( "RESULTFORMAT" ) != null ) { 167 tmp = (String) rpcStruct.getMember( "RESULTFORMAT" ).getValue(); 168 // LOG.logDebug( "RESULTFORMAT: " + tmp ); 169 } 170 if ( rpcStruct.getMember( "XMLNS" ) != null ) { 171 tmp = (String) rpcStruct.getMember( "XMLNS" ).getValue(); 172 // LOG.logDebug( "XMLNS: " + tmp ); 173 } 174 if ( rpcStruct.getMember( "NORMALIZE" ) != null ) { 175 Boolean shouldNormalize = (Boolean) rpcStruct.getMember( "NORMALIZE" ).getValue(); 176 LOG.logDebug( "NORMALIZE: " + shouldNormalize ); 177 } 178 if ( rpcStruct.getMember( "LOCALE" ) != null ) { 179 tmp = (String) rpcStruct.getMember( "LOCALE" ).getValue(); 180 // LOG.logDebug( "LOCALE: " + tmp ); 181 } 182 if ( rpcStruct.getMember( "SESSIONID" ) != null ) { 183 tmp = (String) rpcStruct.getMember( "SESSIONID" ).getValue(); 184 // LOG.logDebug( "SESSIONID: " + tmp ); 185 } 186 } catch ( Exception e ) { 187 LOG.logError( e.getMessage(), e ); 188 189 throw new WFSClientException( "Member of rpc request must not be null or empty: ", e ); 190 } 191 192 } 193 194 /** 195 * 196 * @param rpcEvent 197 * @throws WFSClientException 198 */ 199 protected void doGetFeature( RPCWebEvent rpcEvent ) 200 throws WFSClientException { 201 202 RPCParameter[] params = rpcEvent.getRPCMethodCall().getParameters(); 203 RPCStruct rpcStruct = (RPCStruct) params[0].getValue(); 204 205 // xml namespaces 206 String tmp = null; 207 RPCMember rpcMember = rpcStruct.getMember( "XMLNS" ); 208 String[] xmlns = null; 209 if ( rpcMember != null ) { 210 tmp = (String) rpcMember.getValue(); 211 } 212 if ( tmp == null ) { 213 xmlns = new String[0]; 214 } else { 215 xmlns = StringTools.toArray( tmp, ",", true ); 216 } 217 218 // NORMALIZATION 219 // check if the query string needs to be normalized 220 Boolean getsNormalized = false; 221 rpcMember = rpcStruct.getMember( "NORMALIZE" ); 222 if ( rpcMember != null ) { 223 getsNormalized = (Boolean) rpcMember.getValue(); 224 } 225 // set locale for normalization 226 String locale = null; 227 if ( getsNormalized ) { 228 rpcMember = rpcStruct.getMember( "LOCALE" ); 229 if ( rpcMember != null ) { 230 locale = (String) rpcMember.getValue(); 231 } else { 232 locale = "default"; 233 } 234 } 235 236 // CREATE QUERY 237 // featuretypes to query 238 rpcMember = rpcStruct.getMember( "FEATURETYPES" ); 239 tmp = (String) rpcMember.getValue(); 240 String[] featureTypes = StringTools.toArray( tmp, ",", true ); 241 242 String moduleName = (String) rpcStruct.getMember( "MODULE" ).getValue(); 243 String query = null; 244 245 // use template or filter to build query 246 if ( rpcStruct.getMember( "QUERYTEMPLATE" ) != null ) { 247 String queryTemplate = (String) rpcStruct.getMember( "QUERYTEMPLATE" ).getValue(); 248 RPCMember filterProperties = rpcStruct.getMember( "FILTERPROPERTIES" ); 249 RPCMember sessionId = rpcStruct.getMember( "SESSIONID" ); 250 try { 251 query = createQueryFromTemplate( queryTemplate, moduleName, filterProperties, sessionId, 252 getsNormalized, locale ); 253 } catch ( Exception e ) { 254 LOG.logError( e.getMessage(), e ); 255 256 throw new WFSClientException( "Could not create query from template: " + e.getMessage() ); 257 } 258 getRequest().setAttribute( "QUERYTEMPLATE", queryTemplate ); 259 260 } else if ( rpcStruct.getMember( "FILTER" ) != null ) { 261 // TODO this is not implemented yet 262 String filter = (String) rpcStruct.getMember( "FILTER" ).getValue(); 263 query = createQueryFromFilter( featureTypes, xmlns, filter, getsNormalized, locale ); 264 } else { 265 // TODO reactivate this option 266 // String filter = createFilterFromProperties(); 267 // query = createQueryFromFilter( featureTypes, xmlns, filter, getsNormalized ); 268 throw new WFSClientException( "could not create query" ); 269 } 270 271 // PERFORM QUERY 272 // LOG.logDebug( "\n***** QUERY *****\n" + query + "\n" ); 273 XMLFragment response = performQuery( query, moduleName ); 274 // LOG.logDebug( "\n***** RESPONSE *****\n" + response.getAsString() + "\n" ); 275 276 FeatureCollection fc = null; 277 try { 278 GMLFeatureCollectionDocument doc = new GMLFeatureCollectionDocument(); 279 doc.setRootElement( response.getRootElement() ); 280 fc = doc.parse(); 281 } catch ( Exception e ) { 282 // DOMPrinter.printNode( response.getRootElement(), " " ); 283 LOG.logError( e.getMessage(), e ); 284 285 throw new WFSClientException( "Could not build FeatureCollection from xml Document: " + e.getMessage() ); 286 } 287 // TODO replace initParam 288 // if ( getInitParam( INIT_TARGETSRS ) != null ) { 289 // try { 290 // // TODO comment in again when needed 291 // fc = transformGeometries( fc ); 292 // } catch ( Exception e ) { 293 // LOG.logError( e.getMessage(), e ); 294 // 295 // throw new WFSClientException( "Could not transform geometries in FeatureCollection." ); 296 // } 297 // } 298 299 String resultFormat = null; 300 rpcMember = rpcStruct.getMember( "RESULTFORMAT" ); 301 if ( rpcMember != null ) { 302 resultFormat = (String) rpcMember.getValue(); 303 } 304 if ( !"XML".equals( resultFormat ) && !"FEATURECOLLECTION".equals( resultFormat ) ) { 305 throw new WFSClientException( "resultFormat" ); 306 } 307 308 // WRITE FEATURE RESULTS BACK TO CLIENT 309 try { 310 writeGetFeatureResult( fc, resultFormat ); 311 } catch ( Exception e ) { 312 LOG.logError( e.getMessage(), e ); 313 314 throw new WFSClientException( "Could not write getFeatureResult: " + e.getMessage() ); 315 } 316 317 } 318 319 /** 320 * Creates a WFS GetFeature query from a named template and a set of KVP-encoded properties. 321 * 322 * @param queryTemplate 323 * @param moduleName 324 * @param filterProperties 325 * @param sessionId 326 * the users session id. may be null. 327 * @param getsNormalized 328 * if true, the filter string gets normalized 329 * @param locale 330 * the locale language defining the normalization rules to choose, e.g. "de" 331 * @return Returns the WFS GetFeature query as String. 332 * @throws WFSClientException 333 */ 334 private String createQueryFromTemplate( String queryTemplate, String moduleName, RPCMember filterProperties, 335 RPCMember sessionId, Boolean getsNormalized, String locale ) 336 throws WFSClientException { 337 338 HttpSession session = ( (HttpServletRequest) this.getRequest() ).getSession( true ); 339 ViewContext vc = (ViewContext) session.getAttribute( org.deegree.portal.Constants.CURRENTMAPCONTEXT ); 340 341 GeneralExtension ge = vc.getGeneral().getExtension(); 342 AbstractFrontend fe = (AbstractFrontend) ge.getFrontend(); 343 Module module = null; 344 Module[] mods = fe.getModulesByName( moduleName ); 345 if ( mods.length > 0 ) { 346 module = mods[0]; 347 } else { 348 LOG.logError( "no module with the name" + moduleName + "could be found." ); 349 350 throw new WFSClientException( "The current map context does not contain the module:" + moduleName ); 351 } 352 353 queryTemplate = (String) module.getParameter().getParameter( queryTemplate ).getValue(); 354 if ( queryTemplate.startsWith( "'" ) && queryTemplate.endsWith( "'" ) ) { 355 // strip ' from front and end of string 356 queryTemplate = queryTemplate.substring( 1, queryTemplate.length() - 1 ); 357 } 358 359 if ( !( new File( queryTemplate ).isAbsolute() ) ) { 360 queryTemplate = getHomePath() + queryTemplate; 361 LOG.logDebug( "The template file now has an absolute path: " + queryTemplate ); 362 } 363 StringBuffer template = new StringBuffer( 10000 ); 364 try { 365 BufferedReader br = new BufferedReader( new FileReader( queryTemplate ) ); 366 String line = null; 367 while ( ( line = br.readLine() ) != null ) { 368 template.append( line ); 369 } 370 br.close(); 371 } catch ( IOException e ) { 372 LOG.logError( e.getMessage(), e ); 373 374 throw new WFSClientException( "could not read query template: " + queryTemplate ); 375 } 376 String query = template.toString(); 377 378 // SUBSTITUTE FILTER PROPERTIES 379 String tmp = null; 380 if ( filterProperties != null ) { 381 tmp = (String) filterProperties.getValue(); // tmp={myKey=searchStringXXX}{key2=value2} 382 } 383 384 if ( tmp != null ) { 385 String[] properties = StringTools.extractStrings( tmp, "{", "}" ); 386 387 for ( int i = 0; i < properties.length; i++ ) { 388 if ( properties[i].startsWith( "{" ) ) { 389 properties[i] = properties[i].substring( 1, properties[i].length() ); 390 } 391 if ( properties[i].endsWith( "}" ) ) { 392 properties[i] = properties[i].substring( 0, properties[i].length() - 1 ); 393 } 394 395 String[] kvp = StringTools.toArray( properties[i], "=", false ); 396 // FIXME instead of using "%" as wildcard: read the wildcard character from the 397 // template! 398 kvp[1] = StringTools.replace( kvp[1], "XXX", "%", true ); 399 400 if ( getsNormalized ) { 401 try { 402 kvp[1] = StringTools.normalizeString( kvp[1], locale ); 403 } catch ( Exception e ) { 404 LOG.logError( "the search string of the filter property could not be normalized", e ); 405 throw new WFSClientException( e.getMessage(), e ); 406 } 407 } 408 query = StringTools.replace( query, '$' + kvp[0], kvp[1], true ); 409 } 410 } 411 412 // SUBSTITUTE SESSION_ID 413 tmp = null; 414 if ( sessionId != null ) { 415 tmp = (String) sessionId.getValue(); 416 } 417 query = StringTools.replace( query, "$SESSION_ID", tmp, true ); 418 419 return query; 420 } 421 422 /** 423 * Creates a WFS GetFeature query from a OGC filter expression sent from a client. 424 * 425 * TODO: implement support for getNormalized 426 * 427 * @param featureTypes 428 * @param xmlns 429 * @param filter 430 * @param getsNormalized 431 * if true, the filter string gets normalized 432 * @param locale 433 * the locale language defining the normalization rules to choose, e.g. "de" 434 * @return Returns the WFS GetFeature query as String. 435 */ 436 private String createQueryFromFilter( String[] featureTypes, String[] xmlns, String filter, Boolean getsNormalized, 437 String locale ) { 438 439 // TODO handle SESSIONID if it is part of the rpc request 440 441 // normalize filter if needed 442 if ( getsNormalized ) { 443 // FIXME remove try-catch. 444 // TODO Proper implementation of method doNormalizeFilter(). 445 try { 446 filter = doNormalizeFilter( filter, locale ); 447 } catch ( Exception e ) { 448 LOG.logError( "Could not normalize filter.", e ); 449 } 450 } 451 452 StringBuffer query = new StringBuffer( 20000 ); 453 String format = "text/xml; subtype=gml/3.1.1"; 454 String resultType = "results"; 455 456 // TODO get values for parameters from rpc Request 457 // if ( parameter.get( "OUTPUTFORMAT" ) != null ) { 458 // format = (String) parameter.get( "OUTPUTFORMAT" ); 459 // } 460 // if ( parameter.get( "RESULTTYPE" ) != null ) { 461 // resultType = (String) parameter.get( "RESULTTYPE" ); 462 // } 463 464 query.append( "<wfs:GetFeature outputFormat='" ).append( format ); 465 query.append( " resultType='" ).append( resultType ).append( "' " ); 466 467 for ( int i = 0; i < xmlns.length; i++ ) { 468 String[] tmp = StringTools.toArray( xmlns[i], "=", false ); 469 query.append( "xmlns:" ).append( tmp[0] ).append( "='" ); 470 query.append( tmp[1] ).append( "' " ); 471 } 472 query.append( "xmlns:wfs='http://www.opengis.net/wfs' " ); 473 query.append( "xmlns:ogc='http://www.opengis.net/ogc' " ); 474 query.append( "xmlns:gml='http://www.opengis.net/gml' " ); 475 query.append( ">" ); 476 477 query.append( "<wfs:Query " ); 478 for ( int i = 0; i < featureTypes.length; i++ ) { 479 query.append( "typeName='" ).append( featureTypes[i] ); 480 if ( i < featureTypes.length - 1 ) { 481 query.append( "," ); 482 } 483 } 484 query.append( "'>" ); 485 query.append( filter ); 486 query.append( "</wfs:Query></wfs:GetFeature>" ); 487 488 return query.toString(); 489 } 490 491 // /** 492 // * creates an OGC FE filter from a set of KVP-encode properties and logical operations 493 // * 494 // * @return 495 // */ 496 // private String createFilterFromProperties() { 497 // // TODO normalization 498 // // TODO handle SESSIONID if it is part of the rpc request 499 // 500 // String tmp = (String) parameter.get( "FILTERPROPERTIES" ); 501 // if ( tmp != null ) { 502 // String[] properties = StringExtend.extractArray( tmp, "{", "}" ); 503 // String logOp = (String) parameter.get( "LOGICALOPERATOR" ); 504 // StringBuffer filter = new StringBuffer( 10000 ); 505 // filter.append( "<ogc:Filter>" ); 506 // if ( properties.length > 1 ) { 507 // filter.append( "<ogc:" ).append( logOp ).append( '>' ); 508 // } 509 // for ( int i = 0; i < properties.length; i++ ) { 510 // String[] prop = StringExtend.extractArray( tmp, "[", "]" ); 511 // if ( "!=".equals( prop[1] ) || "NOT LIKE".equals( prop[1] ) ) { 512 // filter.append( "<ogc:Not>" ); 513 // } 514 // if ( "=".equals( prop[1] ) || "!=".equals( prop[1] ) ) { 515 // filter.append( "<ogc:PropertyIsEqualTo>" ); 516 // filter.append( "<ogc:PropertyName>" ).append( prop[0] ).append( "</ogc:PropertyName>" ); 517 // filter.append( "<ogc:Literal>" ).append( prop[2] ).append( "</ogc:Literal>" ); 518 // filter.append( "</ogc:PropertyIsEqualTo>" ); 519 // } else if ( ">=".equals( prop[1] ) ) { 520 // filter.append( "<ogc:PropertyIsGreaterThanOrEqualTo>" ); 521 // filter.append( "<ogc:PropertyName>" ).append( prop[0] ).append( "</ogc:PropertyName>" ); 522 // filter.append( "<ogc:Literal>" ).append( prop[2] ).append( "</ogc:Literal>" ); 523 // filter.append( "</ogc:PropertyIsGreaterThanOrEqualTo>" ); 524 // } else if ( ">".equals( prop[1] ) ) { 525 // filter.append( "<ogc:PropertyIsGreaterThan>" ); 526 // filter.append( "<ogc:PropertyName>" ).append( prop[0] ).append( "</ogc:PropertyName>" ); 527 // filter.append( "<ogc:Literal>" ).append( prop[2] ).append( "</ogc:Literal>" ); 528 // filter.append( "</ogc:PropertyIsGreaterThan>" ); 529 // } else if ( "<=".equals( prop[1] ) ) { 530 // filter.append( "<ogc:PropertyIsLessThanOrEqualTo>" ); 531 // filter.append( "<ogc:PropertyName>" ).append( prop[0] ).append( "</ogc:PropertyName>" ); 532 // filter.append( "<ogc:Literal>" ).append( prop[2] ).append( "</ogc:Literal>" ); 533 // filter.append( "</ogc:PropertyIsLessThanOrEqualTo>" ); 534 // } else if ( "<".equals( prop[1] ) ) { 535 // filter.append( "<ogc:PropertyIsLessThan>" ); 536 // filter.append( "<ogc:PropertyName>" ).append( prop[0] ).append( "</ogc:PropertyName>" ); 537 // filter.append( "<ogc:Literal>" ).append( prop[2] ).append( "</ogc:Literal>" ); 538 // filter.append( "</ogc:PropertyIsLessThan>" ); 539 // } else if ( "LIKE".equals( prop[1] ) || "NOT LIKE".equals( prop[1] ) ) { 540 // filter.append( "<ogc:PropertyIsLike wildCard='%' singleChar='#' escape='!'>" ); 541 // filter.append( "<ogc:PropertyName>" ).append( prop[0] ).append( "</ogc:PropertyName>" ); 542 // filter.append( "<ogc:Literal>" ).append( prop[2] ).append( "</ogc:Literal>" ); 543 // filter.append( "</ogc:PropertyIsLike>" ); 544 // } 545 // if ( "!=".equals( prop[1] ) || "NOT LIKE".equals( prop[1] ) ) { 546 // filter.append( "</ogc:Not>" ); 547 // } 548 // } 549 // if ( properties.length > 1 ) { 550 // filter.append( "</ogc:" ).append( logOp ).append( '>' ); 551 // } 552 // filter.append( "</ogc:Filter>" ); 553 // return filter.toString(); 554 // } 555 // return ""; 556 // } 557 558 /** 559 * Replace the filter string with a normalized version. 560 * 561 * @param filter 562 * @param locale 563 * the locale language defining the normalization rules to choose, e.g. "de" 564 * @return the query with a normalized filter if query cannot be transformed to XMLFragment 565 */ 566 private String doNormalizeFilter( String filter, String locale ) { 567 568 throw new UnsupportedOperationException( "this method is not fully implemented yet" ); 569 570 // 571 // 572 // XMLFragment xmlFilter = new XMLFragment(); 573 // try { 574 // xmlFilter.load( new StringReader( filter ), 575 // "http://www.deegree.org/portal/standard/WFSClientListener" ); 576 // xmlFilter.prettyPrint( System.out ); 577 // } catch ( Exception e ) { 578 // LOG.logError( e.getMessage() ); 579 // throw new WFSClientException( "Could not transform filter into XMLFragment", e ); 580 // } 581 // 582 // //FIXME normalization of filter using the passed locale ! 583 // 584 // 585 // return xmlFilter.getAsString(); 586 } 587 588 /** 589 * Performs a GetFeature query against a WFS. 590 * 591 * The WFS address is defined in the module configuration: The default WFS is given with Parameter Name = WFS. If a 592 * different WFS is to be used for a special querytemplate, this is defined by specifying ParameterName = 593 * WFS:querytemplate 594 * 595 * @param query 596 * @param moduleName 597 * @return Returns the response to a WFS GetFeature request as xml Document. 598 * @throws WFSClientException 599 */ 600 private XMLFragment performQuery( String query, String moduleName ) 601 throws WFSClientException { 602 603 HttpSession session = ( (HttpServletRequest) this.getRequest() ).getSession( true ); 604 ViewContext vc = (ViewContext) session.getAttribute( org.deegree.portal.Constants.CURRENTMAPCONTEXT ); 605 606 // WFS to contact 607 GeneralExtension ge = vc.getGeneral().getExtension(); 608 AbstractFrontend fe = (AbstractFrontend) ge.getFrontend(); 609 Module module = null; 610 Module[] mods = fe.getModulesByName( moduleName ); 611 if ( mods.length > 0 ) { 612 module = mods[0]; 613 } else { 614 LOG.logError( "no module with the name" + moduleName + "could be found." ); 615 616 throw new WFSClientException( "The current map context does not contain the module:" + moduleName ); 617 } 618 619 // get WFS address for template of current featuretype OR, if not available, the default WFS 620 String wfsAddress = null; 621 String queryTemplate = (String) getRequest().getAttribute( "QUERYTEMPLATE" ); 622 if ( module.getParameter().getParameter( "WFS:" + queryTemplate ) != null ) { 623 wfsAddress = (String) module.getParameter().getParameter( "WFS:" + queryTemplate ).getValue(); 624 } else { 625 wfsAddress = (String) module.getParameter().getParameter( "WFS" ).getValue(); 626 } 627 if ( wfsAddress == null ) { 628 629 throw new WFSClientException( "WFS is not known by the portal" ); 630 } 631 if ( wfsAddress.startsWith( "'" ) && wfsAddress.endsWith( "'" ) ) { 632 // strip ' from front and end of string 633 wfsAddress = wfsAddress.substring( 1, wfsAddress.length() - 1 ); 634 } 635 636 InputStream is = null; 637 try { 638 StringRequestEntity re = new StringRequestEntity( query, "text/xml", CharsetUtils.getSystemCharset() ); 639 PostMethod post = new PostMethod( wfsAddress ); 640 post.setRequestEntity( re ); 641 post.setRequestHeader( "Content-type", "text/xml;charset=" + CharsetUtils.getSystemCharset() ); 642 643 HttpClient client = new HttpClient(); 644 client = WebUtils.enableProxyUsage( client, new URL( wfsAddress ) ); 645 client.executeMethod( post ); 646 is = post.getResponseBodyAsStream(); 647 } catch ( IOException e ) { 648 LOG.logError( e.getMessage(), e ); 649 650 throw new WFSClientException( "could not perform query against the WFS." ); 651 } 652 653 XMLFragment xmlFrag = new XMLFragment(); 654 try { 655 InputStreamReader isr = new InputStreamReader( is, CharsetUtils.getSystemCharset() ); 656 xmlFrag.load( isr, wfsAddress ); 657 } catch ( Exception e ) { 658 LOG.logError( e.getMessage(), e ); 659 660 throw new WFSClientException( "could not load xmlFragment. \n" + e.getMessage(), e ); 661 } 662 return xmlFrag; 663 } 664 665 /** 666 * writes the result into the forwarded request object 667 * 668 * @param fc 669 * @param resultFormat 670 * the format of the result in the servlet request. Can be either 'XML' or 'FEATURECOLLECTION'. 671 * @throws WFSClientException 672 * if the feature collection could not be exported to GML. 673 * @throws RuntimeException 674 * if the resultFormat is not supported. 675 */ 676 677 private void writeGetFeatureResult( FeatureCollection fc, String resultFormat ) 678 throws WFSClientException { 679 680 if ( "XML".equals( resultFormat ) ) { 681 try { 682 GMLFeatureCollectionDocument gmlFcDoc = new GMLFeatureAdapter().export( fc ); 683 getRequest().setAttribute( "RESULT", gmlFcDoc ); 684 } catch ( Exception e ) { 685 LOG.logError( e.getMessage(), e ); 686 687 throw new WFSClientException( "could not export feature collection as GML", e ); 688 } 689 } else if ( "FEATURECOLLECTION".equals( resultFormat ) ) { 690 getRequest().setAttribute( "RESULT", fc ); 691 } else { 692 throw new RuntimeException( "'" + resultFormat + "' is not a supported format." ); 693 } 694 695 } 696 697 }