001/*
002 * Copyright 2013 Atteo.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.atteo.moonshine;
017
018import java.io.IOException;
019import java.util.Enumeration;
020import java.util.Properties;
021
022import javax.servlet.ServletContext;
023import javax.servlet.ServletContextEvent;
024import javax.servlet.ServletContextListener;
025
026import org.atteo.evo.filtering.PropertiesPropertyResolver;
027import org.atteo.evo.filtering.PropertyResolver;
028
029import com.google.inject.Injector;
030import com.google.inject.servlet.GuiceServletContextListener;
031
032/**
033 * {@link ServletContextListener} which starts {@link Moonshine} framework.
034 *
035 * <p>
036 * Below is a sample web.xml which shows how to start Moonshine framework.
037 * <pre>
038 * {@code
039 *
040 * <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
041 *  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
042 *  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
043 *     metadata-complete="true">
044 *
045 *  <context-param>
046 *      <!-- Any context param will be available as a ${property} in Moonshine -->
047 *      <param-name>property name</param-name>
048 *      <param-value>property value</param-value>
049 *  </context-param>
050 *
051 *  <listener>
052 *      <listener-class>org.atteo.moonshine.MoonshineServletContextListener</listener-class>
053 *  </listener>
054 *
055 *  <filter>
056 *      <filter-name>guiceFilter</filter-name>
057 *      <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
058 *  </filter>
059 *
060 *  <filter-mapping>
061 *      <filter-name>guiceFilter</filter-name>
062 *      <url-pattern>/*</url-pattern>
063 *  </filter-mapping>
064 * </web-app>
065 * }
066 * </pre>
067 * </p>
068 */
069public class MoonshineServletContextListener extends GuiceServletContextListener {
070    private Moonshine moonshine;
071
072    @Override
073    public void contextInitialized(ServletContextEvent servletContextEvent) {
074        ServletContext servletContext = servletContextEvent.getServletContext();
075        try {
076            Moonshine.Builder builder = Moonshine.Factory.builder();
077
078            configure(builder, servletContext);
079
080            moonshine = builder.build();
081
082            if (moonshine != null) {
083                moonshine.start();
084            }
085        } catch (IOException | MoonshineException e) {
086            throw new RuntimeException(e);
087        }
088        super.contextInitialized(servletContextEvent);
089    }
090
091    /**
092     * Configures {@link Moonshine} using provided builder.
093     * @param builder Moonshine builder
094     * @param servletContext servlet context
095     */
096    protected void configure(Moonshine.Builder builder, ServletContext servletContext) {
097        builder
098                .applicationName(servletContext.getServletContextName())
099                .shutdownHook(false)
100                .addPropertyResolver(retrieveContextParameters(servletContext));
101    }
102
103    @Override
104    public void contextDestroyed(ServletContextEvent servletContextEvent) {
105        super.contextDestroyed(servletContextEvent);
106        if (moonshine != null) {
107            moonshine.close();
108        }
109    }
110
111    @Override
112    protected Injector getInjector() {
113        return moonshine.getGlobalInjector();
114    }
115
116    private static PropertyResolver retrieveContextParameters(ServletContext servletContext) {
117        Properties properties = new Properties();
118        Enumeration<String> initParameterNames = servletContext.getInitParameterNames();
119        while (initParameterNames.hasMoreElements()) {
120            String name = initParameterNames.nextElement();
121
122            properties.put(name, servletContext.getInitParameter(name));
123        }
124
125        return new PropertiesPropertyResolver(properties);
126    }
127}