package nl.ipo.cds.admin.config; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.Map; import java.util.Properties; import javax.inject.Inject; import javax.servlet.ServletContext; import nl.idgis.commons.mvc.config.annotation.EnableJSONViewResolver; import nl.idgis.commons.mvc.config.annotation.EnableVelocityViewResolver; import nl.idgis.commons.mvc.config.annotation.VelocityViewConfiguration; import nl.ipo.cds.admin.BaseConfiguration; import nl.ipo.cds.admin.ba.ViewContextHandlerInterceptorAdapter; import nl.ipo.cds.admin.i18n.EnableI18N; import nl.ipo.cds.admin.i18n.LocaleProvider; import nl.ipo.cds.admin.i18n.SpringLocaleProvider; import nl.ipo.cds.admin.i18n.VelocityAdapter; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.context.support.ReloadableResourceBundleMessageSource; import org.springframework.stereotype.Controller; import org.springframework.ui.context.support.ResourceBundleThemeSource; import org.springframework.web.context.ServletContextAware; import org.springframework.web.multipart.commons.CommonsMultipartResolver; import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver; import org.springframework.web.servlet.i18n.CookieLocaleResolver; import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; import org.springframework.web.servlet.mvc.WebContentInterceptor; import org.springframework.web.servlet.theme.FixedThemeResolver; @Configuration @EnableWebMvc @EnableI18N (basePackage = "nl.ipo.cds.admin.i18n.messages") @EnableJSONViewResolver (prefixJson = true) @EnableVelocityViewResolver (cache = true, layoutUrl = "layouts/baLayout.vm", reloadVelocityMacroLibrary = true, resourceLoaderPath = "/WEB-INF/views/", velocityMacroLibrary = "velocity-macros.vm") @ComponentScan (useDefaultFilters = false, basePackageClasses = nl.ipo.cds.admin.ba.controller.Package.class, includeFilters = { @ComponentScan.Filter (type = FilterType.ANNOTATION, value = Controller.class) }) public class AdminWebMvcConfig extends WebMvcConfigurerAdapter implements VelocityViewConfiguration, ServletContextAware { private @Inject LocaleChangeInterceptor localeChangeInterceptor; private @Inject ViewContextHandlerInterceptorAdapter viewContextHandlerInterceptorAdapter; private @Inject WebContentInterceptor webContentInterceptor; private @Inject BaseConfiguration baseConfiguration; private static final Log logger = LogFactory.getLog(AdminWebMvcConfig.class); private boolean hasDojoProduction; @Override public void addResourceHandlers (final ResourceHandlerRegistry registry) { // Handles HTTP GET requests for /resources/** by efficiently serving up static resources: registry .addResourceHandler ("/resources/**") .addResourceLocations ("/resources/**", "classpath:/META-INF/web-resources/"); } @Override public void configureDefaultServletHandling (final DefaultServletHandlerConfigurer configurer) { // Allows for mapping the DispatcherServlet to "/" by forwarding static resource requests to the container's default Servlet configurer.enable (); } @Override public void addInterceptors (final InterceptorRegistry registry) { // register "global" interceptor beans to apply to all registered HandlerMappings registry.addInterceptor (localeChangeInterceptor ()); registry.addInterceptor (viewContextHandlerInterceptorAdapter ()); registry.addInterceptor (webContentInterceptor ()); } /** * Route exceptions to defaultException.vm with a default status code of 500. */ public @Bean SimpleMappingExceptionResolver simpleMappingExceptionResolver () { final SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver (); resolver.setDefaultErrorView ("defaultException"); resolver.setDefaultStatusCode (500); return resolver; } /** * Selects a static view for rendering without the need for an explicit controller. */ public void addViewControllers (final ViewControllerRegistry registry) { registry.addViewController ("/uncaughtException"); registry.addViewController ("/resourceNotFound"); } /** * Resolves localized messages*.properties and application.properties files in the application to allow for internationalization. * The messages*.properties files translate Roo generated messages which are part of the admin interface, the application.properties * resource bundle localizes all application specific messages such as entity names and menu items. */ public @Bean ReloadableResourceBundleMessageSource messageSource () { final ReloadableResourceBundleMessageSource source = new ReloadableResourceBundleMessageSource (); if (!hasDojoProduction) { source.setCacheSeconds (0); } source.setBasenames ("WEB-INF/i18n/messages"); source.setFallbackToSystemLocale (false); return source; } /** * Store preferred language configuration in a cookie */ public @Bean CookieLocaleResolver localeResolver () { final CookieLocaleResolver resolver = new CookieLocaleResolver (); resolver.setCookieName ("locale"); return resolver; } /** * Resolves localized <theme_name>.properties files in the classpath to allow for theme support. */ public @Bean ResourceBundleThemeSource themeSource () { return new ResourceBundleThemeSource (); } /** * Set a fixed default theme name. */ public @Bean FixedThemeResolver themeResolver () { final FixedThemeResolver themeResolver = new FixedThemeResolver (); themeResolver.setDefaultThemeName ("default"); return themeResolver; } /** * Allows for integration of file upload functionality. */ public @Bean CommonsMultipartResolver multipartResolver () { return new CommonsMultipartResolver (); } public @Bean LocaleChangeInterceptor localeChangeInterceptor () { if (this.localeChangeInterceptor == null) { this.localeChangeInterceptor = new LocaleChangeInterceptor (); localeChangeInterceptor.setParamName ("lang"); } return this.localeChangeInterceptor; } public @Bean ViewContextHandlerInterceptorAdapter viewContextHandlerInterceptorAdapter () { if (this.viewContextHandlerInterceptorAdapter == null) { this.viewContextHandlerInterceptorAdapter = new ViewContextHandlerInterceptorAdapter (); } return this.viewContextHandlerInterceptorAdapter; } public @Bean WebContentInterceptor webContentInterceptor () { if (this.webContentInterceptor == null) { this.webContentInterceptor = new WebContentInterceptor (); this.webContentInterceptor.setAlwaysUseFullPath (true); this.webContentInterceptor.setCacheSeconds (0); this.webContentInterceptor.setCacheMappings (new Properties () { private static final long serialVersionUID = 1L; { put ("/styles/**", "86400"); put ("/scripts/**", "86400"); put ("/images/**", "86400"); } }); } return this.webContentInterceptor; } @Override public void setServletContext (final ServletContext servletContext) { // Test whether a production build of dojo is available in the war: final InputStream dojoStream = servletContext.getResourceAsStream ("/scripts/cds/dojo/dojo.js"); if (dojoStream != null) { hasDojoProduction = true; try { dojoStream.close (); } catch (IOException e) { } } else { hasDojoProduction = false; } logger.info("Has Dojo production? " + (hasDojoProduction ? "Yes" : "No")); } /** * Adds default properties to each view. This method adds the 'dojoDebug' property based on which the * default layout decides to use a CDN version of dojo (debug) or a custom built version (production). * Tests whether a production build of dojo is available in the war. */ @Override public Map<String, Object> getAttributes () { // Return default properties for use in velocity views: return new HashMap<String, Object> () { private static final long serialVersionUID = 1L; { put ("dojoDebug", !hasDojoProduction); put ("mavenVersion", baseConfiguration.getMavenVersion ()); put ("cdsVersion", baseConfiguration.getCdsVersion ()); put ("buildVersion", baseConfiguration.getBuild()); put ("i18n", velocityAdapter()); put ("requestAuthorizationPrompt", baseConfiguration.getRequestAuthorizationPrompt ()); put ("requestAuthorizationHref", baseConfiguration.getRequestAuthorizationHref ()); } }; } @Bean public LocaleProvider localeProvider() { return new SpringLocaleProvider(); } @Bean public VelocityAdapter velocityAdapter() { return new VelocityAdapter(); } }