001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/portal/wac/WACServlet.java $
002    /*----------------    FILE HEADER  ------------------------------------------
003    
004     This file is part of deegree.
005     Copyright (C) 2001-2008 by:
006     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     Klaus Greve
035     Department of Geography
036     University of Bonn
037     Meckenheimer Allee 166
038     53115 Bonn
039     Germany
040     E-Mail: klaus.greve@uni-bonn.de
041    
042     ---------------------------------------------------------------------------*/
043    package org.deegree.portal.wac;
044    
045    import java.io.IOException;
046    import java.io.InputStream;
047    import java.io.OutputStream;
048    import java.io.PrintWriter;
049    import java.net.MalformedURLException;
050    import java.net.URL;
051    import java.util.Collections;
052    import java.util.HashMap;
053    import java.util.List;
054    import java.util.Map;
055    
056    import javax.servlet.ServletException;
057    import javax.servlet.http.HttpServlet;
058    import javax.servlet.http.HttpServletRequest;
059    import javax.servlet.http.HttpServletResponse;
060    
061    import org.deegree.framework.log.ILogger;
062    import org.deegree.framework.log.LoggerFactory;
063    import org.deegree.framework.util.KVP2Map;
064    import org.deegree.framework.util.StringTools;
065    import org.deegree.framework.xml.XMLFragment;
066    import org.deegree.model.metadata.iso19115.Linkage;
067    import org.deegree.model.metadata.iso19115.OnlineResource;
068    import org.deegree.ogcwebservices.InvalidParameterValueException;
069    import org.deegree.ogcwebservices.wms.XMLFactory;
070    import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilities;
071    import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilitiesDocument;
072    import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilitiesDocumentFactory;
073    import org.deegree.owscommon_new.DCP;
074    import org.deegree.owscommon_new.HTTP;
075    import org.deegree.owscommon_new.Operation;
076    import org.deegree.owscommon_new.OperationsMetadata;
077    import org.w3c.dom.Document;
078    
079    /**
080     * 
081     * 
082     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a>
083     * @author last edited by: $Author: apoth $
084     * 
085     * @version $Revision: 9346 $, $Date: 2007-12-27 17:39:07 +0100 (Do, 27 Dez 2007) $
086     */
087    public class WACServlet extends HttpServlet {
088    
089        private Map<String, String> users = new HashMap<String, String>();
090    
091        private Map<String, String> passwords = new HashMap<String, String>();
092    
093        private Map<String, String> sessionIDs = Collections.synchronizedMap( new HashMap<String, String>() );
094    
095        private String host = null;
096    
097        private int port = 443;
098    
099        private String path = null;
100    
101        private String certificate = null;
102    
103        private String wacURL = null;
104    
105        private static final ILogger LOG = LoggerFactory.getLogger( WACServlet.class );
106    
107        @Override
108        public void init()
109                                throws ServletException {
110            super.init();
111            String user = getInitParameter( "USER" );
112            if ( user == null ) {
113                throw new ServletException( "user must be set!" );
114            }
115            users.put( "*", user );
116            String password = getInitParameter( "PASSWORD" );
117            if ( password == null ) {
118                throw new ServletException( "password must be set!" );
119            }
120            passwords.put( "*", password );
121            host = getInitParameter( "HOST" );
122            if ( host == null ) {
123                throw new ServletException( "WSS host must be set!" );
124            }
125            try {
126                port = Integer.parseInt( getInitParameter( "PORT" ) );
127            } catch ( NumberFormatException e ) {
128                getServletContext().log( "-> using default SSL port 443" );
129            }
130            path = getInitParameter( "PATH" );
131            if ( path == null ) {
132                throw new ServletException( "path to web application on host must be set!" );
133            }
134            certificate = getInitParameter( "CERTIFICATE" );
135            if ( certificate == null ) {
136                getServletContext().log( "no certificate defined" );
137            }
138    
139        }
140    
141        /**
142         * @param request
143         * @param response
144         * @throws IOException
145         */
146        @Override
147        protected void doGet( HttpServletRequest request, HttpServletResponse response )
148                                throws IOException {
149    
150            wacURL = "http://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath()
151                     + request.getServletPath();
152    
153            String user = users.get( "*" );
154            WAClient wac = new WAClient( host, path, port, certificate );
155            if ( sessionIDs.get( user ) == null ) {
156                if ( !accessSessionID( wac, response ) ) {
157                    return;
158                }
159            }
160            // get sessionID assigned to the user
161            String sessionID = sessionIDs.get( user );
162            InputStream is = null;
163            try {
164                StringBuffer sb = new StringBuffer( 2000 );
165                sb.append( request.getQueryString() ).append( "&sessionID=" ).append( sessionID );
166                is = wac.performDoService( request.getQueryString(), sessionID );
167            } catch ( Exception e ) {
168                e.printStackTrace();
169                sendException( response, "GetSession", "could not perform DoService", StringTools.stackTraceToString( e ) );
170            }
171    
172            OutputStream os = null;
173            try {
174                os = response.getOutputStream();
175                postProcess( request.getQueryString(), is, os );
176            } catch ( Exception e ) {
177                sendException( response, "GetSession", "could not post process capabilities",
178                               StringTools.stackTraceToString( e ) );
179            } finally {
180                os.flush();
181                os.close();
182                is.close();
183            }
184        }
185    
186        /**
187         * access a sessionID from a WSS and stores it into an internal Map to use for DoService calls
188         * against a WSS
189         * 
190         * @param wac
191         * @param response
192         * @return
193         */
194        private boolean accessSessionID( WAClient wac, HttpServletResponse response ) {
195            String user = users.get( "*" );
196            String password = passwords.get( "*" );
197            try {
198                String sessionID = wac.performGetSession( user, password );
199                sessionIDs.put( user, sessionID );
200            } catch ( WACException e ) {
201                e.printStackTrace();
202                sendException( response, "GetSession", "could not perform GetSession", StringTools.stackTraceToString( e ) );
203                return false;
204            } catch ( Exception e ) {
205                e.printStackTrace();
206                sendException( response, "GetSession", "could not evaluate GetSession result",
207                               StringTools.stackTraceToString( e ) );
208                return false;
209            }
210            return true;
211        }
212    
213        private void sendException( HttpServletResponse response, String req, String message, String stacktrace ) {
214            this.getServletContext().log( message );
215            this.getServletContext().log( stacktrace );
216            response.setContentType( "text/xml" );
217            if ( req == null )
218                req = "";
219            if ( message == null )
220                message = "";
221            try {
222                PrintWriter pw = response.getWriter();
223                pw.write( "<OGCWebServiceException>" );
224                pw.write( "<Message>" );
225                pw.write( req );
226                pw.write( ": failed! " );
227                pw.write( message );
228                pw.write( "</Message>" );
229                pw.write( "<Locator>" );
230                pw.write( stacktrace );
231                pw.write( "</Locator>" );
232                pw.write( "</OGCWebServiceException>" );
233                pw.close();
234            } catch ( Exception ee ) {
235                ee.printStackTrace();
236            }
237        }
238    
239        /**
240         * forces a post processing of the wss response if a GetCapabilities request has been performed
241         * by replacing contained the online resources
242         * 
243         * @param request
244         * @param is
245         * @param os
246         *            stream to write the result too
247         * @return
248         * @throws Exception
249         */
250        private void postProcess( String request, InputStream is, OutputStream os )
251                                throws Exception {
252            Map map = KVP2Map.toMap( request );
253            if ( map.get( "REQUEST" ).equals( "GetCapabilities" ) ) {
254                XMLFragment xml = new XMLFragment();
255                xml.load( is, XMLFragment.DEFAULT_URL );
256                is.close();
257                Document doc = xml.getRootElement().getOwnerDocument();
258                if ( map.get( "SERVICE" ).equals( "WMS" ) ) {
259                    adjustWMSCapabilities( doc, os );
260                } else if ( map.get( "SERVICE" ).equals( "WFS" ) ) {
261                    // TODO
262                } else if ( map.get( "SERVICE" ).equals( "WCS" ) ) {
263                    // TODO
264                } else if ( map.get( "SERVICE" ).equals( "CSW" ) ) {
265                    // TODO
266                } else if ( map.get( "SERVICE" ).equals( "SCS" ) ) {
267                    // TODO
268                }
269                if ( map.get( "SERVICE" ).equals( "WFS-G" ) ) {
270                    // TODO
271                }
272                if ( map.get( "SERVICE" ).equals( "WTS" ) ) {
273                    // TODO
274                }
275            } else {
276                byte[] b = new byte[1024];
277                int c = 0;
278                while ( ( c = is.read( b ) ) > 0 ) {
279                    os.write( b, 0, c );
280                }
281                os.close();
282                is.close();
283            }
284        }
285    
286        /**
287         * adjusts the passed WMS capabilities document by replacing the contained online resources with
288         * the address of the WAC
289         * 
290         * @param xml
291         * @param user
292         * @throws InvalidParameterValueException
293         */
294        private void adjustWMSCapabilities( Document doc, OutputStream os )
295                                throws InvalidParameterValueException, IOException {
296    
297            WMSCapabilities capa = null;
298            try {
299                WMSCapabilitiesDocument cdoc = 
300                    WMSCapabilitiesDocumentFactory.getWMSCapabilitiesDocument( doc.getDocumentElement() );
301                capa = (WMSCapabilities) cdoc.parseCapabilities();
302            } catch ( Exception e ) {
303                e.printStackTrace();
304                throw new InvalidParameterValueException( "no valid wms capabilities\n"
305                                                          + StringTools.stackTraceToString( e ) );
306            }
307    
308            OperationsMetadata om = capa.getOperationMetadata();
309    
310            List<Operation> ops = om.getOperations();
311            for ( Operation operation : ops ) {
312                setNewOnlineResource( operation );
313            }
314    
315            WMSCapabilitiesDocument cdoc = XMLFactory.export( capa );
316            cdoc.write( os );
317        }
318    
319        /**
320         * sets a new online resource for the passed <tt>Operation</tt>
321         * 
322         * @param op
323         */
324        private void setNewOnlineResource( Operation op ) {
325            List<DCP> dcps = op.getDCP();
326            if ( dcps != null ) {
327                for ( DCP dcp : dcps ) {
328                    HTTP http = (HTTP) dcp;
329                    try {
330                        URL url = new URL( wacURL );
331                        OnlineResource link = new OnlineResource( new Linkage( url ) );
332                        List<OnlineResource> resources = http.getLinks();
333                        int size = resources.size();
334                        resources.clear();
335                        for ( int i = 0; i < size; ++i )
336                            resources.add( link );
337                    } catch ( MalformedURLException e1 ) {
338                        LOG.logError( e1.getLocalizedMessage(), e1 );
339                    }
340                }
341            }
342        }
343    
344        /**
345         * @param request
346         * @param response
347         * @throws ServletException
348         * @throws IOException
349         */
350        @Override
351        protected void doPost( HttpServletRequest request, HttpServletResponse response )
352                                throws ServletException, IOException {
353            doGet( request, response );
354        }
355    
356    }