001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/enterprise/servlet/WMSHandler.java $ 002 /*---------------- FILE HEADER ------------------------------------------ 003 004 This file is part of deegree. 005 Copyright (C) 2001-2008 by: 006 EXSE, Department of Geography, University of Bonn 007 http://www.giub.uni-bonn.de/deegree/ 008 lat/lon GmbH 009 http://www.lat-lon.de 010 011 This library is free software; you can redistribute it and/or 012 modify it under the terms of the GNU Lesser General Public 013 License as published by the Free Software Foundation; either 014 version 2.1 of the License, or (at your option) any later version. 015 016 This library is distributed in the hope that it will be useful, 017 but WITHOUT ANY WARRANTY; without even the implied warranty of 018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 019 Lesser General Public License for more details. 020 021 You should have received a copy of the GNU Lesser General Public 022 License along with this library; if not, write to the Free Software 023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 024 025 Contact: 026 027 Andreas Poth 028 lat/lon GmbH 029 Aennchenstr. 19 030 53115 Bonn 031 Germany 032 E-Mail: poth@lat-lon.de 033 034 Prof. Dr. Klaus Greve 035 Department of Geography 036 University of Bonn 037 Meckenheimer Allee 166 038 53115 Bonn 039 Germany 040 E-Mail: greve@giub.uni-bonn.de 041 042 ---------------------------------------------------------------------------*/ 043 044 package org.deegree.enterprise.servlet; 045 046 import static javax.imageio.ImageIO.write; 047 048 import java.awt.Color; 049 import java.awt.Graphics; 050 import java.awt.image.BufferedImage; 051 import java.io.ByteArrayOutputStream; 052 import java.io.IOException; 053 import java.io.OutputStream; 054 import java.io.OutputStreamWriter; 055 import java.io.PrintWriter; 056 import java.io.StringReader; 057 import java.io.Writer; 058 import java.net.MalformedURLException; 059 import java.net.URISyntaxException; 060 import java.net.URL; 061 import java.util.LinkedList; 062 import java.util.List; 063 064 import javax.servlet.http.HttpServletResponse; 065 import javax.xml.transform.Source; 066 import javax.xml.transform.TransformerException; 067 import javax.xml.transform.stream.StreamResult; 068 import javax.xml.transform.stream.StreamSource; 069 070 import org.deegree.datatypes.QualifiedName; 071 import org.deegree.datatypes.values.TypedLiteral; 072 import org.deegree.enterprise.ServiceException; 073 import org.deegree.framework.log.ILogger; 074 import org.deegree.framework.log.LoggerFactory; 075 import org.deegree.framework.util.CharsetUtils; 076 import org.deegree.framework.util.ImageUtils; 077 import org.deegree.framework.util.MimeTypeMapper; 078 import org.deegree.framework.util.NetWorker; 079 import org.deegree.framework.util.StringTools; 080 import org.deegree.framework.xml.DOMPrinter; 081 import org.deegree.framework.xml.Marshallable; 082 import org.deegree.framework.xml.XMLFragment; 083 import org.deegree.framework.xml.XSLTDocument; 084 import org.deegree.ogcwebservices.ExceptionReport; 085 import org.deegree.ogcwebservices.OGCWebService; 086 import org.deegree.ogcwebservices.OGCWebServiceException; 087 import org.deegree.ogcwebservices.OGCWebServiceRequest; 088 import org.deegree.ogcwebservices.OGCWebServiceResponse; 089 import org.deegree.ogcwebservices.wms.InvalidFormatException; 090 import org.deegree.ogcwebservices.wms.WMService; 091 import org.deegree.ogcwebservices.wms.WMServiceFactory; 092 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilities; 093 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilities_1_3_0; 094 import org.deegree.ogcwebservices.wms.configuration.WMSConfigurationType; 095 import org.deegree.ogcwebservices.wms.configuration.WMSDeegreeParams; 096 import org.deegree.ogcwebservices.wms.operation.DescribeLayerResult; 097 import org.deegree.ogcwebservices.wms.operation.GetFeatureInfo; 098 import org.deegree.ogcwebservices.wms.operation.GetFeatureInfoResult; 099 import org.deegree.ogcwebservices.wms.operation.GetLegendGraphic; 100 import org.deegree.ogcwebservices.wms.operation.GetLegendGraphicResult; 101 import org.deegree.ogcwebservices.wms.operation.GetMap; 102 import org.deegree.ogcwebservices.wms.operation.GetMapResult; 103 import org.deegree.ogcwebservices.wms.operation.GetStylesResult; 104 import org.deegree.ogcwebservices.wms.operation.PutStylesResult; 105 import org.deegree.ogcwebservices.wms.operation.WMSGetCapabilitiesResult; 106 import org.deegree.owscommon.XMLFactory; 107 import org.deegree.owscommon_new.DomainType; 108 import org.deegree.owscommon_new.Operation; 109 import org.deegree.owscommon_new.OperationsMetadata; 110 import org.w3c.dom.Node; 111 import org.xml.sax.SAXException; 112 113 /** 114 * <code>WMSHandler</code> is the handler class for WMS requests and their results. 115 * 116 * @author <a href="mailto:schmitz@lat-lon.de">Andreas Schmitz</a> 117 * @author last edited by: $Author: aschmitz $ 118 * 119 * @version 2.0, $Revision: 12258 $, $Date: 2008-06-10 08:40:41 +0200 (Di, 10 Jun 2008) $ 120 * 121 * @since 2.0 122 */ 123 public class WMSHandler extends AbstractOWServiceHandler { 124 125 private static ILogger LOG = LoggerFactory.getLogger( WMSHandler.class ); 126 127 private Color bgColor = Color.WHITE; 128 129 private HttpServletResponse resp = null; 130 131 private OGCWebServiceRequest request = null; 132 133 private String exceptionFormat; 134 135 private String format = null; 136 137 private boolean transparent = false; 138 139 private int height = 400; 140 141 private int width = 600; 142 143 private WMSConfigurationType configuration = null; 144 145 /** 146 * 147 */ 148 WMSHandler() { 149 LOG.logDebug( "New WMSHandler instance created: " + this.getClass().getName() ); 150 } 151 152 private String checkExceptionFormat( String exceptionFormat, List<String> availableExceptionFormats ) { 153 boolean found = false; 154 for ( String f : availableExceptionFormats ) { 155 if ( f.equalsIgnoreCase( exceptionFormat ) ) { 156 found = true; 157 } 158 } 159 if ( !found ) { 160 return availableExceptionFormats.get( 0 ); 161 } 162 163 return exceptionFormat; 164 } 165 166 /** 167 * performs the passed OGCWebServiceRequest by accessing service from the pool and passing the 168 * request to it 169 */ 170 public void perform( OGCWebServiceRequest request, HttpServletResponse response ) 171 throws ServiceException { 172 this.request = request; 173 resp = response; 174 try { 175 176 OGCWebService service = WMServiceFactory.getService(); 177 configuration = (WMSConfigurationType) ( (WMService) service ).getCapabilities(); 178 179 List<String> availableExceptionFormats = new LinkedList<String>(); 180 181 // add 1.1.1 names if 1.3.0 capable 182 for ( String f : configuration.getExceptions() ) { 183 if ( f.equalsIgnoreCase( "XML" ) ) { 184 availableExceptionFormats.add( "application/vnd.ogc.se_xml" ); 185 } 186 if ( f.equalsIgnoreCase( "INIMAGE" ) ) { 187 availableExceptionFormats.add( "application/vnd.ogc.se_inimage" ); 188 } 189 if ( f.equalsIgnoreCase( "BLANK" ) ) { 190 availableExceptionFormats.add( "application/vnd.ogc.se_blank" ); 191 } 192 193 availableExceptionFormats.add( f ); 194 } 195 196 // EXCEPTION HANDLING NOTES: 197 // currently, the exceptions are handled differently for each request type, 198 // change the behaviour here 199 if ( request instanceof GetMap ) { 200 GetMap req = (GetMap) request; 201 exceptionFormat = req.getExceptions(); 202 exceptionFormat = checkExceptionFormat( exceptionFormat, availableExceptionFormats ); 203 format = req.getFormat(); 204 bgColor = req.getBGColor(); 205 transparent = req.getTransparency(); 206 height = req.getHeight(); 207 width = req.getWidth(); 208 } 209 210 if ( request instanceof GetLegendGraphic ) { 211 GetLegendGraphic req = (GetLegendGraphic) request; 212 exceptionFormat = req.getExceptions(); 213 exceptionFormat = checkExceptionFormat( exceptionFormat, availableExceptionFormats ); 214 format = req.getFormat(); 215 height = req.getHeight(); 216 width = req.getWidth(); 217 } 218 219 if ( request instanceof GetFeatureInfo ) { 220 GetFeatureInfo req = (GetFeatureInfo) request; 221 exceptionFormat = req.getExceptions(); 222 exceptionFormat = checkExceptionFormat( exceptionFormat, availableExceptionFormats ); 223 } 224 225 if ( exceptionFormat == null || exceptionFormat.equals( "" ) ) { 226 if ( "1.1.1".equals( request.getVersion() ) ) { 227 exceptionFormat = "application/vnd.ogc.se_xml"; 228 } else { 229 exceptionFormat = "XML"; 230 } 231 } 232 233 // fixup the exception formats, 1.3.0 has it different 234 // note that XML/....se_xml are not the same format! 235 if ( "INIMAGE".equalsIgnoreCase( exceptionFormat ) ) { 236 exceptionFormat = "application/vnd.ogc.se_inimage"; 237 } 238 if ( "BLANK".equalsIgnoreCase( exceptionFormat ) ) { 239 exceptionFormat = "application/vnd.ogc.se_blank"; 240 } 241 242 if ( service == null ) { 243 writeServiceExceptionReport( new OGCWebServiceException( "WMS", "could not access a WMService instance" ) ); 244 return; 245 } 246 247 // first, try the normal case 248 Object o = service.doService( request ); 249 handleResponse( o ); 250 251 } catch ( OGCWebServiceException e ) { 252 writeServiceExceptionReport( e ); 253 } 254 } 255 256 /** 257 * 258 * 259 * @param result 260 * @throws OGCWebServiceException 261 */ 262 private void handleResponse( Object result ) { 263 // this method may need restructuring 264 265 // handle exception case 266 if ( result instanceof OGCWebServiceException ) { 267 writeServiceExceptionReport( (OGCWebServiceException) result ); 268 return; 269 } 270 271 try { 272 OGCWebServiceResponse response = (OGCWebServiceResponse) result; 273 274 if ( response.getException() != null ) { 275 // handle the case that an exception occured during the 276 // request performance 277 writeServiceExceptionReport( response.getException() ); 278 } else { 279 if ( response instanceof OGCWebServiceException ) { 280 writeServiceExceptionReport( (OGCWebServiceException) response ); 281 } else if ( response instanceof Exception ) { 282 sendException( resp, (Exception) response ); 283 } else if ( response instanceof WMSGetCapabilitiesResult ) { 284 handleGetCapabilitiesResponse( (WMSGetCapabilitiesResult) response ); 285 } else if ( response instanceof GetMapResult ) { 286 handleGetMapResponse( (GetMapResult) response ); 287 } else if ( response instanceof GetFeatureInfoResult ) { 288 handleFeatureInfoResponse( (GetFeatureInfoResult) response ); 289 } else if ( response instanceof GetStylesResult ) { 290 handleGetStylesResponse( (GetStylesResult) response ); 291 } else if ( response instanceof PutStylesResult ) { 292 handlePutStylesResponse( (PutStylesResult) response ); 293 } else if ( response instanceof DescribeLayerResult ) { 294 handleDescribeLayerResponse( (DescribeLayerResult) response ); 295 } else if ( response instanceof GetLegendGraphicResult ) { 296 handleGetLegendGraphicResponse( (GetLegendGraphicResult) response ); 297 } 298 } 299 } catch ( InvalidFormatException ife ) { 300 LOG.logError( ife.getMessage(), ife ); 301 writeServiceExceptionReport( ife ); 302 } catch ( Exception e ) { 303 LOG.logError( e.getMessage(), e ); 304 writeServiceExceptionReport( new OGCWebServiceException( "WMS:write", e.getLocalizedMessage() ) ); 305 } 306 } 307 308 /** 309 * handles the response to a get capabilities request 310 * 311 * @param response 312 * @throws IOException 313 * @throws TransformerException 314 */ 315 private void handleGetCapabilitiesResponse( WMSGetCapabilitiesResult response ) 316 throws IOException, TransformerException { 317 WMSConfigurationType capa = response.getCapabilities(); 318 319 WMSDeegreeParams params = capa.getDeegreeParams(); 320 321 // version war follows 322 323 boolean version130 = "1.3.0".equals( capa.calculateVersion( request.getVersion() ) ); 324 325 // version not set -> use highest supported version 326 // use request's version otherwise 327 328 boolean support111 = false; 329 boolean support130 = false; 330 for ( String version : params.getSupportedVersions() ) { 331 if ( "1.1.1".equals( version ) ) 332 support111 = true; 333 if ( "1.3.0".equals( version ) ) 334 support130 = true; 335 } 336 337 if ( ( !support130 ) && ( !support111 ) ) { 338 support111 = true; 339 } 340 341 if ( version130 && support130 ) { 342 resp.setContentType( "text/xml" ); 343 } else { 344 resp.setContentType( "application/vnd.ogc.wms_xml" ); 345 } 346 347 XMLFragment doc = null; 348 349 if ( ( ( ( !version130 ) && support111 ) || ( !support130 ) ) && ( capa instanceof WMSCapabilities_1_3_0 ) ) { 350 doc = org.deegree.ogcwebservices.wms.XMLFactory.exportAs_1_1_1( (WMSCapabilities_1_3_0) capa ); 351 } else { 352 doc = org.deegree.ogcwebservices.wms.XMLFactory.export( (WMSCapabilities) capa ); 353 } 354 355 if ( ( version130 && support130 ) || ( !support111 ) ) { 356 doc.getRootElement().setAttribute( "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance" ); 357 doc.getRootElement().setAttribute( 358 "xsi:schemaLocation", 359 "http://www.opengis.net/wms " 360 + "http://schemas.opengis.net/wms/1.3.0/capabilities_1_3_0.xsd" 361 + " http://www.opengis.net/sld " 362 + "http://schemas.opengis.net/sld/1.1.0/sld_capabilities.xsd" ); 363 364 doc.prettyPrint( resp.getWriter() ); 365 } else { 366 String xml = new XMLFragment( doc.getRootElement() ).getAsString(); 367 xml = doc.getAsString(); 368 String dtd = NetWorker.url2String( configuration.getDeegreeParams().getDTDLocation() ); 369 StringBuffer sb = new StringBuffer(); 370 sb.append( "<!DOCTYPE WMT_MS_Capabilities SYSTEM " ); 371 sb.append( "'" + dtd + "' \n" ); 372 sb.append( "[\n<!ELEMENT VendorSpecificCapabilities EMPTY>\n]>" ); 373 374 int p = xml.indexOf( "?>" ); 375 if ( p > -1 ) { 376 xml = xml.substring( p + 2, xml.length() ); 377 } 378 379 xml = StringTools.concat( 50000, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>", "\n", sb.toString(), xml ); 380 381 xml = StringTools.replace( xml, "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"", "", false ); 382 383 try { 384 PrintWriter pw = resp.getWriter(); 385 pw.print( xml ); 386 pw.close(); 387 } catch ( Exception e ) { 388 LOG.logError( "-", e ); 389 } 390 391 } 392 } 393 394 /** 395 * handles the response to a get map request 396 * 397 * @param response 398 */ 399 private void handleGetMapResponse( GetMapResult response ) 400 throws InvalidFormatException { 401 // schmitz: added the toLowerCase to avoid errors 402 String mime = MimeTypeMapper.toMimeType( ( (GetMap) request ).getFormat().toLowerCase() ); 403 404 if ( !MimeTypeMapper.isImageType( mime ) ) { 405 throw new InvalidFormatException( mime + " is not a known image format" ); 406 } 407 408 writeImage( response.getMap(), mime ); 409 } 410 411 /** 412 * handles the response to a get featureinfo request 413 * 414 * @param response 415 */ 416 private void handleFeatureInfoResponse( GetFeatureInfoResult response ) 417 throws Exception { 418 GetFeatureInfo req = (GetFeatureInfo) request; 419 420 String s = req.getInfoFormat(); 421 422 // check if GML is actually the correct one 423 // THIS IS A HACK 424 if ( req.isInfoFormatDefault() ) { 425 OperationsMetadata om = configuration.getOperationMetadata(); 426 Operation op = om.getOperation( new QualifiedName( "GetFeatureInfo" ) ); 427 DomainType dt = (DomainType) op.getParameter( new QualifiedName( "Format" ) ); 428 List<TypedLiteral> vals = dt.getValues(); 429 s = vals.get( 0 ).getValue(); 430 } 431 432 String mime = MimeTypeMapper.toMimeType( s ); 433 resp.setContentType( mime + "; charset=" + CharsetUtils.getSystemCharset() ); 434 435 String fir = response.getFeatureInfo(); 436 437 String filter = FeatureInfoFilterDef.getString( s ); 438 439 if ( filter != null ) { 440 handleFilteredFeatureInfoResponse( fir, filter ); 441 } else { 442 OutputStreamWriter os = null; 443 try { 444 os = new OutputStreamWriter( resp.getOutputStream(), CharsetUtils.getSystemCharset() ); 445 os.write( fir ); 446 } catch ( Exception e ) { 447 LOG.logError( "could not write to outputstream", e ); 448 } finally { 449 os.close(); 450 } 451 } 452 } 453 454 /** 455 * @param fir 456 * @param filter 457 * @throws MalformedURLException 458 * @throws SAXException 459 * @throws IOException 460 * @throws URISyntaxException 461 * @throws TransformerException 462 */ 463 private void handleFilteredFeatureInfoResponse( String fir, String filter ) 464 throws Exception { 465 URL url = new URL( configuration.getBaseURL(), filter ); 466 LOG.logDebug( "used XSLT for transformation: ", url ); 467 LOG.logDebug( "GML document to transform", fir ); 468 if ( url != null ) { 469 Source xmlSource = new StreamSource( new StringReader( fir ) ); 470 Source xslSource; 471 try { 472 xslSource = new StreamSource( url.openStream() ); 473 } catch ( IOException ioe ) { 474 throw new InvalidFormatException( "Unknown feature info format (missing XSL script in configuration?)." ); 475 } 476 OutputStream os = null; 477 try { 478 os = resp.getOutputStream(); 479 StreamResult result = new StreamResult( os ); 480 XSLTDocument.transform( xmlSource, xslSource, result, null, null ); 481 } catch ( IOException e ) { 482 LOG.logError( "could not write to outputstream", e ); 483 } finally { 484 os.close(); 485 } 486 } 487 } 488 489 /** 490 * handles the response to a get styles request 491 * 492 * @param response 493 */ 494 private void handleGetStylesResponse( GetStylesResult response ) { 495 throw new RuntimeException( "method: handleGetStylesResponse not implemented yet" ); 496 } 497 498 /** 499 * handles the response to a put styles request 500 * 501 * @param response 502 */ 503 private void handlePutStylesResponse( PutStylesResult response ) { 504 throw new RuntimeException( "method: handlePutStylesResponse not implemented yet" ); 505 } 506 507 /** 508 * handles the response to a describe layer request 509 * 510 * @param response 511 * @throws IOException 512 * @throws TransformerException 513 */ 514 private void handleDescribeLayerResponse( DescribeLayerResult response ) 515 throws TransformerException, IOException { 516 resp.setCharacterEncoding( "UTF-8" ); 517 Writer out = resp.getWriter(); 518 response.getResult().prettyPrint( out ); 519 out.close(); 520 } 521 522 /** 523 * handles the response to a get legend graphic request 524 * 525 * @param response 526 */ 527 private void handleGetLegendGraphicResponse( GetLegendGraphicResult response ) 528 throws Exception { 529 String mime = MimeTypeMapper.toMimeType( ( (GetLegendGraphic) request ).getFormat() ); 530 531 if ( !MimeTypeMapper.isImageType( mime ) ) { 532 throw new InvalidFormatException( mime + " is not a known image format" ); 533 } 534 535 writeImage( response.getLegendGraphic(), mime ); 536 } 537 538 private void writeServiceExceptionReport( OGCWebServiceException exception, OutputStream out ) { 539 LOG.logInfo( "Sending exception in XML format." ); 540 if ( LOG.getLevel() == ILogger.LOG_DEBUG ) { 541 ExceptionReport report = new ExceptionReport( new OGCWebServiceException[] { exception } ); 542 String msg; 543 if ( exceptionFormat.equals( "XML" ) ) { 544 msg = XMLFactory.exportNS( report ).getAsPrettyString(); 545 } else { 546 msg = XMLFactory.export( report ).getAsPrettyString(); 547 } 548 549 LOG.logDebug( "Exception being sent: " + msg ); 550 } 551 552 ExceptionReport report = new ExceptionReport( new OGCWebServiceException[] { exception } ); 553 try { 554 XMLFragment doc; 555 556 if ( exceptionFormat.equals( "XML" ) ) { 557 resp.setContentType( "text/xml" ); 558 doc = XMLFactory.exportNS( report ); 559 } else { 560 resp.setContentType( "application/vnd.ogc.se_xml" ); 561 doc = XMLFactory.export( report ); 562 } 563 564 doc.write( out ); 565 out.close(); 566 } catch ( Exception ex ) { 567 LOG.logError( "ERROR: " + ex.getMessage(), ex ); 568 } 569 } 570 571 /** 572 * writes an service exception report into the <tt>OutputStream</tt> back to the client. the 573 * method considers the format an exception shall be returned to the client as defined in the 574 * request. 575 * 576 * @param exception 577 * the exception object containing the code and message 578 * @throws OGCWebServiceException 579 */ 580 private void writeServiceExceptionReport( OGCWebServiceException exception ) { 581 String code = "none"; 582 if ( exception.getCode() != null ) { 583 code = exception.getCode().value; 584 } 585 String message = exception.getMessage(); 586 587 LOG.logInfo( "sending exception in format " + exceptionFormat ); 588 if ( LOG.getLevel() == ILogger.LOG_DEBUG ) { 589 ExceptionReport report = new ExceptionReport( new OGCWebServiceException[] { exception } ); 590 String msg; 591 if ( exceptionFormat.equals( "XML" ) ) { 592 msg = XMLFactory.exportNS( report ).getAsPrettyString(); 593 } else { 594 msg = XMLFactory.export( report ).getAsPrettyString(); 595 } 596 597 LOG.logDebug( "Exception being sent: " + msg ); 598 } 599 600 if ( exceptionFormat.equals( "application/vnd.ogc.se_inimage" ) ) { 601 BufferedImage bi = new BufferedImage( width, height, BufferedImage.TYPE_INT_ARGB ); 602 Graphics g = bi.getGraphics(); 603 604 if ( !transparent ) { 605 g.setColor( bgColor ); 606 g.fillRect( 0, 0, bi.getWidth(), bi.getHeight() ); 607 } 608 609 g.setColor( Color.BLUE ); 610 g.drawString( code, 5, 20 ); 611 int pos1 = message.indexOf( ':' ); 612 g.drawString( message.substring( 0, pos1 + 1 ), 5, 50 ); 613 g.drawString( message.substring( pos1 + 1, message.length() ), 5, 80 ); 614 String mime = MimeTypeMapper.toMimeType( format ); 615 writeImage( bi, mime ); 616 } else if ( exceptionFormat.equals( "application/vnd.ogc.se_blank" ) ) { 617 BufferedImage bi = new BufferedImage( width, height, BufferedImage.TYPE_INT_ARGB ); 618 Graphics g = bi.getGraphics(); 619 620 if ( !transparent ) { 621 g.setColor( bgColor ); 622 g.fillRect( 0, 0, bi.getWidth(), bi.getHeight() ); 623 } 624 625 g.dispose(); 626 String mime = MimeTypeMapper.toMimeType( format ); 627 writeImage( bi, mime ); 628 } else { 629 LOG.logInfo( "Sending OGCWebServiceException to client." ); 630 ExceptionReport report = new ExceptionReport( new OGCWebServiceException[] { exception } ); 631 try { 632 XMLFragment doc; 633 634 if ( exceptionFormat.equals( "XML" ) ) { 635 resp.setContentType( "text/xml" ); 636 doc = XMLFactory.exportNS( report ); 637 } else { 638 resp.setContentType( "application/vnd.ogc.se_xml" ); 639 doc = XMLFactory.export( report ); 640 } 641 642 OutputStream os = resp.getOutputStream(); 643 doc.write( os ); 644 os.close(); 645 } catch ( Exception ex ) { 646 LOG.logError( "ERROR: " + ex.getMessage(), ex ); 647 } 648 } 649 } 650 651 /** 652 * writes the passed image to the response output stream. 653 * 654 * @param output 655 * @param mime 656 */ 657 private void writeImage( Object output, String mime ) { 658 OutputStream os = null; 659 try { 660 resp.setContentType( mime ); 661 if ( mime.equalsIgnoreCase( "image/gif" ) ) { 662 BufferedImage img = (BufferedImage) output; 663 ByteArrayOutputStream out = new ByteArrayOutputStream( img.getWidth() * img.getHeight() * 4 ); 664 try { 665 ImageUtils.encodeGif( out, img ); 666 } catch ( IOException e ) { 667 LOG.logWarning( "ACME failed to write GIF image, trying ImageIO." ); 668 LOG.logDebug( "Stack trace", e ); 669 // use imageio, it can transform the colors correctly starting from Java 1.6 670 if ( !write( img, "gif", out ) ) { 671 os = resp.getOutputStream(); 672 writeServiceExceptionReport( new OGCWebServiceException( e.getLocalizedMessage() ), os ); 673 os.close(); 674 return; 675 } 676 } 677 678 resp.setContentType( mime ); 679 os = resp.getOutputStream(); 680 681 out.close(); 682 byte[] bs = out.toByteArray(); 683 out = null; 684 685 os.write( bs ); 686 } else if ( mime.equalsIgnoreCase( "image/jpg" ) || mime.equalsIgnoreCase( "image/jpeg" ) ) { 687 os = resp.getOutputStream(); 688 ImageUtils.saveImage( (BufferedImage) output, os, "jpeg", 689 configuration.getDeegreeParams().getMapQuality() ); 690 } else if ( mime.equalsIgnoreCase( "image/png" ) ) { 691 os = resp.getOutputStream(); 692 ImageUtils.saveImage( (BufferedImage) output, os, "png", 1 ); 693 } else if ( mime.equalsIgnoreCase( "image/tif" ) || mime.equalsIgnoreCase( "image/tiff" ) ) { 694 os = resp.getOutputStream(); 695 ImageUtils.saveImage( (BufferedImage) output, os, "tif", 1 ); 696 } else if ( mime.equalsIgnoreCase( "image/bmp" ) ) { 697 os = resp.getOutputStream(); 698 ImageUtils.saveImage( (BufferedImage) output, os, "bmp", 1 ); 699 } else if ( mime.equalsIgnoreCase( "image/svg+xml" ) ) { 700 os = resp.getOutputStream(); 701 resp.setContentType( "text/xml; charset=" + CharsetUtils.getSystemCharset() ); 702 PrintWriter pw = new PrintWriter( os ); 703 DOMPrinter.printNode( pw, (Node) output ); 704 pw.close(); 705 } else { 706 resp.setContentType( "text/xml; charset=" + CharsetUtils.getSystemCharset() ); 707 os = resp.getOutputStream(); 708 OGCWebServiceException exce = new OGCWebServiceException( "WMS:writeImage", 709 "unsupported image format: " + mime ); 710 os.write( ( (Marshallable) exce ).exportAsXML().getBytes() ); 711 } 712 713 os.close(); 714 } catch ( Exception e ) { 715 LOG.logError( resp.isCommitted() ? "Response is already committed!" : "Response is not committed yet." ); 716 LOG.logError( "Error while writing image: ", e ); 717 writeServiceExceptionReport( new OGCWebServiceException( e.getLocalizedMessage() ), os ); 718 } 719 } 720 721 }