001    //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/enterprise/servlet/OGCServletController.java $
002    // $Id: OGCServletController.java 26622 2010-09-07 14:43:21Z aschmitz $
003    /*----------------------------------------------------------------------------
004     This file is part of deegree, http://deegree.org/
005     Copyright (C) 2001-2009 by:
006       Department of Geography, University of Bonn
007     and
008       lat/lon GmbH
009    
010     This library is free software; you can redistribute it and/or modify it under
011     the terms of the GNU Lesser General Public License as published by the Free
012     Software Foundation; either version 2.1 of the License, or (at your option)
013     any later version.
014     This library is distributed in the hope that it will be useful, but WITHOUT
015     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
016     FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
017     details.
018     You should have received a copy of the GNU Lesser General Public License
019     along with this library; if not, write to the Free Software Foundation, Inc.,
020     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
021    
022     Contact information:
023    
024     lat/lon GmbH
025     Aennchenstr. 19, 53177 Bonn
026     Germany
027     http://lat-lon.de/
028    
029     Department of Geography, University of Bonn
030     Prof. Dr. Klaus Greve
031     Postfach 1147, 53001 Bonn
032     Germany
033     http://www.geographie.uni-bonn.de/deegree/
034    
035     e-mail: info@deegree.org
036    ----------------------------------------------------------------------------*/
037    
038    package org.deegree.enterprise.servlet;
039    
040    import static java.lang.Character.isDigit;
041    import static java.lang.System.getProperty;
042    import static java.lang.System.setProperty;
043    import static org.deegree.enterprise.servlet.ServiceLookup.getInstance;
044    import static org.deegree.framework.log.LoggerFactory.getLogger;
045    import static org.deegree.framework.util.StringTools.arrayToString;
046    
047    import java.beans.Introspector;
048    import java.io.IOException;
049    import java.io.OutputStream;
050    import java.io.PrintWriter;
051    import java.lang.reflect.InvocationTargetException;
052    import java.lang.reflect.Method;
053    import java.net.InetAddress;
054    import java.net.URL;
055    import java.nio.charset.Charset;
056    import java.sql.Driver;
057    import java.sql.DriverManager;
058    import java.sql.SQLException;
059    import java.text.MessageFormat;
060    import java.util.Enumeration;
061    import java.util.HashMap;
062    import java.util.Iterator;
063    import java.util.Map;
064    
065    import javax.imageio.spi.IIORegistry;
066    import javax.servlet.ServletContext;
067    import javax.servlet.ServletException;
068    import javax.servlet.http.HttpServletRequest;
069    import javax.servlet.http.HttpServletResponse;
070    import javax.xml.parsers.DocumentBuilderFactory;
071    import javax.xml.transform.TransformerFactory;
072    
073    import org.apache.commons.logging.LogFactory;
074    import org.apache.log4j.LogManager;
075    import org.deegree.crs.configuration.CRSConfiguration;
076    import org.deegree.enterprise.AbstractOGCServlet;
077    import org.deegree.enterprise.ServiceException;
078    import org.deegree.framework.log.ILogger;
079    import org.deegree.framework.util.CharsetUtils;
080    import org.deegree.framework.util.KVP2Map;
081    import org.deegree.framework.util.StringTools;
082    import org.deegree.framework.util.WebappResourceResolver;
083    import org.deegree.framework.version.Version;
084    import org.deegree.framework.xml.XMLFragment;
085    import org.deegree.ogcwebservices.ExceptionReport;
086    import org.deegree.ogcwebservices.OGCRequestFactory;
087    import org.deegree.ogcwebservices.OGCWebServiceException;
088    import org.deegree.ogcwebservices.OGCWebServiceRequest;
089    import org.deegree.ogcwebservices.wmps.configuration.WMPSConfigurationDocument;
090    import org.deegree.ogcwebservices.wms.configuration.WMSConfigurationDocument;
091    import org.deegree.ogcwebservices.wms.configuration.WMSConfigurationDocument_1_3_0;
092    import org.deegree.owscommon.XMLFactory;
093    import org.xml.sax.SAXException;
094    
095    /**
096     * An <code>OGCServletController</code> handles all incoming requests. The controller for all OGC service requests.
097     * Dispatcher to specific handler for WMS, WFS and other.
098     *
099     * @author <a href="mailto:tfr@users.sourceforge.net">Torsten Friebe </a>
100     * @author last edited by: $Author: aschmitz $
101     *
102     * @version $Revision: 26622 $, $Date: 22.04.2008 16:23:34$
103     * @see <a href="http://java.sun.com/blueprints/corej2eepatterns/Patterns/FrontController.html">Front controller </a>
104     */
105    public class OGCServletController extends AbstractOGCServlet {
106    
107        /**
108         * address is the url of the client which requests.
109         */
110        public static String address = null;
111    
112        private static final long serialVersionUID = -4461759017823581221L;
113    
114        private static ILogger LOG;
115    
116        private static final String SERVICE = "services";
117    
118        private static final String HANDLER_CLASS = ".handler";
119    
120        private static final String HANDLER_CONF = ".config";
121    
122        private static final Map<Class<?>, String> SERVICE_FACTORIES_MAPPINGS = new HashMap<Class<?>, String>();
123    
124        private static final String ERR_MSG = "Can't set configuration for {0}";
125    
126        /**
127         *
128         *
129         * @param request
130         * @param response
131         * @TODO refactor and optimize code for initializing handler
132         */
133        public void doService( HttpServletRequest request, HttpServletResponse response ) {
134            if ( response.isCommitted() ) {
135                LOG.logWarning( "The response object is already committed!" );
136            }
137    
138            long startTime = System.currentTimeMillis();
139            address = request.getRequestURL().toString();
140    
141            String service = null;
142            try {
143                OGCWebServiceRequest ogcRequest = OGCRequestFactory.create( request );
144    
145                LOG.logInfo( StringTools.concat( 500, "Handling request '", ogcRequest.getId(), "' from '",
146                                                 request.getRemoteAddr(), "' to service: '", ogcRequest.getServiceName(),
147                                                 "'" ) );
148    
149                // get service from request
150                service = ogcRequest.getServiceName().toUpperCase();
151    
152                // get handler instance
153                ServiceDispatcher handler = ServiceLookup.getInstance().getHandler( service, request.getRemoteAddr() );
154                // dispatch request to specific handler
155                handler.perform( ogcRequest, response );
156            } catch ( OGCWebServiceException e ) {
157                LOG.logError( e.getMessage(), e );
158                sendException( response, e, request, service );
159            } catch ( ServiceException e ) {
160                if ( e.getNestedException() instanceof OGCWebServiceException ) {
161                    sendException( response, (OGCWebServiceException) e.getNestedException(), request, service );
162                } else {
163                    sendException( response, new OGCWebServiceException( this.getClass().getName(), e.getMessage() ),
164                                   request, service );
165                }
166                LOG.logError( e.getMessage(), e );
167            } catch ( Exception e ) {
168                sendException( response, new OGCWebServiceException( this.getClass().getName(), e.getMessage() ), request,
169                               service );
170                LOG.logError( e.getMessage(), e );
171            }
172            if ( LOG.isDebug() ) {
173                LOG.logDebug( "OGCServletController: request performed in "
174                              + Long.toString( System.currentTimeMillis() - startTime ) + " milliseconds." );
175            }
176        }
177    
178        /**
179         * Sends the passed <code>OGCWebServiceException</code> to the calling client.
180         *
181         * @param response
182         * @param e
183         * @param request
184         * @param service
185         *            the service name, if known
186         */
187        private static void sendException( HttpServletResponse response, OGCWebServiceException e,
188                                           HttpServletRequest request, String service ) {
189            LOG.logInfo( "Sending OGCWebServiceException to client." );
190    
191            Map<?, ?> pmap = request.getParameterMap();
192            Map<String, String> map = new HashMap<String, String>( pmap.size() );
193            for ( Object o : pmap.keySet() ) {
194                String[] tmp = (String[]) pmap.get( o );
195                for ( int i = 0; i < tmp.length; i++ ) {
196                    tmp[i] = tmp[i].trim();
197                }
198                map.put( ( (String) o ).toLowerCase(), arrayToString( tmp, ',' ) );
199            }
200    
201            boolean isWMS130 = false, isCSW = false, isWCTS = false, isWFS = false, isWFS100 = false;
202    
203            if ( service == null ) {
204                service = map.get( "service" );
205            }
206    
207            String version = map.get( "version" );
208    
209            if ( service != null ) {
210                if ( "wms".equalsIgnoreCase( service ) ) {
211                    isWMS130 = version != null && version.equals( "1.3.0" );
212                }
213                if ( "wfs".equalsIgnoreCase( service ) ) {
214                    isWFS = true;
215                    isWFS100 = version != null && version.equals( "1.0.0" );
216                }
217    
218                isCSW = "csw".equalsIgnoreCase( service );
219                isWCTS = "wcts".equalsIgnoreCase( service );
220                isWFS = "wfs".equalsIgnoreCase( service );
221            } else {
222                try {
223                    XMLFragment doc = new XMLFragment( request.getReader(), XMLFragment.DEFAULT_URL );
224                    service = OGCRequestFactory.getTargetService( "", "", doc.getRootElement().getOwnerDocument() );
225                    isCSW = "csw".equalsIgnoreCase( service );
226                    isWCTS = "wcts".equalsIgnoreCase( service );
227                    isWFS = "wfs".equalsIgnoreCase( service );
228                    isWFS100 = isWFS && doc.getRootElement().getAttribute( "version" ) != null
229                               && doc.getRootElement().getAttribute( "version" ).equals( "1.0.0" );
230                } catch ( SAXException e1 ) {
231                    // ignore
232                } catch ( IOException e1 ) {
233                    // ignore
234                } catch ( IllegalStateException e1 ) {
235                    // ignore, that happens in some tomcats
236                }
237            }
238    
239            try {
240                XMLFragment doc;
241                String contentType = "text/xml";
242    
243                if ( !( isWMS130 || isCSW || isWCTS || isWFS ) ) {
244                    // apply the simplest of heuristics...
245                    String req = request.getRequestURI().toLowerCase();
246                    if ( req.indexOf( "csw" ) != -1 ) {
247                        isCSW = true;
248                    } else if ( req.indexOf( "wcts" ) != -1 ) {
249                        isWCTS = true;
250                    } else if ( req.indexOf( "wfs" ) != -1 ) {
251                        isWFS = true;
252                    }
253    
254                    if ( isWFS ) {
255                        isWFS100 = req.indexOf( "1.0.0" ) != -1;
256                    }
257    
258                    if ( !( isWMS130 || isCSW || isWCTS || isWFS || isWFS100 ) ) {
259                        isWMS130 = version != null && version.equals( "1.3.0" );
260                    }
261                }
262    
263                // send exception format INIMAGE etc. for WMS
264                if ( service != null && service.equalsIgnoreCase( "wms" ) ) {
265                    ServiceDispatcher handler = getInstance().getHandler( service, request.getRemoteAddr() );
266                    if ( handler instanceof WMSHandler ) {
267                        WMSHandler h = (WMSHandler) handler;
268                        String format = map.get( "format" );
269                        String eFormat = map.get( "exceptions" );
270                        try {
271                            h.determineExceptionFormat( eFormat, format, version, response );
272                            h.writeServiceExceptionReport( e );
273                            return;
274                        } catch ( Exception ex ) {
275                            LOG.logDebug( "Error while sending the exception in special format."
276                                          + " Continuing in default mode.", ex );
277                        }
278                    }
279                }
280    
281                if ( isWMS130 || "wcs".equalsIgnoreCase( e.getLocator() ) ) {
282                    doc = XMLFactory.exportNS( new ExceptionReport( new OGCWebServiceException[] { e } ) );
283                } else if ( isCSW ) {
284                    doc = XMLFactory.exportExceptionReport( new ExceptionReport( new OGCWebServiceException[] { e } ) );
285                } else if ( isWCTS ) {
286                    doc = org.deegree.owscommon_1_1_0.XMLFactory.exportException( e );
287                } else if ( isWFS100 ) {
288                    doc = XMLFactory.exportExceptionReportWFS100( e );
289                } else if ( isWFS ) {
290                    doc = XMLFactory.exportExceptionReportWFS( e );
291                } else {
292                    contentType = "application/vnd.ogc.se_xml";
293                    doc = XMLFactory.export( new ExceptionReport( new OGCWebServiceException[] { e } ) );
294                }
295    
296                response.setContentType( contentType );
297                OutputStream os = response.getOutputStream();
298                doc.write( os );
299                os.close();
300            } catch ( Exception ex ) {
301                LOG.logError( "ERROR: " + ex.getMessage(), ex );
302            }
303        }
304    
305        /**
306         *
307         * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest,
308         *      javax.servlet.http.HttpServletResponse)
309         */
310        @Override
311        protected void doGet( HttpServletRequest request, HttpServletResponse response )
312                                throws ServletException, IOException {
313    
314            LOG.logDebug( "query string ", request.getQueryString() );
315            if ( request.getParameter( "RELOADDEEGREE" ) != null ) {
316                reloadServices( request, response );
317            } else {
318                this.doService( request, response );
319            }
320        }
321    
322        /**
323         *
324         * @param request
325         * @param response
326         * @throws ServletException
327         * @throws IOException
328         */
329        private void reloadServices( HttpServletRequest request, HttpServletResponse response )
330                                throws ServletException, IOException {
331            Map<?, ?> map = KVP2Map.toMap( request );
332            String user = (String) map.get( "USER" );
333            String password = (String) map.get( "PASSWORD" );
334            String message = null;
335            if ( getInitParameter( "USER" ) != null && getInitParameter( "PASSWORD" ) != null
336                 && getInitParameter( "USER" ).equals( user ) && getInitParameter( "PASSWORD" ).equals( password ) ) {
337                initServices( getServletContext() );
338                ctDestroyed();
339                message = Messages.getString( "OGCServletController.reloadsuccess" );
340            } else {
341                message = Messages.getString( "OGCServletController.reloadfailed" );
342            }
343            PrintWriter pw = response.getWriter();
344            pw.print( message );
345            pw.flush();
346            pw.close();
347        }
348    
349        /*
350         * (non-Javadoc)
351         *
352         * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest,
353         * javax.servlet.http.HttpServletResponse)
354         */
355        @Override
356        protected void doPost( HttpServletRequest request, HttpServletResponse response )
357                                throws ServletException, IOException {
358            this.doService( request, response );
359        }
360    
361        private static String spaces( int i ) {
362            if ( i <= 0 ) {
363                return "";
364            }
365    
366            StringBuffer sb = new StringBuffer( i );
367            for ( int j = 0; j < i; ++j ) {
368                sb.append( " " );
369            }
370            return sb.toString();
371        }
372    
373        private static void logIfThere( String param ) {
374            String val = getProperty( param );
375            if ( val != null ) {
376                LOG.logInfo( "- " + param + spaces( 15 - param.length() ) + ": " + val );
377            }
378        }
379    
380        /**
381         * @see javax.servlet.GenericServlet#init()
382         */
383        @Override
384        public void init()
385                                throws ServletException {
386    
387            synchronized ( OGCServletController.class ) {
388                if ( LOG == null ) {
389                    // hack to figure out and set the context path name
390                    // for a laugh, see http://marc.info/?l=tomcat-user&m=109215904113904&w=2 and the related thread
391                    // http://marc.info/?t=109215871400004&r=1&w=2
392                    String path = getServletContext().getRealPath( "" );
393                    String[] ps = path.split( "[/\\\\]" );
394                    path = ps[ps.length - 1];
395                    // heuristics are always a charm (and work best for tomcat in this case)
396                    if ( isDigit( path.charAt( 0 ) ) && path.indexOf( "-" ) != -1 ) {
397                        path = path.split( "-", 2 )[1];
398                    }
399                    // note that setting this changes it on a JVM GLOBAL BASIS, so it WILL GET OVERWRITTEN in subsequent
400                    // deegree startups! (However, since the log4j.properties will only be read on startup, this hack is
401                    // useful anyway)
402                    setProperty( "context.name", path );
403    
404                    LOG = getLogger( OGCServletController.class );
405                }
406            }
407    
408            super.init();
409            LOG.logDebug( "Logger for " + this.getClass().getName() + " initialized." );
410    
411            SERVICE_FACTORIES_MAPPINGS.put( CSWHandler.class, "org.deegree.ogcwebservices.csw.CSWFactory" );
412            SERVICE_FACTORIES_MAPPINGS.put( WFSHandler.class, "org.deegree.ogcwebservices.wfs.WFServiceFactory" );
413            SERVICE_FACTORIES_MAPPINGS.put( WCSHandler.class, "org.deegree.ogcwebservices.wcs.WCServiceFactory" );
414            SERVICE_FACTORIES_MAPPINGS.put( WMSHandler.class, "org.deegree.ogcwebservices.wms.WMServiceFactory" );
415            SERVICE_FACTORIES_MAPPINGS.put( SOSHandler.class, "org.deegree.ogcwebservices.sos.SOServiceFactory" );
416            SERVICE_FACTORIES_MAPPINGS.put( WPVSHandler.class, "org.deegree.ogcwebservices.wpvs.WPVServiceFactory" );
417            SERVICE_FACTORIES_MAPPINGS.put( WMPSHandler.class, "org.deegree.ogcwebservices.wmps.WMPServiceFactory" );
418            SERVICE_FACTORIES_MAPPINGS.put( WPSHandler.class, "org.deegree.ogcwebservices.wps.WPServiceFactory" );
419            SERVICE_FACTORIES_MAPPINGS.put( WASSHandler.class, "org.deegree.ogcwebservices.wass.common.WASServiceFactory" );
420            SERVICE_FACTORIES_MAPPINGS.put( WCTSHandler.class, "org.deegree.ogcwebservices.wcts.WCTServiceFactory" );
421    
422            LOG.logInfo( "-------------------------------------------------------------------------------" );
423            LOG.logInfo( "Starting deegree version " + Version.getVersion() );
424            LOG.logInfo( "- context        : " + this.getServletContext().getServletContextName() );
425            LOG.logInfo( "- real path      : " + this.getServletContext().getRealPath( "/" ) );
426            LOG.logInfo( "- java version   : " + System.getProperty( "java.version" ) + "" );
427            LOG.logInfo( "- dom builder    : " + DocumentBuilderFactory.newInstance().getClass().getName() + "" );
428            LOG.logInfo( "- xslt builder   : " + TransformerFactory.newInstance().getClass().getName() + "" );
429            LOG.logInfo( "- system charset : " + CharsetUtils.getSystemCharset() );
430            LOG.logInfo( "- default charset: " + Charset.defaultCharset() );
431            LOG.logInfo( "- server info    : " + this.getServletContext().getServerInfo() );
432            logIfThere( "proxyHost" );
433            logIfThere( "proxyPort" );
434            logIfThere( "noProxyHosts" );
435            logIfThere( "nonProxyHosts" );
436            logIfThere( "http.proxyHost" );
437            logIfThere( "http.proxyPort" );
438            logIfThere( "http.noProxyHosts" );
439            logIfThere( "http.nonProxyHosts" );
440            logIfThere( "ftp.proxyHost" );
441            logIfThere( "ftp.proxyPort" );
442            logIfThere( "ftp.noProxyHosts" );
443            logIfThere( "ftp.nonProxyHosts" );
444            logIfThere( "https.proxyHost" );
445            logIfThere( "https.proxyPort" );
446            logIfThere( "https.noProxyHosts" );
447            logIfThere( "https.nonProxyHosts" );
448            try {
449                LOG.logInfo( "- ip             : " + InetAddress.getLocalHost().getHostAddress() );
450                LOG.logInfo( "- host name      : " + InetAddress.getLocalHost().getHostName() );
451                LOG.logInfo( "- domain name    : " + InetAddress.getLocalHost().getCanonicalHostName() );
452            } catch ( Exception e ) {
453                LOG.logError( e.getMessage(), e );
454            }
455            LOG.logInfo( "-------------------------------------------------------------------------------" );
456            this.initServices( getServletContext() );
457            checkServerCompatibility();
458            LOG.logInfo( "-------------------------------------------------------------------------------" );
459            String tmpServiceList = this.getServiceList();
460            if ( tmpServiceList != null && !( "".equals( tmpServiceList.trim() ) ) ) {
461                LOG.logInfo( "Initialized successfully (context '" + this.getServletContext().getServletContextName()
462                             + "'):" );
463                String[] tmpServices = tmpServiceList.split( "," );
464                for ( String service : tmpServices ) {
465                    // Added a check for the alternative service name, because it should not be outputed twice for the csw.
466                    if ( !OGCRequestFactory.CSW_SERVICE_NAME_EBRIM.toUpperCase().equals( service ) ) {
467                        LOG.logInfo( "- " + service );
468                    }
469                }
470            } else {
471                LOG.logError( "An Error occured while initializing context '"
472                              + this.getServletContext().getServletContextName() + "', no services are available." );
473            }
474    
475            LOG.logInfo( "-------------------------------------------------------------------------------" );
476            // Sets the attributes for tomcat -> application.getAttribute(); in jsp sites
477            this.getServletContext().setAttribute( "deegree_ogc_services", this.getServiceList() );
478        }
479    
480        private void checkServerCompatibility() {
481            String serverInfo = getServletContext().getServerInfo();
482            if ( "Apache Tomcat/5.5.26".equals( serverInfo ) || "Apache Tomcat/6.0.16".equals( serverInfo ) ) {
483                LOG.logWarning( "*******************************************************************************" );
484                LOG.logWarning( "YOU ARE RUNNING DEEGREE ON A TOMCAT RELEASE (" + serverInfo
485                                + ") THAT IS KNOWN TO HAVE A SERIOUS ISSUE WITH LARGE POST REQUESTS." );
486                LOG.logWarning( "PLEASE CONSIDER THE CORRESPONDING DEEGREE WIKI PAGE AT  https://wiki.deegree.org/deegreeWiki/ApacheTomcat "
487                                + "FOR DETAILS AND SWITCH TO A DIFFERENT TOMCAT VERSION." );
488                LOG.logWarning( "*******************************************************************************" );
489            }
490        }
491    
492        private void initServices( ServletContext context )
493                                throws ServletException {
494    
495            // get list of OGC services
496            String serviceList = this.getRequiredInitParameter( SERVICE );
497    
498            String[] serviceNames = StringTools.toArray( serviceList, ",", false );
499    
500            ServiceLookup lookup = ServiceLookup.getInstance();
501            for ( int i = 0; i < serviceNames.length; i++ ) {
502                LOG.logInfo( StringTools.concat( 100, "---- Initializing ", serviceNames[i].toUpperCase(), " ----" ) );
503                try {
504                    String className = this.getRequiredInitParameter( serviceNames[i] + HANDLER_CLASS );
505                    Class<?> handlerClzz = Class.forName( className );
506    
507                    // initialize each service factory
508                    String s = this.getRequiredInitParameter( serviceNames[i] + HANDLER_CONF );
509                    URL serviceConfigurationURL = WebappResourceResolver.resolveFileLocation( s, context, LOG );
510    
511                    // set configuration
512                    LOG.logInfo( StringTools.concat( 300, "Reading configuration for ", serviceNames[i].toUpperCase(),
513                                                     " from URL: '", serviceConfigurationURL, "'." ) );
514    
515                    String factoryClassName = SERVICE_FACTORIES_MAPPINGS.get( handlerClzz );
516    
517                    Class<?> factory = Class.forName( factoryClassName );
518                    Method method = factory.getMethod( "setConfiguration", new Class[] { URL.class } );
519                    method.invoke( factory, new Object[] { serviceConfigurationURL } );
520    
521                    // The csw-ebrim profile adds an alternative service name, it too is registred with the CSW handler.
522                    if ( "CSW".equals( serviceNames[i].toUpperCase() ) ) {
523                        lookup.addService( OGCRequestFactory.CSW_SERVICE_NAME_EBRIM.toUpperCase(), handlerClzz );
524                    }
525                    // put handler to available service list
526                    lookup.addService( serviceNames[i].toUpperCase(), handlerClzz );
527    
528                    LOG.logInfo( StringTools.concat( 300, serviceNames[i].toUpperCase(), " successfully initialized." ) );
529                } catch ( ServletException e ) {
530                    LOG.logError( e.getMessage(), e );
531                } catch ( InvocationTargetException e ) {
532                    e.getTargetException().printStackTrace();
533                    LOG.logError( this.produceMessage( ERR_MSG, new Object[] { serviceNames[i] } ), e );
534                } catch ( Exception e ) {
535                    LOG.logError( "Can't initialize OGC service:" + serviceNames[i], e );
536                }
537            }
538        }
539    
540        private String getRequiredInitParameter( String name )
541                                throws ServletException {
542            String paramValue = getInitParameter( name );
543            if ( paramValue == null ) {
544    
545                String msg = "Required init parameter '" + name + "' missing in web.xml";
546                LOG.logError( msg );
547                throw new ServletException( msg );
548            }
549            return paramValue;
550        }
551    
552        /**
553         * @return the services, separated by ","
554         */
555        private String getServiceList() {
556    
557            StringBuffer buf = new StringBuffer();
558            ServiceLookup lookup = ServiceLookup.getInstance();
559            for ( Iterator<?> iter = lookup.getIterator(); iter.hasNext(); ) {
560                String serviceName = (String) iter.next();
561                buf.append( serviceName );
562                if ( iter.hasNext() ) {
563                    buf.append( ',' );
564                }
565            }
566            return buf.toString();
567        }
568    
569        /**
570         * Formats the provided string and the args array into a String using MessageFormat.
571         *
572         * @param pattern
573         * @param args
574         * @return the message to present the client.
575         */
576        private String produceMessage( String pattern, Object[] args ) {
577            return new MessageFormat( pattern ).format( args );
578        }
579    
580        /**
581         * @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent)
582         */
583        public void ctDestroyed() {
584            LOG.logInfo( "Stopping context: " );
585    
586            WMSConfigurationDocument.resetCapabilitiesCache();
587            WMSConfigurationDocument_1_3_0.resetCapabilitiesCache();
588            WMPSConfigurationDocument.resetCapabilitiesCache();
589    
590            ServiceLookup lookup = ServiceLookup.getInstance();
591            for ( Iterator<?> iter = lookup.getIterator(); iter.hasNext(); ) {
592                String serviceName = (String) iter.next();
593                LOG.logInfo( "Stopping service " + serviceName );
594    
595                try {
596                    String s = SERVICE_FACTORIES_MAPPINGS.get( lookup.getService( serviceName ) );
597                    Class<?> clzz = Class.forName( s );
598                    // TODO stop and reset all service instances
599                    Method[] methods = clzz.getMethods();
600                    for ( int j = 0; j < methods.length; j++ ) {
601                        if ( methods[j].getName().equals( "reset" ) ) {
602                            Object[] args = new Object[0];
603                            methods[j].invoke( clzz.newInstance(), args );
604                        }
605                    }
606                } catch ( Exception e ) {
607                    LOG.logError( e.getMessage(), e );
608                }
609            }
610        }
611    
612        @Override
613        public void destroy() {
614            super.destroy();
615            Enumeration<Driver> e = DriverManager.getDrivers();
616            while ( e.hasMoreElements() ) {
617                Driver driver = e.nextElement();
618                try {
619                    if ( driver.getClass().getClassLoader() == getClass().getClassLoader() )
620                        DriverManager.deregisterDriver( driver );
621                } catch ( SQLException e1 ) {
622                    LOG.logError( "Cannot unload driver: " + driver );
623                }
624            }
625            LogFactory.releaseAll();
626            LogManager.shutdown();
627            // SLF4JLogFactory.releaseAll(); // should be the same as the LogFactory.releaseAll call
628            Iterator<Class<?>> i = IIORegistry.getDefaultInstance().getCategories();
629            while ( i.hasNext() ) {
630                Class<?> c = i.next();
631                Iterator<?> k = IIORegistry.getDefaultInstance().getServiceProviders( c, false );
632                while ( k.hasNext() ) {
633                    Object o = k.next();
634                    if ( o.getClass().getClassLoader() == getClass().getClassLoader() ) {
635                        IIORegistry.getDefaultInstance().deregisterServiceProvider( o );
636                        LOG.logDebug( "Deregistering JAI driver ", o.getClass() );
637                    }
638                }
639            }
640            Introspector.flushCaches();
641            // just clear the configurations for now, it does not hurt
642            CRSConfiguration.DEFINED_CONFIGURATIONS.clear();
643        }
644    
645    }