FactoryInitServlet.java :  » J2EE » Pustefix » de » schlund » pfixxml » Java Open Source

Java Open Source » J2EE » Pustefix 
Pustefix » de » schlund » pfixxml » FactoryInitServlet.java
/*
 * This file is part of PFIXCORE.
 *
 * PFIXCORE 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 of the License, or
 * (at your option) any later version.
 *
 * PFIXCORE 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 PFIXCORE; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
package de.schlund.pfixxml;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.log4j.Logger;
import org.apache.log4j.xml.DOMConfigurator;
import org.w3c.dom.Document;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;

import de.schlund.pfixxml.config.CustomizationHandler;
import de.schlund.pfixxml.config.GlobalConfigurator;
import de.schlund.pfixxml.config.XMLPropertiesUtil;
import de.schlund.pfixxml.resources.FileResource;
import de.schlund.pfixxml.resources.ResourceUtil;
import de.schlund.pfixxml.util.TransformerHandlerAdapter;
import de.schlund.pfixxml.util.logging.ProxyLogUtil;

/**
 * This Servlet is just there to have it's init method called on startup of the
 * VM. It starts all VM-global factories by calling their 'init' method from the
 * {@link FactoryInit} interface. These factories are located by analyzing the
 * "servlet.propfile" parameter which points to a file where all factories are
 * listed.
 */
public class FactoryInitServlet extends HttpServlet {

    // ~ Instance/static variables
    // ..................................................................
    public final static String PROP_DOCROOT = "pustefix.docroot";

    private final static String PROP_LOG4J = "pustefix.log4j.config";

    private final static String PROP_PREFER_CONTAINER_LOGGING = "pustefix.logging.prefercontainer";

    private Object LOCK = new Object();

    private final static Logger LOG = Logger.getLogger(FactoryInitServlet.class);

    private static boolean configured = false;
    
    private static FactoryInitException initException;

    private static String log4jconfig = null;

    private static long log4jmtime = -1;
    
    private boolean warMode = false;
    private boolean standaloneMode = false;

    // ~ Methods
    // ....................................................................................

    /**
     * Handle the HTTP-Post method.
     * 
     * @see javax.servlet.http.HttpServlet#doPost(HttpServletRequest,
     *      HttpServletResponse)
     * @throws ServletException
     *             on all
     */
    public void doPost(HttpServletRequest req, HttpServletResponse res)
            throws ServletException {
        doGet(req, res);
    }

    /**
     * Handle the HTTP-Get method
     * 
     * @see javax.servlet.http.HttpServlet#doGet(HttpServletRequest,
     *      HttpServletResponse)
     * @throws ServletException
     *             on call
     */
    public void doGet(HttpServletRequest req, HttpServletResponse res)
            throws ServletException {
        throw new ServletException("This servlet can't be called interactively");
    }

    public static void tryReloadLog4j() {
        if (log4jconfig != null) {
            FileResource l4jfile = ResourceUtil.getFileResourceFromDocroot(log4jconfig);
            long tmpmtime = l4jfile.lastModified();
            if (tmpmtime > log4jmtime) {
                LOG.error("\n\n################################\n"
                        + "#### Reloading log4j config ####\n"
                        + "################################\n");
                try {
                    configureLog4j(l4jfile);
                } catch (FileNotFoundException e) {
                    Logger.getLogger(FactoryInitServlet.class).error(
                            "Reloading log4j config failed!", e);
                } catch (SAXException e) {
                    Logger.getLogger(FactoryInitServlet.class).error(
                            "Reloading log4j config failed!", e);
                } catch (IOException e) {
                    Logger.getLogger(FactoryInitServlet.class).error(
                            "Reloading log4j config failed!", e);
                }
                log4jmtime = tmpmtime;
            }
        }
    }

    /**
     * Initialize this servlet. Also call the 'init' method of all classes
     * listed in the configuration. These classes must implement the FactoryInit
     * interface.
     * 
     * @param config
     *            the servlet configuration
     * @see javax.servlet.Servlet#init(ServletConfig)
     * @throws ServletException
     *             on errors
     */
    @SuppressWarnings("deprecation")
    public void init(ServletConfig Config) throws ServletException {
        super.init(Config);
        Properties properties = new Properties(System.getProperties());
        // old webapps specify docroot -- true webapps don't
        String docrootstr = Config.getInitParameter(PROP_DOCROOT);
        if (docrootstr != null && !docrootstr.equals("")) {
            standaloneMode = true;
        } else {
            docrootstr = Config.getServletContext().getRealPath("/WEB-INF/pfixroot");
            if (docrootstr == null) {
                warMode = true;
            }
        }

        // Setup global configuration before doing anything else
        if (docrootstr != null) {
            GlobalConfigurator.setDocroot(docrootstr);
        }
        if (warMode) {
            GlobalConfigurator.setServletContext(getServletContext());
        }
        
        if (docrootstr != null) {
            // For compatibility with old apps, initialize PathFactory
            PathFactory.getInstance().init(docrootstr);
        }

        String confname = Config.getInitParameter("servlet.propfile");
        if (confname != null) {
            FileResource confFile = ResourceUtil.getFileResourceFromDocroot(confname);
            try {
                XMLPropertiesUtil.loadPropertiesFromXMLFile(confFile, properties);
            } catch (FileNotFoundException e) {
                throw new ServletException("*** [" + confname + "] Not found: "
                        + e.toString());
            } catch (IOException e) {
                throw new ServletException("*** [" + confname + "] IO-error: "
                        + e.toString());
            } catch (SAXException e) {
                throw new ServletException("*** [" + confname + "] Parsing-error: "
                        + e.toString());
            }
        } else {
            throw new ServletException(
                    "*** FATAL: Need the servlet.propfile property as init parameter! ***");
        }
        
        if (docrootstr != null) {
            // this is for stuff that can't use the PathFactory. Should not be used
            // when possible...
            properties.setProperty("pustefix.docroot", docrootstr);
        }

        synchronized (LOCK) {
            if (!configured) {
                configureLogging(properties);
                LOG.debug(">>>> LOG4J Init OK <<<<");

                try {
                    FactoryInitUtil.initialize(properties);
                } catch (FactoryInitException e) {
                    throw new ServletException(e.getCause().toString());
                }
            }
            configured = true;
            LOG.debug("***** INIT of FactoryInitServlet done *****");

        }
    }

    private void configureLogging(Properties properties) throws ServletException {
        String containerProp = properties.getProperty(PROP_PREFER_CONTAINER_LOGGING);
        if (warMode || (!standaloneMode && (containerProp != null && containerProp.toLowerCase().equals("true")))) {
            ProxyLogUtil.getInstance().configureLog4jProxy();
            ProxyLogUtil.getInstance().setServletContext(getServletContext());
        } else {
            log4jconfig = properties.getProperty(PROP_LOG4J);
            if (log4jconfig == null || log4jconfig.equals("")) {
                throw new ServletException("*** FATAL: Need the pustefix.log4j.config property in factory.xml! ***");
            }
            FileResource l4jfile = ResourceUtil.getFileResourceFromDocroot(log4jconfig);
            try {
                configureLog4j(l4jfile);
            } catch (FileNotFoundException e) {
                throw new ServletException("File for log4j configuration not found!", e);
            } catch (SAXException e) {
                throw new ServletException("Error on parsing log4j configuration file!", e);
            } catch (IOException e) {
                throw new ServletException("Error on reading log4j configuration file!", e);
            }

        }
    }

    private static void configureLog4j(FileResource configFile) throws SAXException, FileNotFoundException, IOException {
        log4jmtime = configFile.lastModified();
        XMLReader xreader = XMLReaderFactory.createXMLReader();
        TransformerFactory tf = TransformerFactory.newInstance();
        if (tf.getFeature(SAXTransformerFactory.FEATURE)) {
            SAXTransformerFactory stf = (SAXTransformerFactory) tf;
            TransformerHandler th;
            try {
                th = stf.newTransformerHandler();
            } catch (TransformerConfigurationException e) {
                throw new RuntimeException(
                        "Failed to configure TransformerFactory!", e);
            }
            DOMResult dr = new DOMResult();
            th.setResult(dr);
            DefaultHandler dh = new TransformerHandlerAdapter(th);
            DefaultHandler cushandler = new CustomizationHandler(dh);
            xreader.setContentHandler(cushandler);
            xreader.setDTDHandler(cushandler);
            xreader.setErrorHandler(cushandler);
            xreader.setEntityResolver(cushandler);
            xreader.parse(new InputSource(configFile.getInputStream()));
            ByteArrayOutputStream bufferStream = new ByteArrayOutputStream();
            try {
                tf
                        .newTransformer(
                                new StreamSource(
                                        ResourceUtil.getFileResourceFromDocroot("core/build/create_log4j_config.xsl").toURL()
                                        .toString())).transform(
                                new DOMSource(dr.getNode()), new StreamResult(bufferStream));
            } catch (TransformerException e) {
                throw new SAXException(e);
            }
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setValidating(true);
            dbf.setNamespaceAware(true);
            Document confDoc;
            try {
                DocumentBuilder db = dbf.newDocumentBuilder();
                db.setEntityResolver(new EntityResolver() {

                    public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
                        if (systemId.equals("http://logging.apache.org/log4j/docs/api/org/apache/log4j/xml/log4j.dtd")) {
                            return new InputSource(ResourceUtil.getFileResourceFromDocroot("core/schema/log4j.dtd").getInputStream());
                        }
                        return null;
                    }
                    
                });
                db.setErrorHandler(new ErrorHandler() {

                    public void warning(SAXParseException exception) throws SAXException {
                        System.err.println("Warning while parsing log4j configuration: ");
                        exception.printStackTrace(System.err);
                    }

                    public void error(SAXParseException exception) throws SAXException {
                        System.err.println("Error while parsing log4j configuration: ");
                        exception.printStackTrace(System.err);
                    }

                    public void fatalError(SAXParseException exception) throws SAXException {
                        System.err.println("Fatal error while parsing log4j configuration: ");
                        exception.printStackTrace(System.err);                    }
                    
                });
                confDoc = db.parse(new ByteArrayInputStream(bufferStream.toByteArray()));
            } catch (SAXException e) {
                throw e;
            } catch (IOException e) {
                throw e;
            } catch (ParserConfigurationException e) {
                String msg = "Error while trying to create DOM document";
                throw new RuntimeException(msg, e);
            }
            DOMConfigurator.configure(confDoc.getDocumentElement());
        } else {
            throw new RuntimeException(
                    "Could not get instance of SAXTransformerFactory!");
        }
    }

    public static boolean isConfigured() {
        return configured;
    }

    public static FactoryInitException getInitException() {
        return initException;
    }

}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.