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