001/* 002 * Copyright 2012-2017 the original author or authors. 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 */ 016 017package org.springframework.boot.autoconfigure.groovy.template; 018 019import java.security.CodeSource; 020import java.security.ProtectionDomain; 021 022import javax.annotation.PostConstruct; 023import javax.servlet.Servlet; 024 025import groovy.text.markup.MarkupTemplateEngine; 026import org.apache.commons.logging.Log; 027import org.apache.commons.logging.LogFactory; 028 029import org.springframework.beans.factory.ObjectProvider; 030import org.springframework.boot.autoconfigure.AutoConfigureAfter; 031import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; 032import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 033import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 034import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; 035import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; 036import org.springframework.boot.autoconfigure.template.TemplateLocation; 037import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; 038import org.springframework.boot.context.properties.ConfigurationProperties; 039import org.springframework.boot.context.properties.EnableConfigurationProperties; 040import org.springframework.context.ApplicationContext; 041import org.springframework.context.annotation.Bean; 042import org.springframework.context.annotation.Configuration; 043import org.springframework.context.i18n.LocaleContextHolder; 044import org.springframework.web.servlet.view.UrlBasedViewResolver; 045import org.springframework.web.servlet.view.groovy.GroovyMarkupConfig; 046import org.springframework.web.servlet.view.groovy.GroovyMarkupConfigurer; 047import org.springframework.web.servlet.view.groovy.GroovyMarkupViewResolver; 048 049/** 050 * Auto-configuration support for Groovy templates in MVC. By default creates a 051 * {@link MarkupTemplateEngine} configured from {@link GroovyTemplateProperties}, but you 052 * can override that by providing your own {@link GroovyMarkupConfig} or even a 053 * {@link MarkupTemplateEngine} of a different type. 054 * 055 * @author Dave Syer 056 * @author Andy Wilkinson 057 * @author Brian Clozel 058 * @since 1.1.0 059 */ 060@Configuration 061@ConditionalOnClass(MarkupTemplateEngine.class) 062@AutoConfigureAfter(WebMvcAutoConfiguration.class) 063@EnableConfigurationProperties(GroovyTemplateProperties.class) 064public class GroovyTemplateAutoConfiguration { 065 066 private static final Log logger = LogFactory 067 .getLog(GroovyTemplateAutoConfiguration.class); 068 069 @Configuration 070 @ConditionalOnClass(GroovyMarkupConfigurer.class) 071 public static class GroovyMarkupConfiguration { 072 073 private final ApplicationContext applicationContext; 074 075 private final GroovyTemplateProperties properties; 076 077 private final MarkupTemplateEngine templateEngine; 078 079 public GroovyMarkupConfiguration(ApplicationContext applicationContext, 080 GroovyTemplateProperties properties, 081 ObjectProvider<MarkupTemplateEngine> templateEngine) { 082 this.applicationContext = applicationContext; 083 this.properties = properties; 084 this.templateEngine = templateEngine.getIfAvailable(); 085 } 086 087 @PostConstruct 088 public void checkTemplateLocationExists() { 089 if (this.properties.isCheckTemplateLocation() && !isUsingGroovyAllJar()) { 090 TemplateLocation location = new TemplateLocation( 091 this.properties.getResourceLoaderPath()); 092 if (!location.exists(this.applicationContext)) { 093 logger.warn("Cannot find template location: " + location 094 + " (please add some templates, check your Groovy " 095 + "configuration, or set spring.groovy.template." 096 + "check-template-location=false)"); 097 } 098 } 099 } 100 101 /** 102 * MarkupTemplateEngine could be loaded from groovy-templates or groovy-all. 103 * Unfortunately it's quite common for people to use groovy-all and not actually 104 * need templating support. This method check attempts to check the source jar so 105 * that we can skip the {@code /template} folder check for such cases. 106 * @return true if the groovy-all jar is used 107 */ 108 private boolean isUsingGroovyAllJar() { 109 try { 110 ProtectionDomain domain = MarkupTemplateEngine.class 111 .getProtectionDomain(); 112 CodeSource codeSource = domain.getCodeSource(); 113 if (codeSource != null 114 && codeSource.getLocation().toString().contains("-all")) { 115 return true; 116 } 117 return false; 118 } 119 catch (Exception ex) { 120 return false; 121 } 122 } 123 124 @Bean 125 @ConditionalOnMissingBean(GroovyMarkupConfig.class) 126 @ConfigurationProperties(prefix = "spring.groovy.template.configuration") 127 public GroovyMarkupConfigurer groovyMarkupConfigurer() { 128 GroovyMarkupConfigurer configurer = new GroovyMarkupConfigurer(); 129 configurer.setResourceLoaderPath(this.properties.getResourceLoaderPath()); 130 configurer.setCacheTemplates(this.properties.isCache()); 131 if (this.templateEngine != null) { 132 configurer.setTemplateEngine(this.templateEngine); 133 } 134 return configurer; 135 } 136 137 } 138 139 @Configuration 140 @ConditionalOnClass({ Servlet.class, LocaleContextHolder.class, 141 UrlBasedViewResolver.class }) 142 @ConditionalOnWebApplication(type = Type.SERVLET) 143 @ConditionalOnProperty(name = "spring.groovy.template.enabled", matchIfMissing = true) 144 public static class GroovyWebConfiguration { 145 146 private final GroovyTemplateProperties properties; 147 148 public GroovyWebConfiguration(GroovyTemplateProperties properties) { 149 this.properties = properties; 150 } 151 152 @Bean 153 @ConditionalOnMissingBean(name = "groovyMarkupViewResolver") 154 public GroovyMarkupViewResolver groovyMarkupViewResolver() { 155 GroovyMarkupViewResolver resolver = new GroovyMarkupViewResolver(); 156 this.properties.applyToMvcViewResolver(resolver); 157 return resolver; 158 } 159 160 } 161 162}