/*
* Constellation - An open source and standard compliant SDI
* http://www.constellation-sdi.org
*
* Copyright 2014 Geomatys.
*
* 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.
*/
package org.constellation.admin.conf;
import org.constellation.admin.web.filter.CachingHttpHeadersFilter;
import org.constellation.admin.web.filter.StaticResourcesProductionFilter;
import org.constellation.admin.web.filter.gzip.GZipServletFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.Environment;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AbstractRefreshableWebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.DispatcherServlet;
import javax.servlet.DispatcherType;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRegistration;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
/**
* Configuration of web application with Servlet 3.0 APIs.
*/
public class WebConfigurer implements ServletContextListener {
private final Logger log = LoggerFactory.getLogger(WebConfigurer.class);
@Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext servletContext = sce.getServletContext();
log.info("Web application configuration");
log.debug("Configuring Spring root application context");
Object rootContextObject = WebApplicationContextUtils.getWebApplicationContext(servletContext);
AbstractRefreshableWebApplicationContext rootContext;
if(rootContextObject==null) {
AnnotationConfigWebApplicationContext annotationRootContext = new AnnotationConfigWebApplicationContext();
annotationRootContext.register(ApplicationConfiguration.class);
annotationRootContext.refresh();
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, annotationRootContext);
rootContext = annotationRootContext;
} else {
if (rootContextObject instanceof AbstractRefreshableWebApplicationContext) {
rootContext = (AbstractRefreshableWebApplicationContext) rootContextObject;
} else {
throw new IllegalStateException("Root web application context not an instance " +
"of AbstractRefreshableWebApplicationContext"+ rootContextObject);
}
}
EnumSet<DispatcherType> disps = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.ASYNC);
initSpring(servletContext, rootContext);
// initSpringSecurity(servletContext, disps);
if (WebApplicationContextUtils
.getRequiredWebApplicationContext(servletContext)
.getBean(Environment.class)
.acceptsProfiles(Constants.SPRING_PROFILE_PRODUCTION)) {
initStaticResourcesProductionFilter(servletContext, disps);
initCachingHttpHeadersFilter(servletContext, disps);
}
initGzipFilter(servletContext, disps);
log.debug("Web application fully configured");
}
/**
* Initializes the GZip filter.
*/
private void initGzipFilter(ServletContext servletContext, EnumSet<DispatcherType> disps) {
log.debug("Registering GZip Filter");
FilterRegistration.Dynamic compressingFilter = servletContext.addFilter("gzipFilter", new GZipServletFilter());
Map<String, String> parameters = new HashMap<String, String>();
compressingFilter.setInitParameters(parameters);
compressingFilter.addMappingForUrlPatterns(disps, true, "*.css");
compressingFilter.addMappingForUrlPatterns(disps, true, "*.json");
compressingFilter.addMappingForUrlPatterns(disps, true, "*.html");
compressingFilter.addMappingForUrlPatterns(disps, true, "*.js");
compressingFilter.addMappingForUrlPatterns(disps, true, "*.svg");
//@TODO add gzip filter for cstl-services war and cstl-sdi
//compressingFilter.addMappingForUrlPatterns(disps, true, "/app/rest/*");
//compressingFilter.addMappingForUrlPatterns(disps, true, "/metrics/*");
compressingFilter.setAsyncSupported(true);
}
/**
* Initializes the static resources production Filter.
*/
private void initStaticResourcesProductionFilter(ServletContext servletContext,
EnumSet<DispatcherType> disps) {
log.debug("Registering static resources production Filter");
FilterRegistration.Dynamic staticResourcesProductionFilter =
servletContext.addFilter("staticResourcesProductionFilter",
new StaticResourcesProductionFilter());
staticResourcesProductionFilter.addMappingForUrlPatterns(disps, true, "/");
staticResourcesProductionFilter.addMappingForUrlPatterns(disps, true, "/index.html");
staticResourcesProductionFilter.addMappingForUrlPatterns(disps, true, "/img/*");
staticResourcesProductionFilter.addMappingForUrlPatterns(disps, true, "/fonts/*");
staticResourcesProductionFilter.addMappingForUrlPatterns(disps, true, "/js/*");
staticResourcesProductionFilter.addMappingForUrlPatterns(disps, true, "/css/*");
staticResourcesProductionFilter.addMappingForUrlPatterns(disps, true, "/views/*");
staticResourcesProductionFilter.setAsyncSupported(true);
}
/**
* Initializes the cachig HTTP Headers Filter.
*/
private void initCachingHttpHeadersFilter(ServletContext servletContext,
EnumSet<DispatcherType> disps) {
log.debug("Registering Cachig HTTP Headers Filter");
FilterRegistration.Dynamic cachingHttpHeadersFilter =
servletContext.addFilter("cachingHttpHeadersFilter",
new CachingHttpHeadersFilter());
cachingHttpHeadersFilter.addMappingForUrlPatterns(disps, true, "/dist/img/*");
cachingHttpHeadersFilter.addMappingForUrlPatterns(disps, true, "/dist/fonts/*");
cachingHttpHeadersFilter.addMappingForUrlPatterns(disps, true, "/dist/js/*");
cachingHttpHeadersFilter.addMappingForUrlPatterns(disps, true, "/dist/css/*");
cachingHttpHeadersFilter.setAsyncSupported(true);
}
/**
* Initializes Spring and Spring MVC.
*/
private ServletRegistration.Dynamic initSpring(ServletContext servletContext, AbstractRefreshableWebApplicationContext rootContext) {
log.debug("Configuring Spring Web application context");
AnnotationConfigWebApplicationContext dispatcherServletConfiguration = new AnnotationConfigWebApplicationContext();
dispatcherServletConfiguration.setParent(rootContext);
dispatcherServletConfiguration.register(DispatcherServletConfiguration.class);
log.debug("Registering Spring MVC Servlet");
ServletRegistration.Dynamic dispatcherServlet = servletContext.addServlet("dispatcher", new DispatcherServlet(
dispatcherServletConfiguration));
dispatcherServlet.addMapping("/app/*");
dispatcherServlet.setLoadOnStartup(1);
dispatcherServlet.setAsyncSupported(true);
return dispatcherServlet;
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
log.info("Destroying Web application");
WebApplicationContext ac = WebApplicationContextUtils.getRequiredWebApplicationContext(sce.getServletContext());
AbstractRefreshableWebApplicationContext gwac = (AbstractRefreshableWebApplicationContext) ac;
gwac.close();
log.debug("Web application destroyed");
}
}