Package org.ow2.easybeans.server.war

Source Code of org.ow2.easybeans.server.war.EasyBeansContextListener

/**
* EasyBeans
* Copyright (C) 2006-2007 Bull S.A.S.
* Contact: easybeans@ow2.org
*
* 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 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
*
* --------------------------------------------------------------------------
* $Id: EasyBeansContextListener.java 5369 2010-02-24 14:58:19Z benoitf $
* --------------------------------------------------------------------------
*/

package org.ow2.easybeans.server.war;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

/**
* Listener class which is notified of lifecycle events. It allows to start
* EasyBeans at startup and stop it at the end.
* @author Florent Benoit
*/
public class EasyBeansContextListener implements ServletContextListener {

    /**
     * Resource containing the list of files.
     */
    private static final String COMMON_LIBRARIES_LIST = "easybeans-exported-libraries.lst";

    /**
     * Default XML file.
     */
    public static final String DEFAULT_XML_FILE = "org/ow2/easybeans/server/war/easybeans-default.xml";

    /**
     * Default Bootstrap class to instantiate.
     */
    public static final String DEFAULT_BOOTSTRAP_CLASS = "org.ow2.easybeans.server.war.EmbeddedBootstrap";

    /**
     * Embedded bootstrap instance.
     */
    private Object embeddedObject = null;

    /**
     * Bootstrap class.
     */
    private Class<?> bootStrapClass;

    /**
     * Container detected ?.
     */
    private ContainerTypeEnum containerType;

    /**
     * Notification that the web application initialization process is starting.
     * All ServletContextListeners are notified of context initialization before
     * any filter or servlet in the web application is initialized.
     * @param servletContextEvent event class for notifications about changes to
     *        the servlet context of a web application.
     */
    public void contextInitialized(final ServletContextEvent servletContextEvent) {

        // Create and configure EasyBeans embedded server
        if (this.embeddedObject == null) {

            // Detects Tomcat/Jetty/etc.
            detectContainerType();

            // Analyze some parameters
            ServletContext ctx = servletContextEvent.getServletContext();
            boolean enableSmartFactory = Boolean.parseBoolean(ctx.getInitParameter("enableSmartFactory"));



            // Register in server some libraries
            registerLibraries(servletContextEvent);

            try {
                // Get class
                this.bootStrapClass = Thread.currentThread().getContextClassLoader().loadClass(getBootstrapClassName());
                this.embeddedObject = this.bootStrapClass.newInstance();

                // Configure container type
                Method setContTypeMethod = this.bootStrapClass.getMethod("setContainerType", ContainerTypeEnum.class);
                setContTypeMethod.invoke(this.embeddedObject, this.containerType);

                // Configure context event
                Method setServletContextEventMethod = this.bootStrapClass.getMethod("setServletContextEvent",
                        ServletContextEvent.class);
                setServletContextEventMethod.invoke(this.embeddedObject, servletContextEvent);

                // Sets the parent directory
                String webContainerDirectory = getWebContainerDirectory();
                System.setProperty("easybeans.home", webContainerDirectory);

                // Use of smart factory
                Method setEnableSmartFactoryMethod = this.bootStrapClass.getMethod("setEnableSmartFactory",
                        boolean.class);
                setEnableSmartFactoryMethod.invoke(this.embeddedObject, Boolean.valueOf(enableSmartFactory));

                // Start
                Method startMethod = this.bootStrapClass.getMethod("start");
                startMethod.invoke(this.embeddedObject);

            } catch (Exception e) {
                e.printStackTrace();
                throw new IllegalStateException("Cannot start", e);
            }

        }
    }

    /**
     * Notification that the servlet context is about to be shut down. All
     * servlets and filters have been destroy()ed before any
     * ServletContextListeners are notified of context destruction.
     * @param servletContextEvent event class for notifications about changes to
     *        the servlet context of a web application.
     */
    public void contextDestroyed(final ServletContextEvent servletContextEvent) {
        if (this.embeddedObject != null) {
            try {
                Method stopMethod = this.bootStrapClass.getMethod("stop");
                stopMethod.invoke(this.embeddedObject);
            } catch (Exception e) {
                throw new IllegalStateException("Cannot stop", e);
            }
        }

        // Run GC
        System.gc();
    }

    /**
     * Detect the web Container type.
     */
    protected void detectContainerType() {
        // catalina base ?
        String catalinaBase = System.getProperty("catalina.base");
        if (catalinaBase != null) {
            // Detect tomcat 5.5 or 6.0
            try {
                EasyBeansContextListener.class.getClassLoader().loadClass("org.apache.AnnotationProcessor");
                // Class present, tomcat6 case
                this.containerType = ContainerTypeEnum.TOMCAT6;
                return;
            } catch (ClassNotFoundException e) {
                // Not found, tomcat5 case
                this.containerType = ContainerTypeEnum.TOMCAT5;
                return;
            }
        }

        // Jetty ?
        String jettyHome = System.getProperty("jetty.home");
        if (jettyHome != null) {
            // Detect Jetty 6 or 7.0
            try {
                EasyBeansContextListener.class.getClassLoader().loadClass("org.eclipse.jetty.webapp.WebAppContext");
                // Class present, Jetty7 case
                this.containerType = ContainerTypeEnum.JETTY7;
                return;
            } catch (ClassNotFoundException e) {
                // Not found, jetty6 case
                this.containerType = ContainerTypeEnum.JETTY6;
                return;
            }
        }

        // not found, return tmp directory
        this.containerType = ContainerTypeEnum.UNKNOWN;
    }

    /**
     * Gets the directory for deployables depending on the servlet container.
     * @return path to catalina.base/jetty.home/etc.
     */
    private String getWebContainerDirectory() {
        // catalina base ?
        String catalinaBase = System.getProperty("catalina.base");
        if (catalinaBase != null) {
            return catalinaBase;
        }

        // Jetty ?
        String jettyHome = System.getProperty("jetty.home");
        if (jettyHome != null) {
            return jettyHome;
        }

        // not found, return tmp directory
        return System.getProperty("java.io.tmpdir");
    }

    /**
     * Register the EasyBeans libraries in the root classloader (allowing each
     * applications to communicate with EasyBeans).
     * @param servletContextEvent event class for notifications about changes to
     *        the servlet context of a web application.
     */
    private void registerLibraries(final ServletContextEvent servletContextEvent) {
        if (this.containerType.equals(ContainerTypeEnum.TOMCAT5) || this.containerType.equals(ContainerTypeEnum.TOMCAT6)) {
            registerTomcat(servletContextEvent);
        } else if (this.containerType.equals(ContainerTypeEnum.JETTY6) || this.containerType.equals(ContainerTypeEnum.JETTY7)) {
            registerJetty(servletContextEvent);
        }
    }

    /**
     * Register the EasyBeans libraries for Jetty.
     * @param servletContextEvent event class for notifications about changes to
     *        the servlet context of a web application.
     */
    protected void registerJetty(final ServletContextEvent servletContextEvent) {
        // Current Classloader
        ClassLoader currentCL = Thread.currentThread().getContextClassLoader();

        // Get parent
        ClassLoader cl = currentCL.getParent();

        // Add libraries
        addLib(cl, servletContextEvent);
    }

    /**
     * Register the EasyBeans libraries for Tomcat.
     * @param servletContextEvent event class for notifications about changes to
     *        the servlet context of a web application.
     */
    protected void registerTomcat(final ServletContextEvent servletContextEvent) {

        // Current Classloader
        ClassLoader currentCL = Thread.currentThread().getContextClassLoader();

        // Now, search shared classloader (child of server CL)
        // Assume that it is a correct Tomcat installation

        // For tomcat 6.x, this is only the direct parent while for Tomcat
        // 5.5.x, it's parent of parent
        ClassLoader cl = currentCL.getParent();
        ClassLoader parent2 = cl.getParent();
        if ("org.apache.catalina.loader.StandardClassLoader".equals(parent2.getClass().getName())) {
            // Tomcat 5.5.x case, gets the parent again
            cl = parent2;
        }
        // Check class :
        if (!"org.apache.catalina.loader.StandardClassLoader".equals(cl.getClass().getName())) {
            throw new IllegalStateException("Didn't find common classloader");
        }

        // Add libraries
        addLib(cl, servletContextEvent);

    }

    /**
     * Add libraries in the given classloader.
     * @param cl the classloader where to add jars (which needs to be an
     *        URLClassLoader)
     * @param servletContextEvent the servlet context event
     */
    protected void addLib(final ClassLoader cl, final ServletContextEvent servletContextEvent) {
        // Get URL ClassLoader
        URLClassLoader urlCl = null;
        if (cl instanceof URLClassLoader) {
            urlCl = (URLClassLoader) cl;
        } else {
            throw new IllegalStateException("Parent classloader is not an URL classloader. Found '" + cl + "'.");
        }

        // Get addURL method
        Method addURL = null;
        try {
            addURL = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] {URL.class});
        } catch (SecurityException e) {
            throw new IllegalArgumentException("Cannot get addURL method on the class '" + URLClassLoader.class + "'.", e);
        } catch (NoSuchMethodException e) {
            throw new IllegalArgumentException("Cannot get addURL method on the class '" + URLClassLoader.class + "'.", e);
        }
        addURL.setAccessible(true);

        // Add libraries
        ServletContext sContext = servletContextEvent.getServletContext();
        List<String> libraries = new ArrayList<String>();
        getLibraries(sContext, libraries);

        for (String library : libraries) {
            URL url = null;
            try {
                url = new File(library).toURI().toURL();
            } catch (Exception e) {
                throw new IllegalArgumentException("Cannot get URL on file '" + library + "'.", e);
            }
            try {
                // logger.debug("Registering '" + url + "'.");
                addURL.invoke(urlCl, url);
            } catch (IllegalArgumentException e) {
                throw new IllegalStateException("Cannot register the URL '" + url + "'.", e);
            } catch (IllegalAccessException e) {
                throw new IllegalStateException("Cannot register the URL '" + url + "'.", e);
            } catch (InvocationTargetException e) {
                throw new IllegalStateException("Cannot register the URL '" + url + "'.", e);
            }
        }
        addURL.setAccessible(false);
    }

    /**
     * Retrieve a List of libraries to be loaded by TopLevel ClassLoaders.
     * @param sContext ServletContext.
     * @param libraries List of libs.
     */
    protected void getLibraries(final ServletContext sContext, final List<String> libraries) {
        // Files that needs to be in the commons classloader are stored in a
        // properties file.

        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

        List<String> librariesList = getExportedLibraries();

        for (String library : librariesList) {

            URL url = classLoader.getResource(library);
            if (url == null) {
                throw new IllegalStateException("No resource named '" + library + "' was found in the current classloader.");
            }

            // got url, open it
            URLConnection urlConnection = null;
            try {
                urlConnection = url.openConnection();
            } catch (IOException e) {
                throw new IllegalStateException("Cannot open connection on the URL '" + url + "'.", e);
            }
            urlConnection.setDefaultUseCaches(false);

            Reader reader = null;
            try {
                try {
                    reader = new InputStreamReader(urlConnection.getInputStream());
                } catch (IOException e) {
                    throw new IllegalStateException("Cannot get inputstream on the URL '" + url + "'.", e);
                }
                BufferedReader bufferedReader = new BufferedReader(reader);
                String fileName = null;
                try {
                    while ((fileName = bufferedReader.readLine()) != null) {
                        fileName = fileName.trim();
                        // only lines with values
                        if (fileName.length() >= 0) {
                            // Get filename
                            libraries.add(sContext.getRealPath("/WEB-INF/lib/" + fileName.trim()));
                        }
                    }
                } catch (IOException e) {
                    throw new IllegalStateException("Cannot read the inputstream on the URL '" + url + "'.", e);
                } finally {
                    if (bufferedReader != null) {
                        try {
                            bufferedReader.close();
                        } catch (IOException e) {
                            throw new IllegalStateException("Cannot close reader object on the URL '" + url + "'.", e);
                        }
                    }
                }
            } finally {
                if (reader != null) {
                    try {
                        reader.close();
                    } catch (IOException e) {
                        throw new IllegalStateException("Cannot close reader object on the URL '" + url + "'.", e);
                    }
                }
            }
        }

    }

    /**
     * @return the bootstrap class name to use.
     */
    protected String getBootstrapClassName() {
        return DEFAULT_BOOTSTRAP_CLASS;
    }

    /**
     * @return a List of resources that contains the libraries to be exported.
     */
    protected List<String> getExportedLibraries() {
        List<String> list = new ArrayList<String>();
        list.add(COMMON_LIBRARIES_LIST);
        return list;
    }

}
TOP

Related Classes of org.ow2.easybeans.server.war.EasyBeansContextListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.