org.grails.web.pages.GroovyPagesServlet Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of grace-web-gsp Show documentation
Show all versions of grace-web-gsp Show documentation
Grace Framework : Grace Web Gsp
/*
* Copyright 2004-2023 the original author or authors.
*
* 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
*
* https://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.grails.web.pages;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import groovy.text.Template;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.FrameworkServlet;
import org.springframework.web.util.WebUtils;
import grails.plugins.GrailsPlugin;
import grails.plugins.GrailsPluginManager;
import grails.plugins.PluginManagerAware;
import grails.util.GrailsStringUtils;
import org.grails.core.io.support.GrailsFactoriesLoader;
import org.grails.gsp.GroovyPageTemplate;
import org.grails.gsp.GroovyPagesTemplateEngine;
import org.grails.gsp.io.GroovyPageCompiledScriptSource;
import org.grails.gsp.io.GroovyPageScriptSource;
import org.grails.plugins.BinaryGrailsPlugin;
import org.grails.web.servlet.mvc.GrailsWebRequest;
import org.grails.web.sitemesh.GrailsLayoutDecoratorMapper;
import org.grails.web.util.GrailsApplicationAttributes;
/**
* NOTE: Based on work done by on the GSP standalone project (https://gsp.dev.java.net/)
*
* Main servlet class. Example usage in web.xml:
*
*
* {@code
*
* GroovyPagesServlet
* GroovyPagesServlet
*
* showSource
* 1
*
* Allows developers to view the intermediade source code, when they pass
* a showSource argument in the URL (eg /edit/list?showSource=true.
*
*
*
* }
*
*
* @author Troy Heninger
* @author Graeme Rocher
*
* Date: Jan 10, 2004
*/
public class GroovyPagesServlet extends FrameworkServlet implements PluginManagerAware {
private static final long serialVersionUID = -1918149859392123495L;
private static final String WEB_INF = "/WEB-INF";
private static final String GRAILS_APP = "/grails-app";
private ServletContext context;
private GrailsApplicationAttributes grailsAttributes;
public GroovyPagesServlet() {
// use the root web application context always
setContextAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
}
@Override
protected ServletRequestAttributes buildRequestAttributes(HttpServletRequest request,
HttpServletResponse response, RequestAttributes previousAttributes) {
if (previousAttributes instanceof GrailsWebRequest) {
return null;
}
else {
return super.buildRequestAttributes(request, response, previousAttributes);
}
}
/**
* The size of the buffer used when formulating the response
*/
public static final String SERVLET_INSTANCE = "org.codehaus.groovy.grails.GSP_SERVLET";
private GroovyPagesTemplateEngine groovyPagesTemplateEngine;
private GrailsPluginManager pluginManager;
@SuppressWarnings("rawtypes")
private Map binaryPluginViewsMap = new ConcurrentHashMap<>();
@Override
protected void initFrameworkServlet() throws BeansException {
this.context = getServletContext();
this.context.log("GSP servlet initialized");
this.context.setAttribute(SERVLET_INSTANCE, this);
final WebApplicationContext webApplicationContext = getWebApplicationContext();
this.grailsAttributes = GrailsFactoriesLoader.loadFactoriesWithArguments(GrailsApplicationAttributes.class,
getClass().getClassLoader(), new Object[] { this.context }).get(0);
final AutowireCapableBeanFactory autowireCapableBeanFactory = webApplicationContext.getAutowireCapableBeanFactory();
if (autowireCapableBeanFactory != null) {
autowireCapableBeanFactory.autowireBeanProperties(this, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false);
}
this.groovyPagesTemplateEngine =
webApplicationContext.getBean(GroovyPagesTemplateEngine.BEAN_ID, GroovyPagesTemplateEngine.class);
}
public void setGroovyPagesTemplateEngine(GroovyPagesTemplateEngine groovyPagesTemplateEngine) {
this.groovyPagesTemplateEngine = groovyPagesTemplateEngine;
}
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
request.setAttribute(GrailsApplicationAttributes.REQUEST_SCOPE_ID, this.grailsAttributes);
request.setAttribute(GroovyPagesServlet.SERVLET_INSTANCE, this);
String pageName = (String) request.getAttribute(GrailsApplicationAttributes.GSP_TO_RENDER);
if (GrailsStringUtils.isBlank(pageName)) {
pageName = getCurrentRequestUri(request);
}
boolean isNotInclude = !WebUtils.isIncludeRequest(request);
if (isNotInclude && isSecurePath(pageName)) {
sendNotFound(response, pageName);
}
else {
GroovyPageScriptSource scriptSource = this.groovyPagesTemplateEngine.findScriptSource(pageName);
if (scriptSource == null) {
scriptSource = findPageInBinaryPlugins(pageName);
}
if (scriptSource == null || (isNotInclude && !scriptSource.isPublic())) {
sendNotFound(response, pageName);
return;
}
renderPageWithEngine(this.groovyPagesTemplateEngine, request, response, scriptSource);
}
}
protected String getCurrentRequestUri(HttpServletRequest request) {
Object includePath = request.getAttribute("jakarta.servlet.include.servlet_path");
if (includePath != null) {
return (String) includePath;
}
return request.getServletPath();
}
public GroovyPagesTemplateEngine getGroovyPagesTemplateEngine() {
return this.groovyPagesTemplateEngine;
}
protected boolean isSecurePath(String pageName) {
return pageName.startsWith(WEB_INF) || pageName.startsWith(GRAILS_APP);
}
protected void sendNotFound(HttpServletResponse response, String pageName) throws IOException {
this.context.log("GroovyPagesServlet: \"" + pageName + "\" not found");
response.sendError(404, "\"" + pageName + "\" not found.");
}
protected GroovyPageScriptSource findPageInBinaryPlugins(String pageName) {
if (pageName != null) {
Class> pageClass = this.binaryPluginViewsMap.get(pageName);
if (pageClass == null && this.pluginManager != null) {
final GrailsPlugin[] allPlugins = this.pluginManager.getAllPlugins();
for (GrailsPlugin plugin : allPlugins) {
if (plugin instanceof BinaryGrailsPlugin) {
BinaryGrailsPlugin binaryPlugin = (BinaryGrailsPlugin) plugin;
pageClass = binaryPlugin.resolveView(pageName);
if (pageClass != null) {
this.binaryPluginViewsMap.put(pageName, pageClass);
break;
}
}
}
}
if (pageClass != null) {
return new GroovyPageCompiledScriptSource(pageName, pageName, pageClass);
}
}
return null;
}
/**
* Attempts to render the page with the given arguments
*
*
* @param engine The GroovyPagesTemplateEngine to use
* @param request The HttpServletRequest
* @param response The HttpServletResponse
* @param scriptSource The template
*
* @throws IOException Thrown when an I/O exception occurs rendering the page
*/
protected void renderPageWithEngine(GroovyPagesTemplateEngine engine, HttpServletRequest request,
HttpServletResponse response, GroovyPageScriptSource scriptSource) throws Exception {
request.setAttribute(GrailsLayoutDecoratorMapper.RENDERING_VIEW, Boolean.TRUE);
GSPResponseWriter out = createResponseWriter(response);
try {
Template template = engine.createTemplate(scriptSource);
if (template instanceof GroovyPageTemplate) {
((GroovyPageTemplate) template).setAllowSettingContentType(true);
}
template.make().writeTo(out);
}
catch (Exception e) {
out.setError();
throw e;
}
finally {
if (out != null) {
out.close();
}
}
}
/**
* Creates a response writer for the given response object
*
* @param response The HttpServletResponse
* @return The created java.io.Writer
*/
protected GSPResponseWriter createResponseWriter(HttpServletResponse response) {
GSPResponseWriter out = GSPResponseWriter.getInstance(response);
GrailsWebRequest webRequest = (GrailsWebRequest) RequestContextHolder.currentRequestAttributes();
webRequest.setOut(out);
return out;
}
public void setPluginManager(GrailsPluginManager pluginManager) {
this.pluginManager = pluginManager;
}
}