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