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