import javax.servlet.http.HttpServletRequest import org.codehaus.groovy.grails.web.servlet.DefaultGrailsApplicationAttributes import org.codehaus.groovy.grails.web.pages.GroovyPagesTemplateEngine import org.springframework.web.context.request.RequestContextHolder import org.codehaus.groovy.grails.web.context.ServletContextHolder import org.springframework.web.context.support.WebApplicationContextUtils import org.codehaus.groovy.grails.plugins.PluginManagerHolder import org.codehaus.groovy.grails.commons.GrailsResourceUtils class GrailsTemplateEngineService { static transactional = false GroovyPagesTemplateEngine groovyPagesTemplateEngine static PATH_TO_VIEWS = "/WEB-INF/grails-app/views" protected String renderView(templateName, model, pluginName = null) { if(!groovyPagesTemplateEngine) throw new IllegalStateException("Property [groovyPagesTemplateEngine] must be set!") assert templateName def engine = groovyPagesTemplateEngine def requestAttributes = RequestContextHolder.getRequestAttributes() boolean unbindRequest = false // outside of an executing request, establish a mock version if(!requestAttributes) { def servletContext = ServletContextHolder.getServletContext() def applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext) requestAttributes = grails.util.GrailsWebUtil.bindMockWebRequest(applicationContext) unbindRequest = true } def servletContext = requestAttributes.request.servletContext def request = requestAttributes.request def grailsAttributes = new DefaultGrailsApplicationAttributes(servletContext); // See if the application has the view for it def uri = resolveViewUri(templateName, request) def r = engine.getResourceForUri(uri) // Try plugin view if not found in application if ((!r || !r.exists()) && pluginName) { // Caution, this uses views/ always, whereas our app view resolution uses the PATH_TO_MAILVIEWS which may in future be orthogonal! def plugin = PluginManagerHolder.pluginManager.getGrailsPlugin(pluginName) String pathToView if (plugin) { pathToView = '/plugins/'+plugin.name+'-'+plugin.version+'/'+GrailsResourceUtils.GRAILS_APP_DIR+'/views'+templateName } if (pathToView != null) { uri = GrailsResourceUtils.WEB_INF +pathToView +templateName+".gsp"; r = engine.getResourceForUri(uri) } } def t = engine.createTemplate( r ) def out = new StringWriter(); def originalOut = requestAttributes.getOut() requestAttributes.setOut(out) try { if(model instanceof Map) { t.make( model ).writeTo(out) } else { t.make().writeTo(out) } } finally { requestAttributes.setOut(originalOut) if(unbindRequest) { RequestContextHolder.setRequestAttributes(null) } } return out.toString(); } protected String resolveViewUri(String viewName, HttpServletRequest request) { StringBuffer buf = new StringBuffer(PATH_TO_VIEWS); if(viewName.startsWith("/")) { String tmp = viewName.substring(1,viewName.length()); if(tmp.indexOf('/') > -1) { buf.append('/'); buf.append(tmp.substring(0,tmp.lastIndexOf('/'))); buf.append("/"); buf.append(tmp.substring(tmp.lastIndexOf('/') + 1,tmp.length())); } else { buf.append("/"); buf.append(viewName.substring(1,viewName.length())); } } else { if (!request) throw new IllegalArgumentException( "View cannot be loaded from relative view paths where there is no current HTTP request") def grailsAttributes = new DefaultGrailsApplicationAttributes(request.servletContext); buf.append(grailsAttributes.getControllerUri(request)) .append("/") .append(viewName); } return buf.append(".gsp").toString(); } }