    001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.4_testing/src/org/deegree/enterprise/servlet/OGCServletController.java $
    002    // $Id: OGCServletController.java 18195 2009-06-18 15:55:39Z mschneider $
    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: mschneider $
    101     *
    102     * @version $Revision: 18195 $, $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, cannot proceed!" );
    136                return;
    137            }
    138
    139            long startTime = System.currentTimeMillis();
    140            address = request.getRequestURL().toString();
    141
    142            String service = null;
    143            try {
    144                OGCWebServiceRequest ogcRequest = OGCRequestFactory.create( request );
    145
    146                LOG.logInfo( StringTools.concat( 500, "Handling request '", ogcRequest.getId(), "' from '",
    147                                                 request.getRemoteAddr(), "' to service: '", ogcRequest.getServiceName(),
    148                                                 "'" ) );
    149
    150                // get service from request
    151                service = ogcRequest.getServiceName().toUpperCase();
    152
    153                // get handler instance
    154                ServiceDispatcher handler = ServiceLookup.getInstance().getHandler( service, request.getRemoteAddr() );
    155                // dispatch request to specific handler
    156                handler.perform( ogcRequest, response );
    157            } catch ( OGCWebServiceException e ) {
    158                LOG.logError( e.getMessage(), e );
    159                sendException( response, e, request, service );
    160            } catch ( ServiceException e ) {
    161                if ( e.getNestedException() instanceof OGCWebServiceException ) {
    162                    sendException( response, (OGCWebServiceException) e.getNestedException(), request, service );
    163                } else {
    164                    sendException( response, new OGCWebServiceException( this.getClass().getName(), e.getMessage() ),
    165                                   request, service );
    166                }
    167                LOG.logError( e.getMessage(), e );
    168            } catch ( Exception e ) {
    169                sendException( response, new OGCWebServiceException( this.getClass().getName(), e.getMessage() ), request,
    170                               service );
    171                LOG.logError( e.getMessage(), e );
    172            }
    173            if ( LOG.isDebug() ) {
    174                LOG.logDebug( "OGCServletController: request performed in "
    175                              + Long.toString( System.currentTimeMillis() - startTime ) + " milliseconds." );
    176            }
    177        }
    178
    179        /**
    180         * Sends the passed <code>OGCWebServiceException</code> to the calling client.
    181         *
    182         * @param response
    183         * @param e
    184         * @param request
    185         * @param service
    186         *            the service name, if known
    187         */
    188        private static void sendException( HttpServletResponse response, OGCWebServiceException e,
    189                                           HttpServletRequest request, String service ) {
    190            LOG.logInfo( "Sending OGCWebServiceException to client." );
    191
    192            Map<?, ?> pmap = request.getParameterMap();
    193            Map<String, String> map = new HashMap<String, String>( pmap.size() );
    194            for ( Object o : pmap.keySet() ) {
    195                String[] tmp = (String[]) pmap.get( o );
    196                for ( int i = 0; i < tmp.length; i++ ) {
    197                    tmp[i] = tmp[i].trim();
    198                }
    199                map.put( ( (String) o ).toLowerCase(), arrayToString( tmp, ',' ) );
    200            }
    201
    202            boolean isWMS130 = false, isCSW = false, isWCTS = false, isWFS = false, isWFS100 = false;
    203
    204            if ( service == null ) {
    205                service = map.get( "service" );
    206            }
    207
    208            String version = map.get( "version" );
    209
    210            if ( service != null ) {
    211                if ( "wms".equalsIgnoreCase( service ) ) {
    212                    isWMS130 = version != null && version.equals( "1.3.0" );
    213                }
    214                if ( "wfs".equalsIgnoreCase( service ) ) {
    215                    isWFS = true;
    216                    isWFS100 = version != null && version.equals( "1.0.0" );
    217                }
    218
    219                isCSW = "csw".equalsIgnoreCase( service );
    220                isWCTS = "wcts".equalsIgnoreCase( service );
    221                isWFS = "wfs".equalsIgnoreCase( service );
    222            } else {
    223                try {
    224                    XMLFragment doc = new XMLFragment( request.getReader(), XMLFragment.DEFAULT_URL );
    225                    service = OGCRequestFactory.getTargetService( "", "", doc.getRootElement().getOwnerDocument() );
    226                    isCSW = "csw".equalsIgnoreCase( service );
    227                    isWCTS = "wcts".equalsIgnoreCase( service );
    228                    isWFS = "wfs".equalsIgnoreCase( service );
    229                    isWFS100 = isWFS && doc.getRootElement().getAttribute( "version" ) != null
    230                               && doc.getRootElement().getAttribute( "version" ).equals( "1.0.0" );
    231                } catch ( SAXException e1 ) {
    232                    // ignore
    233                } catch ( IOException e1 ) {
    234                    // ignore
    235                } catch ( IllegalStateException e1 ) {
    236                    // ignore, that happens in some tomcats
    237                }
    238            }
    239
    240            try {
    241                XMLFragment doc;
    242                String contentType = "text/xml";
    243
    244                if ( !( isWMS130 || isCSW || isWCTS || isWFS ) ) {
    245                    // apply the simplest of heuristics...
    246                    String req = request.getRequestURI().toLowerCase();
    247                    if ( req.indexOf( "csw" ) != -1 ) {
    248                        isCSW = true;
    249                    } else if ( req.indexOf( "wcts" ) != -1 ) {
    250                        isWCTS = true;
    251                    } else if ( req.indexOf( "wfs" ) != -1 ) {
    252                        isWFS = true;
    253                    }
    254
    255                    if ( isWFS ) {
    256                        isWFS100 = req.indexOf( "1.0.0" ) != -1;
    257                    }
    258
    259                    if ( !( isWMS130 || isCSW || isWCTS || isWFS || isWFS100 ) ) {
    260                        isWMS130 = version != null && version.equals( "1.3.0" );
    261                    }
    262                }
    263
    264                // send exception format INIMAGE etc. for WMS
    265                if ( service != null && service.equalsIgnoreCase( "wms" ) ) {
    266                    ServiceDispatcher handler = getInstance().getHandler( service, request.getRemoteAddr() );
    267                    if ( handler instanceof WMSHandler ) {
    268                        WMSHandler h = (WMSHandler) handler;
    269                        String format = map.get( "format" );
    270                        String eFormat = map.get( "exceptions" );
    271                        try {
    272                            h.determineExceptionFormat( eFormat, format, version, response );
    273                            h.writeServiceExceptionReport( e );
    274                            return;
    275                        } catch ( Exception ex ) {
    276                            LOG.logDebug( "Error while sending the exception in special format."
    277                                          + " Continuing in default mode.", ex );
    278                        }
    279                    }
    280                }
    281
    282                if ( isWMS130 || "wcs".equalsIgnoreCase( e.getLocator() ) ) {
    283                    doc = XMLFactory.exportNS( new ExceptionReport( new OGCWebServiceException[] { e } ) );
    284                } else if ( isCSW ) {
    285                    doc = XMLFactory.exportExceptionReport( new ExceptionReport( new OGCWebServiceException[] { e } ) );
    286                } else if ( isWCTS ) {
    287                    doc = org.deegree.owscommon_1_1_0.XMLFactory.exportException( e );
    288                } else if ( isWFS100 ) {
    289                    doc = XMLFactory.exportExceptionReportWFS100( e );
    290                } else if ( isWFS ) {
    291                    doc = XMLFactory.exportExceptionReportWFS( e );
    292                } else {
    293                    contentType = "application/vnd.ogc.se_xml";
    294                    doc = XMLFactory.export( new ExceptionReport( new OGCWebServiceException[] { e } ) );
    295                }
    296
    297                response.setContentType( contentType );
    298                OutputStream os = response.getOutputStream();
    299                doc.write( os );
    300                os.close();
    301            } catch ( Exception ex ) {
    302                LOG.logError( "ERROR: " + ex.getMessage(), ex );
    303            }
    304        }
    305
    306        /**
    307         *
    308         * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest,
    309         *      javax.servlet.http.HttpServletResponse)
    310         */
    311        @Override
    312        protected void doGet( HttpServletRequest request, HttpServletResponse response )
    313                                throws ServletException, IOException {
    314
    315            LOG.logDebug( "query string ", request.getQueryString() );
    316            if ( request.getParameter( "RELOADDEEGREE" ) != null ) {
    317                reloadServices( request, response );
    318            } else {
    319                this.doService( request, response );
    320            }
    321        }
    322
    323        /**
    324         *
    325         * @param request
    326         * @param response
    327         * @throws ServletException
    328         * @throws IOException
    329         */
    330        private void reloadServices( HttpServletRequest request, HttpServletResponse response )
    331                                throws ServletException, IOException {
    332            Map<?, ?> map = KVP2Map.toMap( request );
    333            String user = (String) map.get( "USER" );
    334            String password = (String) map.get( "PASSWORD" );
    335            String message = null;
    336            if ( getInitParameter( "USER" ) != null && getInitParameter( "PASSWORD" ) != null
    337                 && getInitParameter( "USER" ).equals( user ) && getInitParameter( "PASSWORD" ).equals( password ) ) {
    338                initServices( getServletContext() );
    339                ctDestroyed();
    340                message = Messages.getString( "OGCServletController.reloadsuccess" );
    341            } else {
    342                message = Messages.getString( "OGCServletController.reloadfailed" );
    343            }
    344            PrintWriter pw = response.getWriter();
    345            pw.print( message );
    346            pw.flush();
    347            pw.close();
    348        }
    349
    350        /*
    351         * (non-Javadoc)
    352         *
    353         * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest,
    354         * javax.servlet.http.HttpServletResponse)
    355         */
    356        @Override
    357        protected void doPost( HttpServletRequest request, HttpServletResponse response )
    358                                throws ServletException, IOException {
    359            this.doService( request, response );
    360        }
    361
    362        private static String spaces( int i ) {
    363            if ( i <= 0 ) {
    364                return "";
    365            }
    366
    367            StringBuffer sb = new StringBuffer( i );
    368            for ( int j = 0; j < i; ++j ) {
    369                sb.append( " " );
    370            }
    371            return sb.toString();
    372        }
    373
    374        private static void logIfThere( String param ) {
    375            String val = getProperty( param );
    376            if ( val != null ) {
    377                LOG.logInfo( "- " + param + spaces( 15 - param.length() ) + ": " + val );
    378            }
    379        }
    380
    381        /**
    382         * @see javax.servlet.GenericServlet#init()
    383         */
    384        @Override
    385        public void init()
    386                                throws ServletException {
    387
    388            synchronized ( OGCServletController.class ) {
    389                if ( LOG == null ) {
    390                    // hack to figure out and set the context path name
    391                    // for a laugh, see http://marc.info/?l=tomcat-user&m=109215904113904&w=2 and the related thread
    392                    // http://marc.info/?t=109215871400004&r=1&w=2
    393                    String path = getServletContext().getRealPath( "" );
    394                    String[] ps = path.split( "[/\\\\]" );
    395                    path = ps[ps.length - 1];
    396                    // heuristics are always a charm (and work best for tomcat in this case)
    397                    if ( isDigit( path.charAt( 0 ) ) && path.indexOf( "-" ) != -1 ) {
    398                        path = path.split( "-", 2 )[1];
    399                    }
    400                    // note that setting this changes it on a JVM GLOBAL BASIS, so it WILL GET OVERWRITTEN in subsequent
    401                    // deegree startups! (However, since the log4j.properties will only be read on startup, this hack is
    402                    // useful anyway)
    403                    setProperty( "context.name", path );
    404
    405                    LOG = getLogger( OGCServletController.class );
    406                }
    407            }
    408
    409            super.init();
    410            LOG.logDebug( "Logger for " + this.getClass().getName() + " initialized." );
    411
    412            SERVICE_FACTORIES_MAPPINGS.put( CSWHandler.class, "org.deegree.ogcwebservices.csw.CSWFactory" );
    413            SERVICE_FACTORIES_MAPPINGS.put( WFSHandler.class, "org.deegree.ogcwebservices.wfs.WFServiceFactory" );
    414            SERVICE_FACTORIES_MAPPINGS.put( WCSHandler.class, "org.deegree.ogcwebservices.wcs.WCServiceFactory" );
    415            SERVICE_FACTORIES_MAPPINGS.put( WMSHandler.class, "org.deegree.ogcwebservices.wms.WMServiceFactory" );
    416            SERVICE_FACTORIES_MAPPINGS.put( SOSHandler.class, "org.deegree.ogcwebservices.sos.SOServiceFactory" );
    417            SERVICE_FACTORIES_MAPPINGS.put( WPVSHandler.class, "org.deegree.ogcwebservices.wpvs.WPVServiceFactory" );
    418            SERVICE_FACTORIES_MAPPINGS.put( WMPSHandler.class, "org.deegree.ogcwebservices.wmps.WMPServiceFactory" );
    419            SERVICE_FACTORIES_MAPPINGS.put( WPSHandler.class, "org.deegree.ogcwebservices.wps.WPServiceFactory" );
    420            SERVICE_FACTORIES_MAPPINGS.put( WASSHandler.class, "org.deegree.ogcwebservices.wass.common.WASServiceFactory" );
    421            SERVICE_FACTORIES_MAPPINGS.put( WCTSHandler.class, "org.deegree.ogcwebservices.wcts.WCTServiceFactory" );
    422
    423            LOG.logInfo( "-------------------------------------------------------------------------------" );
    424            LOG.logInfo( "Starting deegree version " + Version.getVersion() );
    425            LOG.logInfo( "- context        : " + this.getServletContext().getServletContextName() );
    426            LOG.logInfo( "- real path      : " + this.getServletContext().getRealPath( "/" ) );
    427            LOG.logInfo( "- java version   : " + System.getProperty( "java.version" ) + "" );
    428            LOG.logInfo( "- dom builder    : " + DocumentBuilderFactory.newInstance().getClass().getName() + "" );
    429            LOG.logInfo( "- xslt builder   : " + TransformerFactory.newInstance().getClass().getName() + "" );
    430            LOG.logInfo( "- system charset : " + CharsetUtils.getSystemCharset() );
    431            LOG.logInfo( "- default charset: " + Charset.defaultCharset() );
    432            LOG.logInfo( "- server info    : " + this.getServletContext().getServerInfo() );
    433            logIfThere( "proxyHost" );
    434            logIfThere( "proxyPort" );
    435            logIfThere( "noProxyHosts" );
    436            logIfThere( "nonProxyHosts" );
    437            logIfThere( "http.proxyHost" );
    438            logIfThere( "http.proxyPort" );
    439            logIfThere( "http.noProxyHosts" );
    440            logIfThere( "http.nonProxyHosts" );
    441            logIfThere( "ftp.proxyHost" );
    442            logIfThere( "ftp.proxyPort" );
    443            logIfThere( "ftp.noProxyHosts" );
    444            logIfThere( "ftp.nonProxyHosts" );
    445            logIfThere( "https.proxyHost" );
    446            logIfThere( "https.proxyPort" );
    447            logIfThere( "https.noProxyHosts" );
    448            logIfThere( "https.nonProxyHosts" );
    449            try {
    450                LOG.logInfo( "- ip             : " + InetAddress.getLocalHost().getHostAddress() );
    451                LOG.logInfo( "- host name      : " + InetAddress.getLocalHost().getHostName() );
    452                LOG.logInfo( "- domain name    : " + InetAddress.getLocalHost().getCanonicalHostName() );
    453            } catch ( Exception e ) {
    454                LOG.logError( e.getMessage(), e );
    455            }
    456            LOG.logInfo( "-------------------------------------------------------------------------------" );
    457            this.initServices( getServletContext() );
    458            checkServerCompatibility();
    459            LOG.logInfo( "-------------------------------------------------------------------------------" );
    460            String tmpServiceList = this.getServiceList();
    461            if ( tmpServiceList != null && !( "".equals( tmpServiceList.trim() ) ) ) {
    462                LOG.logInfo( "Initialized successfully (context '" + this.getServletContext().getServletContextName()
    463                             + "'):" );
    464                String[] tmpServices = tmpServiceList.split( "," );
    465                for ( String service : tmpServices ) {
    466                    // Added a check for the alternative service name, because it should not be outputed twice for the csw.
    467                    if ( !OGCRequestFactory.CSW_SERVICE_NAME_EBRIM.toUpperCase().equals( service ) ) {
    468                        LOG.logInfo( "- " + service );
    469                    }
    470                }
    471            } else {
    472                LOG.logError( "An Error occured while initializing context '"
    473                              + this.getServletContext().getServletContextName() + "', no services are available." );
    474            }
    475
    476            LOG.logInfo( "-------------------------------------------------------------------------------" );
    477            // Sets the attributes for tomcat -> application.getAttribute(); in jsp sites
    478            this.getServletContext().setAttribute( "deegree_ogc_services", this.getServiceList() );
    479        }
    480
    481        private void checkServerCompatibility() {
    482            String serverInfo = getServletContext().getServerInfo();
    483            if ( "Apache Tomcat/5.5.26".equals( serverInfo ) || "Apache Tomcat/6.0.16".equals( serverInfo ) ) {
    484                LOG.logWarning( "*******************************************************************************" );
    485                LOG.logWarning( "YOU ARE RUNNING DEEGREE ON A TOMCAT RELEASE (" + serverInfo
    486                                + ") THAT IS KNOWN TO HAVE A SERIOUS ISSUE WITH LARGE POST REQUESTS." );
    487                LOG.logWarning( "PLEASE CONSIDER THE CORRESPONDING DEEGREE WIKI PAGE AT  https://wiki.deegree.org/deegreeWiki/ApacheTomcat "
    488                                + "FOR DETAILS AND SWITCH TO A DIFFERENT TOMCAT VERSION." );
    489                LOG.logWarning( "*******************************************************************************" );
    490            }
    491        }
    492
    493        private void initServices( ServletContext context )
    494                                throws ServletException {
    495
    496            // get list of OGC services
    497            String serviceList = this.getRequiredInitParameter( SERVICE );
    498
    499            String[] serviceNames = StringTools.toArray( serviceList, ",", false );
    500
    501            ServiceLookup lookup = ServiceLookup.getInstance();
    502            for ( int i = 0; i < serviceNames.length; i++ ) {
    503                LOG.logInfo( StringTools.concat( 100, "---- Initializing ", serviceNames[i].toUpperCase(), " ----" ) );
    504                try {
    505                    String className = this.getRequiredInitParameter( serviceNames[i] + HANDLER_CLASS );
    506                    Class<?> handlerClzz = Class.forName( className );
    507
    508                    // initialize each service factory
    509                    String s = this.getRequiredInitParameter( serviceNames[i] + HANDLER_CONF );
    510                    URL serviceConfigurationURL = WebappResourceResolver.resolveFileLocation( s, context, LOG );
    511
    512                    // set configuration
    513                    LOG.logInfo( StringTools.concat( 300, "Reading configuration for ", serviceNames[i].toUpperCase(),
    514                                                     " from URL: '", serviceConfigurationURL, "'." ) );
    515
    516                    String factoryClassName = SERVICE_FACTORIES_MAPPINGS.get( handlerClzz );
    517
    518                    Class<?> factory = Class.forName( factoryClassName );
    519                    Method method = factory.getMethod( "setConfiguration", new Class[] { URL.class } );
    520                    method.invoke( factory, new Object[] { serviceConfigurationURL } );
    521
    522                    // The csw-ebrim profile adds an alternative service name, it too is registred with the CSW handler.
    523                    if ( "CSW".equals( serviceNames[i].toUpperCase() ) ) {
    524                        lookup.addService( OGCRequestFactory.CSW_SERVICE_NAME_EBRIM.toUpperCase(), handlerClzz );
    525                    }
    526                    // put handler to available service list
    527                    lookup.addService( serviceNames[i].toUpperCase(), handlerClzz );
    528
    529                    LOG.logInfo( StringTools.concat( 300, serviceNames[i].toUpperCase(), " successfully initialized." ) );
    530                } catch ( ServletException e ) {
    531                    LOG.logError( e.getMessage(), e );
    532                } catch ( InvocationTargetException e ) {
    533                    e.getTargetException().printStackTrace();
    534                    LOG.logError( this.produceMessage( ERR_MSG, new Object[] { serviceNames[i] } ), e );
    535                } catch ( Exception e ) {
    536                    LOG.logError( "Can't initialize OGC service:" + serviceNames[i], e );
    537                }
    538            }
    539        }
    540
    541        private String getRequiredInitParameter( String name )
    542                                throws ServletException {
    543            String paramValue = getInitParameter( name );
    544            if ( paramValue == null ) {
    545
    546                String msg = "Required init parameter '" + name + "' missing in web.xml";
    547                LOG.logError( msg );
    548                throw new ServletException( msg );
    549            }
    550            return paramValue;
    551        }
    552
    553        /**
    554         * @return the services, separated by ","
    555         */
    556        private String getServiceList() {
    557
    558            StringBuffer buf = new StringBuffer();
    559            ServiceLookup lookup = ServiceLookup.getInstance();
    560            for ( Iterator<?> iter = lookup.getIterator(); iter.hasNext(); ) {
    561                String serviceName = (String) iter.next();
    562                buf.append( serviceName );
    563                if ( iter.hasNext() ) {
    564                    buf.append( ',' );
    565                }
    566            }
    567            return buf.toString();
    568        }
    569
    570        /**
    571         * Formats the provided string and the args array into a String using MessageFormat.
    572         *
    573         * @param pattern
    574         * @param args
    575         * @return the message to present the client.
    576         */
    577        private String produceMessage( String pattern, Object[] args ) {
    578            return new MessageFormat( pattern ).format( args );
    579        }
    580
    581        /**
    582         * @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent)
    583         */
    584        public void ctDestroyed() {
    585            LOG.logInfo( "Stopping context: " );
    586
    587            WMSConfigurationDocument.resetCapabilitiesCache();
    588            WMSConfigurationDocument_1_3_0.resetCapabilitiesCache();
    589            WMPSConfigurationDocument.resetCapabilitiesCache();
    590
    591            ServiceLookup lookup = ServiceLookup.getInstance();
    592            for ( Iterator<?> iter = lookup.getIterator(); iter.hasNext(); ) {
    593                String serviceName = (String) iter.next();
    594                LOG.logInfo( "Stopping service " + serviceName );
    595
    596                try {
    597                    String s = SERVICE_FACTORIES_MAPPINGS.get( lookup.getService( serviceName ) );
    598                    Class<?> clzz = Class.forName( s );
    599                    // TODO stop and reset all service instances
    600                    Method[] methods = clzz.getMethods();
    601                    for ( int j = 0; j < methods.length; j++ ) {
    602                        if ( methods[j].getName().equals( "reset" ) ) {
    603                            Object[] args = new Object[0];
    604                            methods[j].invoke( clzz.newInstance(), args );
    605                        }
    606                    }
    607                } catch ( Exception e ) {
    608                    LOG.logError( e.getMessage(), e );
    609                }
    610            }
    611        }
    612
    613        @Override
    614        public void destroy() {
    615            super.destroy();
    616            Enumeration<Driver> e = DriverManager.getDrivers();
    617            while ( e.hasMoreElements() ) {
    618                Driver driver = e.nextElement();
    619                try {
    620                    if ( driver.getClass().getClassLoader() == getClass().getClassLoader() )
    621                        DriverManager.deregisterDriver( driver );
    622                } catch ( SQLException e1 ) {
    623                    LOG.logError( "Cannot unload driver: " + driver );
    624                }
    625            }
    626            LogFactory.releaseAll();
    627            LogManager.shutdown();
    628            // SLF4JLogFactory.releaseAll(); // should be the same as the LogFactory.releaseAll call
    629            Iterator<Class<?>> i = IIORegistry.getDefaultInstance().getCategories();
    630            while ( i.hasNext() ) {
    631                Class<?> c = i.next();
    632                Iterator<?> k = IIORegistry.getDefaultInstance().getServiceProviders( c, false );
    633                while ( k.hasNext() ) {
    634                    Object o = k.next();
    635                    if ( o.getClass().getClassLoader() == getClass().getClassLoader() ) {
    636                        IIORegistry.getDefaultInstance().deregisterServiceProvider( o );
    637                        LOG.logDebug( "Deregistering JAI driver ", o.getClass() );
    638                    }
    639                }
    640            }
    641            Introspector.flushCaches();
    642            // just clear the configurations for now, it does not hurt
    643            CRSConfiguration.DEFINED_CONFIGURATIONS.clear();
    644        }
    645
    646    }