package org.ff4j.web; import static org.ff4j.web.bean.WebConstants.CSS_SESSIONATTRIBUTE_NAME; import static org.ff4j.web.bean.WebConstants.FF4J_SESSIONATTRIBUTE_NAME; import static org.ff4j.web.bean.WebConstants.SERVLETPARAM_CSS; import static org.ff4j.web.bean.WebConstants.SERVLETPARAM_FF4JPROVIDER; import java.util.HashMap; import java.util.Map; /* * #%L * ff4j-web * %% * Copyright (C) 2013 - 2015 Ff4J * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import org.ff4j.FF4j; import org.ff4j.web.controller.AbstractController; import org.ff4j.web.controller.AuditController; import org.ff4j.web.controller.FeatureUsageController; import org.ff4j.web.controller.FeaturesController; import org.ff4j.web.controller.HomeController; import org.ff4j.web.controller.InfosController; import org.ff4j.web.controller.NotFoundController; import org.ff4j.web.controller.OperationsController; import org.ff4j.web.controller.PropertiesController; import org.ff4j.web.controller.SettingsController; import org.ff4j.web.controller.StaticResourceController; import org.ff4j.web.controller.TimeSeriesController; import org.ff4j.web.thymeleaf.CustomMessageResolver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.thymeleaf.TemplateEngine; import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver; /** * Servlet initialisation to put FF4J in HTTP Session. * * @author <a href="mailto:cedrick.lunven@gmail.com">Cedrick LUNVEN</a> */ public class FF4jServlet extends HttpServlet { /** Serial. */ private static final long serialVersionUID = 8447941463286918975L; /** Logger for this class. */ public static final Logger LOGGER = LoggerFactory.getLogger(FF4jServlet.class); /** instance of ff4j. */ protected FF4j ff4j = null; /** initializing ff4j provider. */ protected FF4jProvider ff4jProvider = null; /** Template engine. */ protected TemplateEngine templateEngine = null; /** Static resource controller. */ protected StaticResourceController staticResourceController; /** Simple Operation. */ protected OperationsController operationsController; /** Mapping PATH <=> Controller */ protected static Map < String , AbstractController > mapOfControllers = new HashMap<String , AbstractController>(); /** * Servlet initialization, init FF4J from "ff4jProvider" attribute Name. * * @param servletConfig * current {@link ServletConfig} context * @throws ServletException * error during servlet initialization */ public void init(ServletConfig servletConfig) throws ServletException { LOGGER.info(" __ __ _ _ _ "); LOGGER.info(" / _|/ _| || | (_)"); LOGGER.info("| |_| |_| || |_| |"); LOGGER.info("| _| _|__ _| |"); LOGGER.info("|_| |_| |_|_/ |"); LOGGER.info(" |__/ v" + getClass().getPackage().getImplementationVersion()); LOGGER.info(" "); if (ff4j == null) { initializeFF4J(servletConfig); } initializeTemplateEngine(); staticResourceController = new StaticResourceController(ff4j, templateEngine); operationsController = new OperationsController(ff4j, templateEngine); addController(new HomeController(ff4j, templateEngine)); addController(new InfosController(ff4j, templateEngine)); addController(new FeaturesController(ff4j, templateEngine)); addController(new PropertiesController(ff4j, templateEngine)); addController(new SettingsController(ff4j, templateEngine)); addController(new NotFoundController(ff4j, templateEngine)); addController(new AuditController(ff4j, templateEngine)); addController(new FeatureUsageController(ff4j, templateEngine)); addController(new TimeSeriesController(ff4j, templateEngine)); } /** * Syntaxic to add controller to map. * * @param ac * current controller */ private void addController(AbstractController ac) { mapOfControllers.put(ac.getSuccessView(), ac); } /** * Initialize FF4J configuration. * * @param servletConfig * current servlet configuration */ private void initializeFF4J(ServletConfig servletConfig) { String className = servletConfig.getInitParameter(SERVLETPARAM_FF4JPROVIDER); try { Class<?> c = Class.forName(className); Object o = c.newInstance(); ff4jProvider = (FF4jProvider) o; LOGGER.info("ff4j context has been successfully initialized - {} feature(s)", ff4jProvider.getFF4j().getFeatures().size()); } catch (ClassNotFoundException e) { throw new IllegalArgumentException("Cannot load ff4jProvider as " + ff4jProvider, e); } catch (InstantiationException e) { throw new IllegalArgumentException("Cannot instantiate " + ff4jProvider + " as ff4jProvider", e); } catch (IllegalAccessException e) { throw new IllegalArgumentException("No public constructor for " + ff4jProvider + " as ff4jProvider", e); } catch (ClassCastException ce) { throw new IllegalArgumentException("ff4jProvider expected instance of " + FF4jProvider.class, ce); } ff4j = ff4jProvider.getFF4j(); servletConfig.getServletContext().setAttribute(FF4J_SESSIONATTRIBUTE_NAME, ff4j); LOGGER.debug("Servlet has been initialized and ff4j store in session with {} ", ff4j.getFeatures().size()); String cssFile = servletConfig.getInitParameter(SERVLETPARAM_CSS); if (cssFile != null) { LOGGER.debug("A custom CSS has been defined [" + cssFile + "]"); servletConfig.getServletContext().setAttribute(CSS_SESSIONATTRIBUTE_NAME, cssFile); } } /** * Initialize Thymeleaf. */ private void initializeTemplateEngine() { ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver(); templateResolver.setTemplateMode("XHTML"); templateResolver.setPrefix("views/view-"); templateResolver.setSuffix(".html"); templateResolver.setCacheTTLMs(3600000L); templateEngine = new TemplateEngine(); templateEngine.setTemplateResolver(templateResolver); templateEngine.addMessageResolver(new CustomMessageResolver()); LOGGER.info("Thymeleaf has been initialized"); } /** * Getter accessor for attribute 'ff4j'. * * @return current value of 'ff4j' */ public FF4j getFf4j() { if (ff4j == null) { throw new IllegalStateException("Console Servlet has not been initialized, please set 'load-at-startup' to 1"); } return ff4j; } /** * Setter accessor for attribute 'ff4j'. * @param ff4j * new value for 'ff4j ' */ public void setFf4j(FF4j ff4j) { this.ff4j = ff4j; } }