org.deegree.enterprise.servlet.OGCServletController.java Source code

Java tutorial

Introduction

Here is the source code for org.deegree.enterprise.servlet.OGCServletController.java

Source

//$HeadURL$
// $Id$
/*----------------------------------------------------------------------------
 This file is part of deegree, http://deegree.org/
 Copyright (C) 2001-2009 by:
   Department of Geography, University of Bonn
 and
   lat/lon GmbH
    
 This library is free software; you can redistribute it and/or modify it under
 the terms of the GNU Lesser General Public License as published by the Free
 Software Foundation; either version 2.1 of the License, or (at your option)
 any later version.
 This library is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 details.
 You should have received a copy of the GNU Lesser General Public License
 along with this library; if not, write to the Free Software Foundation, Inc.,
 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    
 Contact information:
    
 lat/lon GmbH
 Aennchenstr. 19, 53177 Bonn
 Germany
 http://lat-lon.de/
    
 Department of Geography, University of Bonn
 Prof. Dr. Klaus Greve
 Postfach 1147, 53001 Bonn
 Germany
 http://www.geographie.uni-bonn.de/deegree/
    
 e-mail: info@deegree.org
----------------------------------------------------------------------------*/

package org.deegree.enterprise.servlet;

import static java.lang.Character.isDigit;
import static java.lang.System.getProperty;
import static java.lang.System.setProperty;
import static org.deegree.enterprise.servlet.ServiceLookup.getInstance;
import static org.deegree.framework.log.LoggerFactory.getLogger;
import static org.deegree.framework.util.StringTools.arrayToString;

import java.beans.Introspector;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.URL;
import java.nio.charset.Charset;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.text.MessageFormat;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.imageio.spi.IIORegistry;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.TransformerFactory;

import org.apache.commons.logging.LogFactory;
import org.apache.log4j.LogManager;
import org.deegree.crs.configuration.CRSConfiguration;
import org.deegree.enterprise.AbstractOGCServlet;
import org.deegree.enterprise.ServiceException;
import org.deegree.framework.log.ILogger;
import org.deegree.framework.util.CharsetUtils;
import org.deegree.framework.util.KVP2Map;
import org.deegree.framework.util.StringTools;
import org.deegree.framework.util.WebappResourceResolver;
import org.deegree.framework.version.Version;
import org.deegree.framework.xml.XMLFragment;
import org.deegree.ogcwebservices.ExceptionReport;
import org.deegree.ogcwebservices.OGCRequestFactory;
import org.deegree.ogcwebservices.OGCWebServiceException;
import org.deegree.ogcwebservices.OGCWebServiceRequest;
import org.deegree.ogcwebservices.wmps.configuration.WMPSConfigurationDocument;
import org.deegree.ogcwebservices.wms.configuration.WMSConfigurationDocument;
import org.deegree.ogcwebservices.wms.configuration.WMSConfigurationDocument_1_3_0;
import org.deegree.owscommon.XMLFactory;
import org.xml.sax.SAXException;

/**
 * An <code>OGCServletController</code> handles all incoming requests. The controller for all OGC service requests.
 * Dispatcher to specific handler for WMS, WFS and other.
 *
 * @author <a href="mailto:tfr@users.sourceforge.net">Torsten Friebe </a>
 * @author last edited by: $Author$
 *
 * @version $Revision$, $Date: 22.04.2008 16:23:34$
 * @see <a href="http://java.sun.com/blueprints/corej2eepatterns/Patterns/FrontController.html">Front controller </a>
 */
public class OGCServletController extends AbstractOGCServlet {

    /**
     * address is the url of the client which requests.
     */
    public static String address = null;

    private static final long serialVersionUID = -4461759017823581221L;

    private static ILogger LOG;

    private static final String SERVICE = "services";

    private static final String HANDLER_CLASS = ".handler";

    private static final String HANDLER_CONF = ".config";

    private static final Map<Class<?>, String> SERVICE_FACTORIES_MAPPINGS = new HashMap<Class<?>, String>();

    private static final String ERR_MSG = "Can't set configuration for {0}";

    /**
     *
     *
     * @param request
     * @param response
     * @TODO refactor and optimize code for initializing handler
     */
    public void doService(HttpServletRequest request, HttpServletResponse response) {
        if (response.isCommitted()) {
            LOG.logWarning("The response object is already committed!");
        }

        long startTime = System.currentTimeMillis();
        address = request.getRequestURL().toString();

        String service = null;
        try {
            OGCWebServiceRequest ogcRequest = OGCRequestFactory.create(request);

            LOG.logInfo(StringTools.concat(500, "Handling request '", ogcRequest.getId(), "' from '",
                    request.getRemoteAddr(), "' to service: '", ogcRequest.getServiceName(), "'"));

            // get service from request
            service = ogcRequest.getServiceName().toUpperCase();

            // get handler instance
            ServiceDispatcher handler = ServiceLookup.getInstance().getHandler(service, request.getRemoteAddr());
            // dispatch request to specific handler
            handler.perform(ogcRequest, response);
        } catch (OGCWebServiceException e) {
            LOG.logError(e.getMessage(), e);
            sendException(response, e, request, service);
        } catch (ServiceException e) {
            if (e.getNestedException() instanceof OGCWebServiceException) {
                sendException(response, (OGCWebServiceException) e.getNestedException(), request, service);
            } else {
                sendException(response, new OGCWebServiceException(this.getClass().getName(), e.getMessage()),
                        request, service);
            }
            LOG.logError(e.getMessage(), e);
        } catch (Exception e) {
            sendException(response, new OGCWebServiceException(this.getClass().getName(), e.getMessage()), request,
                    service);
            LOG.logError(e.getMessage(), e);
        }
        if (LOG.isDebug()) {
            LOG.logDebug("OGCServletController: request performed in "
                    + Long.toString(System.currentTimeMillis() - startTime) + " milliseconds.");
        }
    }

    /**
     * Sends the passed <code>OGCWebServiceException</code> to the calling client.
     *
     * @param response
     * @param e
     * @param request
     * @param service
     *            the service name, if known
     */
    private static void sendException(HttpServletResponse response, OGCWebServiceException e,
            HttpServletRequest request, String service) {
        LOG.logInfo("Sending OGCWebServiceException to client.");

        Map<?, ?> pmap = request.getParameterMap();
        Map<String, String> map = new HashMap<String, String>(pmap.size());
        for (Object o : pmap.keySet()) {
            String[] tmp = (String[]) pmap.get(o);
            for (int i = 0; i < tmp.length; i++) {
                tmp[i] = tmp[i].trim();
            }
            map.put(((String) o).toLowerCase(), arrayToString(tmp, ','));
        }

        boolean isWMS130 = false, isCSW = false, isWCTS = false, isWFS = false, isWFS100 = false;

        if (service == null) {
            service = map.get("service");
        }

        String version = map.get("version");

        if (service != null) {
            if ("wms".equalsIgnoreCase(service)) {
                isWMS130 = version != null && version.equals("1.3.0");
            }
            if ("wfs".equalsIgnoreCase(service)) {
                isWFS = true;
                isWFS100 = version != null && version.equals("1.0.0");
            }

            isCSW = "csw".equalsIgnoreCase(service);
            isWCTS = "wcts".equalsIgnoreCase(service);
            isWFS = "wfs".equalsIgnoreCase(service);
        } else {
            try {
                XMLFragment doc = new XMLFragment(request.getReader(), XMLFragment.DEFAULT_URL);
                service = OGCRequestFactory.getTargetService("", "", doc.getRootElement().getOwnerDocument());
                isCSW = "csw".equalsIgnoreCase(service);
                isWCTS = "wcts".equalsIgnoreCase(service);
                isWFS = "wfs".equalsIgnoreCase(service);
                isWFS100 = isWFS && doc.getRootElement().getAttribute("version") != null
                        && doc.getRootElement().getAttribute("version").equals("1.0.0");
            } catch (SAXException e1) {
                // ignore
            } catch (IOException e1) {
                // ignore
            } catch (IllegalStateException e1) {
                // ignore, that happens in some tomcats
            }
        }

        try {
            XMLFragment doc;
            String contentType = "text/xml";

            if (!(isWMS130 || isCSW || isWCTS || isWFS)) {
                // apply the simplest of heuristics...
                String req = request.getRequestURI().toLowerCase();
                if (req.indexOf("csw") != -1) {
                    isCSW = true;
                } else if (req.indexOf("wcts") != -1) {
                    isWCTS = true;
                } else if (req.indexOf("wfs") != -1) {
                    isWFS = true;
                }

                if (isWFS) {
                    isWFS100 = req.indexOf("1.0.0") != -1;
                }

                if (!(isWMS130 || isCSW || isWCTS || isWFS || isWFS100)) {
                    isWMS130 = version != null && version.equals("1.3.0");
                }
            }

            // send exception format INIMAGE etc. for WMS
            if (service != null && service.equalsIgnoreCase("wms")) {
                ServiceDispatcher handler = getInstance().getHandler(service, request.getRemoteAddr());
                if (handler instanceof WMSHandler) {
                    WMSHandler h = (WMSHandler) handler;
                    String format = map.get("format");
                    String eFormat = map.get("exceptions");
                    try {
                        h.determineExceptionFormat(eFormat, format, version, response);
                        h.writeServiceExceptionReport(e);
                        return;
                    } catch (Exception ex) {
                        LOG.logDebug("Error while sending the exception in special format."
                                + " Continuing in default mode.", ex);
                    }
                }
            }

            if (isWMS130 || "wcs".equalsIgnoreCase(e.getLocator())) {
                doc = XMLFactory.exportNS(new ExceptionReport(new OGCWebServiceException[] { e }));
            } else if (isCSW) {
                doc = XMLFactory.exportExceptionReport(new ExceptionReport(new OGCWebServiceException[] { e }));
            } else if (isWCTS) {
                doc = org.deegree.owscommon_1_1_0.XMLFactory.exportException(e);
            } else if (isWFS100) {
                doc = XMLFactory.exportExceptionReportWFS100(e);
            } else if (isWFS) {
                doc = XMLFactory.exportExceptionReportWFS(e);
            } else {
                contentType = "application/vnd.ogc.se_xml";
                doc = XMLFactory.export(new ExceptionReport(new OGCWebServiceException[] { e }));
            }

            response.setContentType(contentType);
            OutputStream os = response.getOutputStream();
            doc.write(os);
            os.close();
        } catch (Exception ex) {
            LOG.logError("ERROR: " + ex.getMessage(), ex);
        }
    }

    /**
     *
     * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest,
     *      javax.servlet.http.HttpServletResponse)
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        LOG.logDebug("query string ", request.getQueryString());
        if (request.getParameter("RELOADDEEGREE") != null) {
            reloadServices(request, response);
        } else {
            this.doService(request, response);
        }
    }

    /**
     *
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    private void reloadServices(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        Map<?, ?> map = KVP2Map.toMap(request);
        String user = (String) map.get("USER");
        String password = (String) map.get("PASSWORD");
        String message = null;
        if (getInitParameter("USER") != null && getInitParameter("PASSWORD") != null
                && getInitParameter("USER").equals(user) && getInitParameter("PASSWORD").equals(password)) {
            initServices(getServletContext());
            ctDestroyed();
            message = Messages.getString("OGCServletController.reloadsuccess");
        } else {
            message = Messages.getString("OGCServletController.reloadfailed");
        }
        PrintWriter pw = response.getWriter();
        pw.print(message);
        pw.flush();
        pw.close();
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest,
     * javax.servlet.http.HttpServletResponse)
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.doService(request, response);
    }

    private static String spaces(int i) {
        if (i <= 0) {
            return "";
        }

        StringBuffer sb = new StringBuffer(i);
        for (int j = 0; j < i; ++j) {
            sb.append(" ");
        }
        return sb.toString();
    }

    private static void logIfThere(String param) {
        String val = getProperty(param);
        if (val != null) {
            LOG.logInfo("- " + param + spaces(15 - param.length()) + ": " + val);
        }
    }

    /**
     * @see javax.servlet.GenericServlet#init()
     */
    @Override
    public void init() throws ServletException {

        synchronized (OGCServletController.class) {
            if (LOG == null) {
                // hack to figure out and set the context path name
                // for a laugh, see http://marc.info/?l=tomcat-user&m=109215904113904&w=2 and the related thread
                // http://marc.info/?t=109215871400004&r=1&w=2
                String path = getServletContext().getRealPath("");
                String[] ps = path.split("[/\\\\]");
                path = ps[ps.length - 1];
                // heuristics are always a charm (and work best for tomcat in this case)
                if (isDigit(path.charAt(0)) && path.indexOf("-") != -1) {
                    path = path.split("-", 2)[1];
                }
                // note that setting this changes it on a JVM GLOBAL BASIS, so it WILL GET OVERWRITTEN in subsequent
                // deegree startups! (However, since the log4j.properties will only be read on startup, this hack is
                // useful anyway)
                setProperty("context.name", path);

                LOG = getLogger(OGCServletController.class);
            }
        }

        super.init();
        LOG.logDebug("Logger for " + this.getClass().getName() + " initialized.");

        SERVICE_FACTORIES_MAPPINGS.put(CSWHandler.class, "org.deegree.ogcwebservices.csw.CSWFactory");
        SERVICE_FACTORIES_MAPPINGS.put(WFSHandler.class, "org.deegree.ogcwebservices.wfs.WFServiceFactory");
        SERVICE_FACTORIES_MAPPINGS.put(WCSHandler.class, "org.deegree.ogcwebservices.wcs.WCServiceFactory");
        SERVICE_FACTORIES_MAPPINGS.put(WMSHandler.class, "org.deegree.ogcwebservices.wms.WMServiceFactory");
        SERVICE_FACTORIES_MAPPINGS.put(WPVSHandler.class, "org.deegree.ogcwebservices.wpvs.WPVServiceFactory");
        SERVICE_FACTORIES_MAPPINGS.put(WMPSHandler.class, "org.deegree.ogcwebservices.wmps.WMPServiceFactory");
        SERVICE_FACTORIES_MAPPINGS.put(WPSHandler.class, "org.deegree.ogcwebservices.wps.WPServiceFactory");
        SERVICE_FACTORIES_MAPPINGS.put(WASSHandler.class,
                "org.deegree.ogcwebservices.wass.common.WASServiceFactory");
        SERVICE_FACTORIES_MAPPINGS.put(WCTSHandler.class, "org.deegree.ogcwebservices.wcts.WCTServiceFactory");

        LOG.logInfo("-------------------------------------------------------------------------------");
        LOG.logInfo("Starting deegree version " + Version.getVersion());
        LOG.logInfo("- context        : " + this.getServletContext().getServletContextName());
        LOG.logInfo("- real path      : " + this.getServletContext().getRealPath("/"));
        LOG.logInfo("- java version   : " + System.getProperty("java.version") + "");
        LOG.logInfo("- dom builder    : " + DocumentBuilderFactory.newInstance().getClass().getName() + "");
        LOG.logInfo("- xslt builder   : " + TransformerFactory.newInstance().getClass().getName() + "");
        LOG.logInfo("- system charset : " + CharsetUtils.getSystemCharset());
        LOG.logInfo("- default charset: " + Charset.defaultCharset());
        LOG.logInfo("- server info    : " + this.getServletContext().getServerInfo());
        logIfThere("proxyHost");
        logIfThere("proxyPort");
        logIfThere("noProxyHosts");
        logIfThere("nonProxyHosts");
        logIfThere("http.proxyHost");
        logIfThere("http.proxyPort");
        logIfThere("http.noProxyHosts");
        logIfThere("http.nonProxyHosts");
        logIfThere("ftp.proxyHost");
        logIfThere("ftp.proxyPort");
        logIfThere("ftp.noProxyHosts");
        logIfThere("ftp.nonProxyHosts");
        logIfThere("https.proxyHost");
        logIfThere("https.proxyPort");
        logIfThere("https.noProxyHosts");
        logIfThere("https.nonProxyHosts");
        try {
            LOG.logInfo("- ip             : " + InetAddress.getLocalHost().getHostAddress());
            LOG.logInfo("- host name      : " + InetAddress.getLocalHost().getHostName());
            LOG.logInfo("- domain name    : " + InetAddress.getLocalHost().getCanonicalHostName());
        } catch (Exception e) {
            LOG.logError(e.getMessage(), e);
        }
        LOG.logInfo("-------------------------------------------------------------------------------");
        this.initServices(getServletContext());
        checkServerCompatibility();
        LOG.logInfo("-------------------------------------------------------------------------------");
        String tmpServiceList = this.getServiceList();
        if (tmpServiceList != null && !("".equals(tmpServiceList.trim()))) {
            LOG.logInfo("Initialized successfully (context '" + this.getServletContext().getServletContextName()
                    + "'):");
            String[] tmpServices = tmpServiceList.split(",");
            for (String service : tmpServices) {
                // Added a check for the alternative service name, because it should not be outputed twice for the csw.
                if (!OGCRequestFactory.CSW_SERVICE_NAME_EBRIM.toUpperCase().equals(service)) {
                    LOG.logInfo("- " + service);
                }
            }
        } else {
            LOG.logError("An Error occured while initializing context '"
                    + this.getServletContext().getServletContextName() + "', no services are available.");
        }

        LOG.logInfo("-------------------------------------------------------------------------------");
        // Sets the attributes for tomcat -> application.getAttribute(); in jsp sites
        this.getServletContext().setAttribute("deegree_ogc_services", this.getServiceList());
    }

    private void checkServerCompatibility() {
        String serverInfo = getServletContext().getServerInfo();
        if ("Apache Tomcat/5.5.26".equals(serverInfo) || "Apache Tomcat/6.0.16".equals(serverInfo)) {
            LOG.logWarning("*******************************************************************************");
            LOG.logWarning("YOU ARE RUNNING DEEGREE ON A TOMCAT RELEASE (" + serverInfo
                    + ") THAT IS KNOWN TO HAVE A SERIOUS ISSUE WITH LARGE POST REQUESTS.");
            LOG.logWarning(
                    "PLEASE CONSIDER THE CORRESPONDING DEEGREE WIKI PAGE AT  https://wiki.deegree.org/deegreeWiki/ApacheTomcat "
                            + "FOR DETAILS AND SWITCH TO A DIFFERENT TOMCAT VERSION.");
            LOG.logWarning("*******************************************************************************");
        }
    }

    private void initServices(ServletContext context) throws ServletException {

        // get list of OGC services
        String serviceList = this.getRequiredInitParameter(SERVICE);

        String[] serviceNames = StringTools.toArray(serviceList, ",", false);

        ServiceLookup lookup = ServiceLookup.getInstance();
        for (int i = 0; i < serviceNames.length; i++) {
            LOG.logInfo(StringTools.concat(100, "---- Initializing ", serviceNames[i].toUpperCase(), " ----"));
            try {
                String className = this.getRequiredInitParameter(serviceNames[i] + HANDLER_CLASS);
                Class<?> handlerClzz = Class.forName(className);

                // initialize each service factory
                String s = this.getRequiredInitParameter(serviceNames[i] + HANDLER_CONF);
                URL serviceConfigurationURL = WebappResourceResolver.resolveFileLocation(s, context, LOG);

                // set configuration
                LOG.logInfo(StringTools.concat(300, "Reading configuration for ", serviceNames[i].toUpperCase(),
                        " from URL: '", serviceConfigurationURL, "'."));

                String factoryClassName = SERVICE_FACTORIES_MAPPINGS.get(handlerClzz);

                Class<?> factory = Class.forName(factoryClassName);
                Method method = factory.getMethod("setConfiguration", new Class[] { URL.class });
                method.invoke(factory, new Object[] { serviceConfigurationURL });

                // The csw-ebrim profile adds an alternative service name, it too is registred with the CSW handler.
                if ("CSW".equals(serviceNames[i].toUpperCase())) {
                    lookup.addService(OGCRequestFactory.CSW_SERVICE_NAME_EBRIM.toUpperCase(), handlerClzz);
                }
                // put handler to available service list
                lookup.addService(serviceNames[i].toUpperCase(), handlerClzz);

                LOG.logInfo(StringTools.concat(300, serviceNames[i].toUpperCase(), " successfully initialized."));
            } catch (ServletException e) {
                LOG.logError(e.getMessage(), e);
            } catch (InvocationTargetException e) {
                e.getTargetException().printStackTrace();
                LOG.logError(this.produceMessage(ERR_MSG, new Object[] { serviceNames[i] }), e);
            } catch (Exception e) {
                LOG.logError("Can't initialize OGC service:" + serviceNames[i], e);
            }
        }
    }

    private String getRequiredInitParameter(String name) throws ServletException {
        String paramValue = getInitParameter(name);
        if (paramValue == null) {

            String msg = "Required init parameter '" + name + "' missing in web.xml";
            LOG.logError(msg);
            throw new ServletException(msg);
        }
        return paramValue;
    }

    /**
     * @return the services, separated by ","
     */
    private String getServiceList() {

        StringBuffer buf = new StringBuffer();
        ServiceLookup lookup = ServiceLookup.getInstance();
        for (Iterator<?> iter = lookup.getIterator(); iter.hasNext();) {
            String serviceName = (String) iter.next();
            buf.append(serviceName);
            if (iter.hasNext()) {
                buf.append(',');
            }
        }
        return buf.toString();
    }

    /**
     * Formats the provided string and the args array into a String using MessageFormat.
     *
     * @param pattern
     * @param args
     * @return the message to present the client.
     */
    private String produceMessage(String pattern, Object[] args) {
        return new MessageFormat(pattern).format(args);
    }

    /**
     * @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent)
     */
    public void ctDestroyed() {
        LOG.logInfo("Stopping context: ");

        WMSConfigurationDocument.resetCapabilitiesCache();
        WMSConfigurationDocument_1_3_0.resetCapabilitiesCache();
        WMPSConfigurationDocument.resetCapabilitiesCache();

        ServiceLookup lookup = ServiceLookup.getInstance();
        for (Iterator<?> iter = lookup.getIterator(); iter.hasNext();) {
            String serviceName = (String) iter.next();
            LOG.logInfo("Stopping service " + serviceName);

            try {
                String s = SERVICE_FACTORIES_MAPPINGS.get(lookup.getService(serviceName));
                Class<?> clzz = Class.forName(s);
                // TODO stop and reset all service instances
                Method[] methods = clzz.getMethods();
                for (int j = 0; j < methods.length; j++) {
                    if (methods[j].getName().equals("reset")) {
                        Object[] args = new Object[0];
                        methods[j].invoke(clzz.newInstance(), args);
                    }
                }
            } catch (Exception e) {
                LOG.logError(e.getMessage(), e);
            }
        }
    }

    @Override
    public void destroy() {
        super.destroy();
        Enumeration<Driver> e = DriverManager.getDrivers();
        while (e.hasMoreElements()) {
            Driver driver = e.nextElement();
            try {
                if (driver.getClass().getClassLoader() == getClass().getClassLoader())
                    DriverManager.deregisterDriver(driver);
            } catch (SQLException e1) {
                LOG.logError("Cannot unload driver: " + driver);
            }
        }
        LogFactory.releaseAll();
        LogManager.shutdown();
        // SLF4JLogFactory.releaseAll(); // should be the same as the LogFactory.releaseAll call
        Iterator<Class<?>> i = IIORegistry.getDefaultInstance().getCategories();
        while (i.hasNext()) {
            Class<?> c = i.next();
            Iterator<?> k = IIORegistry.getDefaultInstance().getServiceProviders(c, false);
            while (k.hasNext()) {
                Object o = k.next();
                if (o.getClass().getClassLoader() == getClass().getClassLoader()) {
                    IIORegistry.getDefaultInstance().deregisterServiceProvider(o);
                    LOG.logDebug("Deregistering JAI driver ", o.getClass());
                }
            }
        }
        Introspector.flushCaches();
        // just clear the configurations for now, it does not hurt
        CRSConfiguration.DEFINED_CONFIGURATIONS.clear();
    }

}