remove jars
[zkgrails.git] / src / java / ZKGrailsPageFilter.java
blob3ec1921362407cc4a62341c30cc4668b81a245a9
1 /*
2 * Copyright 2004-2005 the original author or authors.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 // package org.codehaus.groovy.grails.web.sitemesh;
18 import com.opensymphony.module.sitemesh.Decorator;
19 import com.opensymphony.module.sitemesh.DecoratorMapper;
20 import com.opensymphony.module.sitemesh.Page;
21 import com.opensymphony.module.sitemesh.util.Container;
22 import com.opensymphony.module.sitemesh.filter.PageFilter;
23 import com.opensymphony.module.sitemesh.filter.PageResponseWrapper;
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 import org.codehaus.groovy.grails.web.servlet.GrailsApplicationAttributes;
27 import org.codehaus.groovy.grails.commons.ConfigurationHolder;
28 import org.springframework.web.util.UrlPathHelper;
30 import org.codehaus.groovy.grails.web.sitemesh.FactoryHolder;
32 import javax.servlet.*;
33 import javax.servlet.http.HttpServletRequest;
34 import javax.servlet.http.HttpServletResponse;
35 import java.io.IOException;
36 import java.io.PrintWriter;
38 /**
39 * Extends the default page filter to overide the apply decorator behaviour
40 * if the page is a GSP
42 * @author Graeme Rocher
43 * @since Apr 19, 2006
45 public class ZKGrailsPageFilter extends PageFilter {
47 private static final Log LOG = LogFactory.getLog( ZKGrailsPageFilter.class );
48 private static final String HTML_EXT = ".html";
49 private static final String UTF_8_ENCODING = "UTF-8";
50 private static final String CONFIG_OPTION_GSP_ENCODING = "grails.views.gsp.encoding";
53 public void init(FilterConfig filterConfig) {
54 super.init(filterConfig);
55 this.filterConfig = filterConfig;
56 FactoryHolder.setFactory(this.factory);
59 public void destroy() {
60 super.destroy();
61 FactoryHolder.setFactory(null);
64 private boolean isZK(HttpServletRequest request) {
65 String path = extractRequestPath(request);
66 final String[] ext = new String[]{".zul",".dsp","*.zhtml", "*.svg", "*.xml2html"};
67 for(int i=0;i < ext.length; i++) {
68 if(path.lastIndexOf(ext[i])!=-1) return true;
70 return false;
73 * TODO: This method has been copied from the parent to fix a bug in sitemesh 2.3. When sitemesh 2.4 is release this method and the two private methods below can removed
75 * Main method of the Filter.
77 * <p>Checks if the Filter has been applied this request. If not, parses the page
78 * and applies {@link com.opensymphony.module.sitemesh.Decorator} (if found).
80 public void doFilter(ServletRequest rq, ServletResponse rs, FilterChain chain)
81 throws IOException, ServletException {
83 HttpServletRequest request = (HttpServletRequest) rq;
85 // System.out.println(">>> " + extractRequestPath(request));
87 if (rq.getAttribute(FILTER_APPLIED) != null || factory.isPathExcluded(extractRequestPath(request)) || isZK(request)) {
88 // ensure that filter is only applied once per request
89 chain.doFilter(rq, rs);
91 else {
92 request.setAttribute(FILTER_APPLIED, Boolean.TRUE);
94 factory.refresh();
95 DecoratorMapper decoratorMapper = factory.getDecoratorMapper();
96 HttpServletResponse response = (HttpServletResponse) rs;
98 // parse data into Page object (or continue as normal if Page not parseable)
99 Page page = parsePage(request, response, chain);
101 if (page != null) {
102 page.setRequest(request);
104 Decorator decorator = decoratorMapper.getDecorator(request, page);
105 if (decorator != null && decorator.getPage() != null) {
106 applyDecorator(page, decorator, request, response);
107 return;
109 // if we got here, an exception occured or the decorator was null,
110 // what we don't want is an exception printed to the user, so
111 // we write the original page
112 writeOriginal(request, response, page);
118 * Continue in filter-chain, writing all content to buffer and parsing
119 * into returned {@link com.opensymphony.module.sitemesh.Page} object. If
120 * {@link com.opensymphony.module.sitemesh.Page} is not parseable, null is returned.
122 protected Page parsePage(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
123 try {
124 PageResponseWrapper pageResponse = new PageResponseWrapper(response, factory);
125 UrlPathHelper urlHelper = new UrlPathHelper();
126 String requestURI = urlHelper.getOriginatingRequestUri(request);
127 // static content?
128 if(requestURI.endsWith(HTML_EXT)) {
129 String encoding = (String)ConfigurationHolder.getFlatConfig().get(CONFIG_OPTION_GSP_ENCODING);
130 if(encoding == null) encoding = UTF_8_ENCODING;
131 pageResponse.setContentType("text/html;charset="+encoding);
136 chain.doFilter(request, pageResponse);
137 // check if another servlet or filter put a page object to the request
138 Page result = (Page)request.getAttribute(PAGE);
139 if (result == null) {
140 // parse the page
141 result = pageResponse.getPage();
143 request.setAttribute(USING_STREAM, pageResponse.isUsingStream() ? Boolean.TRUE : Boolean.FALSE); // JDK 1.3 friendly
144 return result;
146 catch (IllegalStateException e) {
147 // weblogic throws an IllegalStateException when an error page is served.
148 // it's ok to ignore this, however for all other containers it should be thrown
149 // properly.
150 if (Container.get() != Container.WEBLOGIC) throw e;
151 return null;
155 private String extractRequestPath(HttpServletRequest request) {
156 String servletPath = request.getServletPath();
157 String pathInfo = request.getPathInfo();
158 String query = request.getQueryString();
159 return (servletPath == null ? "" : servletPath)
160 + (pathInfo == null ? "" : pathInfo)
161 + (query == null ? "" : ("?" + query));
164 /** Write the original page data to the response. */
165 private void writeOriginal(HttpServletRequest request, HttpServletResponse response, Page page) throws IOException {
166 response.setContentLength(page.getContentLength());
167 if (request.getAttribute(USING_STREAM).equals(Boolean.TRUE))
169 PrintWriter writer = new PrintWriter(response.getOutputStream());
170 page.writePage(writer);
171 //flush writer to underlying outputStream
172 writer.flush();
173 response.getOutputStream().flush();
175 else
177 page.writePage(response.getWriter());
178 response.getWriter().flush();
183 /* (non-Javadoc)
184 * @see com.opensymphony.module.sitemesh.filter.PageFilter#applyDecorator(com.opensymphony.module.sitemesh.Page, com.opensymphony.module.sitemesh.Decorator, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
186 protected void applyDecorator(Page page, Decorator decorator, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
187 final String uriPath = decorator.getURIPath();
188 if(uriPath != null && uriPath.endsWith(".gsp")) {
189 request.setAttribute(PAGE, page);
191 detectContentTypeFromPage(page, response);
193 RequestDispatcher rd = request.getRequestDispatcher(decorator.getURIPath());
194 if(!response.isCommitted()) {
195 if(LOG.isDebugEnabled()) {
196 LOG.debug("Rendering layout using forward: " + decorator.getURIPath());
198 rd.forward(request, response);
200 else {
201 if(LOG.isDebugEnabled()) {
202 LOG.debug("Rendering layout using include: " + decorator.getURIPath());
204 request.setAttribute(GrailsApplicationAttributes.GSP_TO_RENDER,decorator.getURIPath());
205 rd.include(request,response);
206 request.removeAttribute(GrailsApplicationAttributes.GSP_TO_RENDER);
209 // set the headers specified as decorator init params
210 while (decorator.getInitParameterNames().hasNext()) {
211 String initParam = (String) decorator.getInitParameterNames().next();
212 if (initParam.startsWith("header.")) {
213 response.setHeader(initParam.substring(initParam.indexOf('.')), decorator.getInitParameter(initParam));
216 request.removeAttribute(PAGE);
218 else {
220 super.applyDecorator(page, decorator, request, response);
225 private void detectContentTypeFromPage(Page page, HttpServletResponse response) {
226 String contentType = page.getProperty("meta.http-equiv.Content-Type");
227 if(contentType != null && "text/html".equals(response.getContentType())) {
228 response.setContentType(contentType);