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