001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/enterprise/servlet/WCSHandler.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 java.io.IOException;
047    import java.io.OutputStream;
048    import java.io.StringReader;
049    import java.net.URL;
050    import java.util.ArrayList;
051    import java.util.List;
052    
053    import javax.servlet.http.HttpServletResponse;
054    
055    import org.deegree.datatypes.parameter.GeneralParameterValueIm;
056    import org.deegree.datatypes.parameter.OperationParameterIm;
057    import org.deegree.enterprise.ServiceException;
058    import org.deegree.framework.log.ILogger;
059    import org.deegree.framework.log.LoggerFactory;
060    import org.deegree.framework.util.CharsetUtils;
061    import org.deegree.framework.util.StringTools;
062    import org.deegree.framework.xml.XMLFragment;
063    import org.deegree.framework.xml.XSLTDocument;
064    import org.deegree.i18n.Messages;
065    import org.deegree.model.coverage.grid.Format;
066    import org.deegree.model.coverage.grid.GridCoverage;
067    import org.deegree.model.coverage.grid.GridCoverageExchange;
068    import org.deegree.model.coverage.grid.GridCoverageWriter;
069    import org.deegree.model.spatialschema.Envelope;
070    import org.deegree.ogcwebservices.ExceptionReport;
071    import org.deegree.ogcwebservices.OGCWebServiceException;
072    import org.deegree.ogcwebservices.OGCWebServiceRequest;
073    import org.deegree.ogcwebservices.wcs.CoverageOfferingBrief;
074    import org.deegree.ogcwebservices.wcs.WCService;
075    import org.deegree.ogcwebservices.wcs.WCServiceFactory;
076    import org.deegree.ogcwebservices.wcs.describecoverage.CoverageDescription;
077    import org.deegree.ogcwebservices.wcs.describecoverage.CoverageOffering;
078    import org.deegree.ogcwebservices.wcs.describecoverage.InvalidCoverageDescriptionExcpetion;
079    import org.deegree.ogcwebservices.wcs.getcapabilities.ContentMetadata;
080    import org.deegree.ogcwebservices.wcs.getcapabilities.WCSCapabilities;
081    import org.deegree.ogcwebservices.wcs.getcapabilities.WCSGetCapabilities;
082    import org.deegree.ogcwebservices.wcs.getcoverage.GetCoverage;
083    import org.deegree.ogcwebservices.wcs.getcoverage.ResultCoverage;
084    import org.deegree.ogcwebservices.wcs.getcoverage.SpatialSubset;
085    import org.deegree.owscommon.XMLFactory;
086    import org.xml.sax.SAXException;
087    
088    /**
089     * Dispatcher for WCService.
090     * 
091     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a>
092     * @author last edited by: $Author: apoth $
093     * 
094     * @version 1.0. $Revision: 9338 $, $Date: 2007-12-27 13:31:31 +0100 (Do, 27 Dez 2007) $
095     * 
096     * @since 2.0
097     */
098    class WCSHandler extends AbstractOWServiceHandler {
099    
100        private static ILogger LOG = LoggerFactory.getLogger( WCSHandler.class );
101    
102        /**
103         * 
104         */
105        WCSHandler() {
106            LOG.logDebug( "New WCSHandler instance created: " + this.getClass().getName() );
107        }
108    
109        /**
110         * 
111         */
112        public void perform( OGCWebServiceRequest request, HttpServletResponse response )
113                                throws ServiceException, OGCWebServiceException {
114    
115            try {
116                Object serviceRes = this.getService().doService( request );
117    
118                if ( serviceRes instanceof OGCWebServiceException ) {
119                    sendException( response, (OGCWebServiceException) serviceRes );
120                } else if ( response instanceof Exception ) {
121                    sendException( response, (Exception) serviceRes );
122                } else if ( serviceRes instanceof ResultCoverage ) {
123                    SpatialSubset spsu = ( (GetCoverage) request ).getDomainSubset().getSpatialSubset();
124                    Envelope size = (Envelope) spsu.getGrid();
125                    try {
126                        sendCoverage( response, (ResultCoverage) serviceRes, size );
127                    } catch ( Exception e ) {
128                        sendException( response, e );
129                    }
130                } else if ( serviceRes instanceof WCSCapabilities ) {
131                    sendCapabilities( response, (WCSGetCapabilities) request, (WCSCapabilities) serviceRes );
132                } else if ( serviceRes instanceof CoverageDescription ) {
133                    sendCoverageDescription( response, (CoverageDescription) serviceRes );
134                } else {
135                    String s = Messages.getMessage( "WCS_UNKNOWN_RESPONSE_CLASS", serviceRes.getClass().getName() );
136                    throw new OGCWebServiceException( this.getClass().getName(), s );
137                }
138            } catch ( Exception e ) {
139                sendException( response, e );
140            }
141        }
142    
143        /**
144         * sends the passed <tt>WCSCapabilities</tt> to the calling client
145         * 
146         * @param response
147         *            <tt>HttpServletResponse</tt> for opening stream to the client
148         * @param serviceRes
149         *            object to send
150         */
151        private void sendCapabilities( HttpServletResponse response, WCSGetCapabilities owsr, WCSCapabilities serviceRes ) {
152            StringBuffer sb = new StringBuffer( 1000 );
153            sb.append( "<?xml version=\"1.0\" encoding='" + CharsetUtils.getSystemCharset() + "'?>" );
154            sb.append( "<xsl:stylesheet version=\"1.0\" " );
155            sb.append( "xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" " );
156            sb.append( "xmlns:wcs=\"http://www.opengis.net/wcs\" " );
157            sb.append( "xmlns:deegree=\"http://www.deegree.org/wcs\">" );
158            sb.append( "<xsl:template match=\"wcs:WCS_Capabilities\">" + "<xsl:copy-of select=\"XXX\"/>" );
159            sb.append( "</xsl:template>" + "</xsl:stylesheet>" );
160            String xslt = sb.toString();
161            try {
162                XMLFragment doc = org.deegree.ogcwebservices.wcs.XMLFactory.export( serviceRes );
163                String[] sections = owsr.getSections();
164    
165                if ( sections != null && sections.length > 0 ) {
166                    // filter out the requested section
167                    if ( sections[0].equals( "/WCS_Capabilities/Service" ) ) {
168                        xslt = StringTools.replace( xslt, "XXX", "./wcs:Service", false );
169                    } else if ( sections[0].equals( "/WCS_Capabilities/Capability" ) ) {
170                        xslt = StringTools.replace( xslt, "XXX", "./wcs:Capability", false );
171                    } else if ( sections[0].equals( "/WCS_Capabilities/ContentMetadata" ) ) {
172                        xslt = StringTools.replace( xslt, "XXX", "./wcs:ContentMetadata", false );
173                    } else {
174                        xslt = StringTools.replace( xslt, "XXX", ".", false );
175                    }
176                    XSLTDocument xslSheet = new XSLTDocument();
177                    xslSheet.load( new StringReader( xslt ), XMLFragment.DEFAULT_URL );
178                    doc = xslSheet.transform( doc );
179                }
180    
181                response.setContentType( "text/xml; charset=" + CharsetUtils.getSystemCharset() );
182                OutputStream os = response.getOutputStream();
183                doc.write( os );
184                os.close();
185            } catch ( Exception e ) {
186                LOG.logError( "ERROR: " + StringTools.stackTraceToString( e ), e );
187            }
188        }
189    
190        @Override
191        public void sendException( HttpServletResponse response, Exception exc ) {
192            OGCWebServiceException ogc;
193    
194            if ( exc instanceof OGCWebServiceException ) {
195                ogc = (OGCWebServiceException) exc;
196            } else {
197                ogc = new OGCWebServiceException( exc.getMessage() );
198            }
199    
200            ExceptionReport report = new ExceptionReport( new OGCWebServiceException[] { ogc } );
201    
202            try {
203                response.setContentType( "application/vnd.ogc.se_xml" );
204                XMLFragment reportDocument = XMLFactory.exportNS( report );
205                OutputStream os = response.getOutputStream();
206                reportDocument.write( os );
207                os.close();
208            } catch ( Exception e ) {
209                LOG.logError( "Error sending exception report: ", e );
210            }
211    
212        }
213    
214        /**
215         * sends the passed <tt>CoverageDescription</tt> to the calling client
216         * 
217         * @param response
218         *            <tt>HttpServletResponse</tt> for opening stream to the client
219         * @param serviceRes
220         *            object to send
221         */
222        private void sendCoverageDescription( HttpServletResponse response, CoverageDescription serviceRes ) {
223            try {
224                XMLFragment doc = org.deegree.ogcwebservices.wcs.XMLFactory.export( serviceRes );
225                response.setContentType( "text/xml; charset=" + CharsetUtils.getSystemCharset() );
226                OutputStream os = response.getOutputStream();
227                doc.write( os );
228                os.close();
229            } catch ( Exception e ) {
230                LOG.logError( "ERROR: " + StringTools.stackTraceToString( e ), e );
231            }
232        }
233    
234        /**
235         * writes the <tt>GridCoverage</tt> that is encapsulated within the <tt>ResultCoverage</tt>
236         * into the <tt>OutputStream</tt> taken from the passed <tt>HttpServletResponse</tt>
237         * 
238         * @param response
239         *            destination for writing the result coverage
240         * @param serviceRes
241         *            response to a GetCoverage request
242         * @param size
243         *            desired size of the GridCoverage
244         * @throws IOException
245         * @throws ServiceException 
246         * @throws SAXException 
247         * @throws InvalidCoverageDescriptionExcpetion 
248         */
249        private void sendCoverage( HttpServletResponse response, ResultCoverage serviceRes, Envelope size )
250                                throws IOException, InvalidCoverageDescriptionExcpetion, SAXException, ServiceException {
251            OutputStream os = response.getOutputStream();
252            Format format = new Format( serviceRes.getDesiredOutputFormat() );        
253            String frmt = format.getName();
254            if ( frmt.equalsIgnoreCase( "png" ) ) {
255                frmt = "image/png";
256            } else if ( frmt.equalsIgnoreCase( "bmp" ) ) {
257                frmt = "image/bmp";
258            } else if ( frmt.equalsIgnoreCase( "tif" ) || frmt.equalsIgnoreCase( "tiff" )
259                        || frmt.equalsIgnoreCase( "geotiff" ) ) {
260                frmt = "image/tiff";
261            } else if ( frmt.equalsIgnoreCase( "gif" ) ) {
262                frmt = "image/gif";
263            } else if ( frmt.equalsIgnoreCase( "jpg" ) || frmt.equalsIgnoreCase( "jpeg" ) ) {
264                frmt = "image/jpeg";
265            } else if ( frmt.equalsIgnoreCase( "GML2" ) || frmt.equalsIgnoreCase( "GML3" ) || frmt.equalsIgnoreCase( "GML" ) ) {
266                frmt = "application/vnd.ogc.gml";
267            } else if ( frmt.equalsIgnoreCase( "XYZ" ) ) {
268                frmt = "plain/text";
269            } else {
270                frmt = "application/octet-stream";
271            }
272            response.setContentType( frmt );
273    
274            GetCoverage req = serviceRes.getRequest();
275            List<GeneralParameterValueIm> list = new ArrayList<GeneralParameterValueIm>( 20 );
276            OperationParameterIm op = new OperationParameterIm( "addr", null, OGCServletController.address );
277            list.add( new GeneralParameterValueIm( op ) );
278            op = new OperationParameterIm( "width", null, new Integer( (int) size.getWidth() + 1 ) );
279            list.add( new GeneralParameterValueIm( op ) );
280            op = new OperationParameterIm( "height", null, new Integer( (int) size.getHeight() + 1 ) );
281            list.add( new GeneralParameterValueIm( op ) );
282            op = new OperationParameterIm( "service", null, "WCS" );
283            list.add( new GeneralParameterValueIm( op ) );
284            op = new OperationParameterIm( "version", null, req.getVersion() );
285            list.add( new GeneralParameterValueIm( op ) );
286            op = new OperationParameterIm( "coverage", null, req.getSourceCoverage() );
287            list.add( new GeneralParameterValueIm( op ) );
288            op = new OperationParameterIm( "crs", null, req.getDomainSubset().getRequestSRS().getCode() );
289            list.add( new GeneralParameterValueIm( op ) );
290            op = new OperationParameterIm( "response_crs", null, req.getOutput().getCrs().getCode() );
291            list.add( new GeneralParameterValueIm( op ) );
292            Envelope env = req.getDomainSubset().getSpatialSubset().getEnvelope();
293            String s = StringTools.concat( 100, new Double( env.getMin().getX() ), ",", new Double( env.getMin().getY() ),
294                                           ",", new Double( env.getMax().getX() ), ",", new Double( env.getMax().getY() ) );
295            op = new OperationParameterIm( "BBOX", null, s );
296            list.add( new GeneralParameterValueIm( op ) );
297            op = new OperationParameterIm( "FORMAT", null, "GeoTiff" );
298            list.add( new GeneralParameterValueIm( op ) );
299            op = new OperationParameterIm( "Request", null, "GetCoverage" );
300            list.add( new GeneralParameterValueIm( op ) );
301    
302            GeneralParameterValueIm[] gpvs = new GeneralParameterValueIm[list.size()];
303            if ( serviceRes.getCoverage() != null ) {
304                CoverageOffering co = getCoverageOffering( req );
305                GridCoverageExchange gce = new GridCoverageExchange( co );            
306                GridCoverageWriter writer = gce.getWriter( os, format );
307                writer.write( (GridCoverage) serviceRes.getCoverage(), list.toArray( gpvs ) );
308            } else {
309                s = Messages.getMessage( "WCSHandler.NULLCOVERAGE" );
310                OGCWebServiceException owse = new OGCWebServiceException( getClass().getName(), s );
311                sendException( response, owse );
312            }
313    
314            os.close();
315    
316        }
317    
318        /**
319         * 
320         * @param request
321         * @return
322         * @throws IOException
323         * @throws SAXException
324         * @throws InvalidCoverageDescriptionExcpetion
325         * @throws ServiceException
326         */
327        private CoverageOffering getCoverageOffering( GetCoverage request )
328                                throws IOException, SAXException, InvalidCoverageDescriptionExcpetion, ServiceException {
329    
330            ContentMetadata cm = ((WCSCapabilities)getService().getCapabilities()).getContentMetadata();
331            CoverageOfferingBrief cob = cm.getCoverageOfferingBrief( request.getSourceCoverage() );
332            URL url = cob.getConfiguration();
333            CoverageDescription cd = CoverageDescription.createCoverageDescription( url );
334            CoverageOffering co = cd.getCoverageOffering( request.getSourceCoverage() );
335    
336            return co;
337        }
338    
339        /**
340         * @return a service instance
341         * @throws ServiceException
342         */
343        public WCService getService()
344                                throws ServiceException {
345    
346            WCService service = null;
347            try {
348                service = WCServiceFactory.getService();
349            } catch ( Exception e ) {
350                LOG.logError( "ERROR: " + StringTools.stackTraceToString( e ), e );
351                throw new ServiceException( e );
352            }
353    
354            return service;
355        }
356    
357    }