001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/enterprise/servlet/CSWHandler.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 package org.deegree.enterprise.servlet; 037 038 import java.io.IOException; 039 import java.io.OutputStream; 040 import java.io.PrintWriter; 041 import java.lang.reflect.Method; 042 043 import javax.servlet.http.HttpServletResponse; 044 import javax.xml.transform.TransformerException; 045 046 import org.deegree.enterprise.ServiceException; 047 import org.deegree.framework.log.ILogger; 048 import org.deegree.framework.log.LoggerFactory; 049 import org.deegree.framework.util.CharsetUtils; 050 import org.deegree.framework.xml.XMLFragment; 051 import org.deegree.framework.xml.XMLParsingException; 052 import org.deegree.framework.xml.XMLTools; 053 import org.deegree.ogcbase.CommonNamespaces; 054 import org.deegree.ogcbase.ExceptionCode; 055 import org.deegree.ogcwebservices.EchoRequest; 056 import org.deegree.ogcwebservices.InvalidParameterValueException; 057 import org.deegree.ogcwebservices.OGCWebServiceException; 058 import org.deegree.ogcwebservices.OGCWebServiceRequest; 059 import org.deegree.ogcwebservices.csw.CSWExceptionCode; 060 import org.deegree.ogcwebservices.csw.CSWFactory; 061 import org.deegree.ogcwebservices.csw.CSWPropertiesAccess; 062 import org.deegree.ogcwebservices.csw.CatalogueService; 063 import org.deegree.ogcwebservices.csw.capabilities.CatalogueCapabilities; 064 import org.deegree.ogcwebservices.csw.capabilities.CatalogueGetCapabilities; 065 import org.deegree.ogcwebservices.csw.discovery.DescribeRecordResult; 066 import org.deegree.ogcwebservices.csw.discovery.GetRecordByIdResult; 067 import org.deegree.ogcwebservices.csw.discovery.GetRecordsResult; 068 import org.deegree.ogcwebservices.csw.discovery.GetRepositoryItem; 069 import org.deegree.ogcwebservices.csw.discovery.GetRepositoryItemResponse; 070 import org.deegree.ogcwebservices.csw.manager.HarvestResult; 071 import org.deegree.ogcwebservices.csw.manager.TransactionResult; 072 import org.w3c.dom.Document; 073 import org.w3c.dom.Element; 074 075 /** 076 * Web servlet client for CSW. 077 * 078 * @author <a href="mailto:tfr@users.sourceforge.net">Torsten Friebe </A> 079 * @author last edited by: $Author: mschneider $ 080 * 081 * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $ 082 * 083 * @see <a href="http://www.dofactory.com/patterns/PatternChain.aspx">Chain of Responsibility Design Pattern </a> 084 */ 085 086 public class CSWHandler extends AbstractOWServiceHandler { 087 088 private static final ILogger LOG = LoggerFactory.getLogger( CSWHandler.class ); 089 090 /** 091 * @param request 092 * @param httpResponse 093 * @throws ServiceException 094 * @throws OGCWebServiceException 095 * @see "org.deegree.enterprise.servlet.ServiceDispatcher#perform(org.deegree.services.AbstractOGCWebServiceRequest,javax.servlet.http.HttpServletResponse)" 096 */ 097 public void perform( OGCWebServiceRequest request, HttpServletResponse httpResponse ) 098 throws ServiceException, OGCWebServiceException { 099 100 LOG.logDebug( "Performing request: " + request.toString() ); 101 102 try { 103 CatalogueService service = CSWFactory.getService(); 104 Object response = service.doService( request ); 105 if ( response instanceof OGCWebServiceException ) { 106 if ( request instanceof GetRepositoryItem ) { 107 sendOWSException( httpResponse, (OGCWebServiceException) response ); 108 } else { 109 sendExceptionReport( httpResponse, (OGCWebServiceException) response ); 110 } 111 } else if ( response instanceof Exception ) { 112 sendExceptionReport( httpResponse, (Exception) response ); 113 } else if ( response instanceof CatalogueCapabilities ) { 114 sendCapabilities( httpResponse, (CatalogueGetCapabilities) request, (CatalogueCapabilities) response ); 115 } else if ( response instanceof GetRecordsResult ) { 116 sendGetRecord( httpResponse, (GetRecordsResult) response ); 117 } else if ( response instanceof GetRecordByIdResult ) { 118 sendGetRecordById( httpResponse, (GetRecordByIdResult) response ); 119 } else if ( response instanceof DescribeRecordResult ) { 120 sendDescribeRecord( httpResponse, (DescribeRecordResult) response ); 121 } else if ( response instanceof TransactionResult ) { 122 sendTransactionResult( httpResponse, (TransactionResult) response ); 123 } else if ( response instanceof HarvestResult ) { 124 sendHarvestResult( httpResponse, (HarvestResult) response ); 125 } else if ( response instanceof EchoRequest ) { 126 sendHarvestResult( httpResponse ); 127 } else if ( response instanceof GetRepositoryItemResponse ) { 128 sendGetRepositoryItem( httpResponse, (GetRepositoryItemResponse) response ); 129 } else { 130 OGCWebServiceException e = new OGCWebServiceException( 131 this.getClass().getName(), 132 "Unknown response class: " 133 + ( response == null ? "null response object" 134 : response.getClass().getName() ) 135 + "." ); 136 sendExceptionReport( httpResponse, e ); 137 } 138 } catch ( IOException ex ) { 139 throw new ServiceException( "Error while sending response: " + ex.getMessage(), ex ); 140 } catch ( OGCWebServiceException ogc ) { 141 if ( request instanceof GetRepositoryItem ) { 142 sendOWSException( httpResponse, ogc ); 143 } else { 144 sendExceptionReport( httpResponse, ogc ); 145 } 146 } 147 148 } 149 150 /** 151 * @param httpResponse 152 * @param response 153 * @throws IOException 154 * @throws ServiceException 155 */ 156 private void sendGetRepositoryItem( HttpServletResponse httpResponse, GetRepositoryItemResponse response ) 157 throws IOException, ServiceException { 158 httpResponse.setContentType( "text/xml; charset=" + CharsetUtils.getSystemCharset() ); 159 PrintWriter pw = httpResponse.getWriter(); 160 try { 161 response.getRepositoryItem().prettyPrint( pw ); 162 pw.flush(); 163 } catch ( TransformerException e ) { 164 LOG.logError( e.getLocalizedMessage(), e ); 165 throw new ServiceException( e.getLocalizedMessage(), e ); 166 } 167 } 168 169 /** 170 * Sends the passed <tt>OGCWebServiceException</tt> to the calling client and flushes/closes the writer. 171 * 172 * @param responseWriter 173 * to write the message of the exception to 174 * @param e 175 * the exception to 'send' e.g. write to the stream. 176 * @throws ServiceException 177 * if a writer could not be created from the response. 178 */ 179 private void sendOWSException( HttpServletResponse httpResponse, OGCWebServiceException e ) 180 throws ServiceException { 181 182 if ( LOG.getLevel() == ILogger.LOG_DEBUG ) { 183 Thread.dumpStack(); 184 } 185 httpResponse.setContentType( "application/xml" ); 186 LOG.logDebug( "Sending OGCWebServiceException to client with message: " + e.getMessage() ); 187 Document doc = XMLTools.create(); 188 189 XMLFragment frag = new XMLFragment( doc.createElementNS( CommonNamespaces.OWSNS.toString(), 190 "ows:ExceptionReport" ) ); 191 Element message = null; 192 ExceptionCode code = e.getCode(); 193 if ( code == null ) { 194 code = CSWExceptionCode.WRS_INVALIDREQUEST; 195 } 196 if ( code == CSWExceptionCode.WRS_INVALIDREQUEST ) { 197 message = XMLTools.appendElement( frag.getRootElement(), CommonNamespaces.WRS_EBRIMNS, code.value ); 198 } else { 199 message = XMLTools.appendElement( frag.getRootElement(), CommonNamespaces.WRS_EBRIMNS, 200 CSWExceptionCode.WRS_NOTFOUND.value ); 201 } 202 XMLTools.setNodeValue( message, e.getMessage() ); 203 204 try { 205 PrintWriter writer = httpResponse.getWriter(); 206 writer.write( frag.getAsPrettyString() ); 207 writer.flush(); 208 } catch ( IOException e1 ) { 209 throw new ServiceException( e1 ); 210 } 211 212 // writer.close(); 213 214 } 215 216 /** 217 * Sends the passed <tt>HarvestResult</tt> to the http client. 218 * 219 * @param httpResponse 220 * http connection to the client 221 * @param result 222 * object to send 223 * @throws IOException 224 */ 225 private void sendHarvestResult( HttpServletResponse httpResponse, HarvestResult result ) 226 throws IOException { 227 XMLFragment doc = null; 228 try { 229 doc = org.deegree.ogcwebservices.csw.manager.XMLFactory.export( result ); 230 } catch ( XMLParsingException e ) { 231 throw new IOException( "could not export TransactionResult as XML: " + e.getMessage() ); 232 } 233 httpResponse.setContentType( "text/xml; charset=" + CharsetUtils.getSystemCharset() ); 234 OutputStream os = httpResponse.getOutputStream(); 235 doc.write( os ); 236 os.close(); 237 } 238 239 /** 240 * 241 * @param httpResponse 242 * @throws IOException 243 */ 244 private void sendHarvestResult( HttpServletResponse httpResponse ) 245 throws IOException { 246 247 httpResponse.setContentType( "text/xml; charset=" + CharsetUtils.getSystemCharset() ); 248 PrintWriter pw = httpResponse.getWriter(); 249 pw.write( "<HarvestResponse>Harvest request has been received " ); 250 pw.write( "and will be performed</HarvestResponse>" ); 251 pw.close(); 252 } 253 254 /** 255 * Sends the passed <tt>TransactionResult</tt> to the http client. 256 * 257 * @param httpResponse 258 * http connection to the client 259 * @param result 260 * object to send 261 */ 262 private void sendTransactionResult( HttpServletResponse httpResponse, TransactionResult result ) 263 throws IOException { 264 XMLFragment doc = null; 265 try { 266 doc = org.deegree.ogcwebservices.csw.manager.XMLFactory.export( result ); 267 } catch ( XMLParsingException e ) { 268 throw new IOException( "could not export TransactionResult as XML: " + e.getMessage() ); 269 } 270 httpResponse.setContentType( "text/xml; charset=" + CharsetUtils.getSystemCharset() ); 271 OutputStream os = httpResponse.getOutputStream(); 272 doc.write( os ); 273 os.close(); 274 } 275 276 /** 277 * Sends the passed <tt>CatalogCapabilities</tt> to the http client. 278 * 279 * @param response 280 * http connection to the client 281 * @param capabilities 282 * object to send 283 */ 284 private void sendCapabilities( HttpServletResponse response, CatalogueGetCapabilities getCapabilities, 285 CatalogueCapabilities capabilities ) 286 throws IOException { 287 288 boolean xmlOk = false; 289 String[] formats = getCapabilities.getAcceptFormats(); 290 if ( formats == null || formats.length == 0 ) { 291 xmlOk = true; 292 } else { 293 for ( int i = 0; i < formats.length; i++ ) { 294 if ( formats[i].equals( "text/xml" ) ) { 295 xmlOk = true; 296 break; 297 } 298 } 299 } 300 if ( !xmlOk ) { 301 ExceptionCode code = ExceptionCode.INVALIDPARAMETERVALUE; 302 InvalidParameterValueException e = new InvalidParameterValueException( this.getClass().getName(), 303 "OutputFormat must be 'text/xml'.", 304 code ); 305 sendExceptionReport( response, e ); 306 } else { 307 String version = getCapabilities.getVersion(); 308 String className = CSWPropertiesAccess.getString( "XMLFactory" + version ); 309 XMLFragment doc = null; 310 try { 311 Class<?> clzz = Class.forName( className ); 312 Class<?>[] parameterTypes = new Class<?>[] { CatalogueCapabilities.class, String[].class }; 313 Object[] parameters = new Object[] { capabilities, getCapabilities.getSections() }; 314 Method method = clzz.getMethod( "export", parameterTypes ); 315 doc = (XMLFragment) method.invoke( null, parameters ); 316 } catch ( Exception e ) { 317 e.printStackTrace(); 318 } 319 320 response.setContentType( "text/xml; charset=" + CharsetUtils.getSystemCharset() ); 321 OutputStream os = response.getOutputStream(); 322 doc.write( os ); 323 os.close(); 324 } 325 } 326 327 /** 328 * 329 * @param response 330 * @param getRecordResponse 331 * @throws IOException 332 */ 333 private void sendGetRecord( HttpServletResponse response, GetRecordsResult getRecordResponse ) 334 throws IOException { 335 XMLFragment doc = org.deegree.ogcwebservices.csw.discovery.XMLFactory.export( getRecordResponse ); 336 if ( LOG.isDebug() ) { 337 LOG.logDebug( "GetRecord response", doc.getAsPrettyString() ); 338 } 339 response.setContentType( "text/xml; charset=" + CharsetUtils.getSystemCharset() ); 340 OutputStream os = response.getOutputStream(); 341 doc.write( os ); 342 os.close(); 343 } 344 345 /** 346 * 347 * @param response 348 * @param getRecordByIdResponse 349 * @throws IOException 350 */ 351 private void sendGetRecordById( HttpServletResponse response, GetRecordByIdResult getRecordByIdResponse ) 352 throws IOException { 353 XMLFragment doc = org.deegree.ogcwebservices.csw.discovery.XMLFactory.export( getRecordByIdResponse ); 354 if ( LOG.isDebug() ) { 355 LOG.logDebug( "GetRecordById response", doc.getAsPrettyString() ); 356 } 357 response.setContentType( "text/xml" ); 358 OutputStream os = response.getOutputStream(); 359 doc.write( os ); 360 os.close(); 361 } 362 363 /** 364 * 365 * @param response 366 * @param describeRecordResponse 367 * @throws IOException 368 */ 369 private void sendDescribeRecord( HttpServletResponse response, DescribeRecordResult describeRecordResponse ) 370 throws IOException { 371 XMLFragment doc = org.deegree.ogcwebservices.csw.discovery.XMLFactory.export( describeRecordResponse ); 372 if ( LOG.isDebug() ) { 373 LOG.logDebug( "DescribeRecord response", doc.getAsPrettyString() ); 374 } 375 response.setContentType( "text/xml; charset=" + CharsetUtils.getSystemCharset() ); 376 OutputStream os = response.getOutputStream(); 377 doc.write( os ); 378 os.close(); 379 } 380 }