2005-08-12

sitemesh PageFilter存在writeOriginal存在问题

页面经过sitemesh过滤处理,如果不存在对应的装饰器writeOriginal方法输出的结果很可能截短 原因是page.getContentLength()可能不正确,特别是页面编码为UTF-8时 修正后的类如下:
/* This software is published under the terms of the OpenSymphony Software
 * License version 1.1, of which a copy has been included with this
 * distribution in the LICENSE.txt file. */
package com.opensymphony.module.sitemesh.filter;

import com.opensymphony.module.sitemesh.*;
import com.opensymphony.module.sitemesh.util.Container;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * Main SiteMesh filter for applying Decorators to entire Pages.
 * 
 * @author Joe Walnes
 * @author Scott Farquhar
 * @version $Revision: 1.13 $
 */
public class PageFilter implements Filter, RequestConstants {
    protected FilterConfig filterConfig = null;

    protected Factory factory = null;

    /**
     * Main method of the Filter.
     * 
     * 

* Checks if the Filter has been applied this request. If not, parses the * page and applies {@link com.opensymphony.module.sitemesh.Decorator} (if * found). */ public final void doFilter(ServletRequest rq, ServletResponse rs, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) rq; if (needDecorator(request)) { request.setAttribute(FILTER_APPLIED, Boolean.TRUE); // force creation of the session now because Tomcat 4 had problems // with // creating sessions after the response had been committed if (Container.get() == Container.TOMCAT) { request.getSession(true); } HttpServletResponse response = (HttpServletResponse) rs; // parse data into Page object (or continue as normal if Page not // parseable) Page page = parsePage(request, response, chain); if (page != null) { page.setRequest(request); Decorator decorator = factory.getDecoratorMapper() .getDecorator(request, page); if (decorator != null && decorator.getPage() != null) { applyDecorator(page, decorator, request, response); page = null; return; } // if we got here, an exception occured or the decorator was // null, // what we don't want is an exception printed to the user, so // we write the original page writeOriginal(request, response, page); page = null; } } else { // ensure that filter is only applied once per request chain.doFilter(rq, rs); } } /** * Test need decorator or not
* ensure that filter is only applied once per request * @param request * @return true,if need decorator; otherwise,false. */ protected boolean needDecorator(HttpServletRequest request) { return !(request.getAttribute(FILTER_APPLIED) != null || factory .isPathExcluded(extractRequestPath(request))); } private String extractRequestPath(HttpServletRequest request) { String servletPath = request.getServletPath(); String pathInfo = request.getPathInfo(); String query = request.getQueryString(); return (servletPath == null ? "" : servletPath) + (pathInfo == null ? "" : pathInfo) + (query == null ? "" : ("?" + query)); } /** * Set FilterConfig, and get instance of * {@link com.opensymphony.module.sitemesh.DecoratorMapper}. */ public void init(FilterConfig filterConfig) { if (filterConfig != null) { this.filterConfig = filterConfig; factory = Factory.getInstance(new Config(filterConfig)); } else { destroy(); } } /** * @deprecated Not needed in final version of Servlet 2.3 API - replaced by * init(). */ // NOTE: SiteMesh doesn't work with Orion 1.5.2 without this method public FilterConfig getFilterConfig() { return filterConfig; } /** * @deprecated Not needed in final version of Servlet 2.3 API - replaced by * init(). */ // NOTE: SiteMesh doesn't work with Orion 1.5.2 without this method public void setFilterConfig(FilterConfig filterConfig) { init(filterConfig); } /** Shutdown filter. */ public void destroy() { factory = null; } /** * Continue in filter-chain, writing all content to buffer and parsing into * returned {@link com.opensymphony.module.sitemesh.Page} object. If * {@link com.opensymphony.module.sitemesh.Page} is not parseable, null is * returned. */ protected Page parsePage(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { try { PageResponseWrapper pageResponse = new PageResponseWrapper( response, factory); chain.doFilter(request, pageResponse); // check if another servlet or filter put a page object to the // request Page result = (Page) request.getAttribute(PAGE); if (result == null) { // parse the page result = pageResponse.getPage(); } request.setAttribute(USING_STREAM, new Boolean(pageResponse .isUsingStream())); return result; } catch (IllegalStateException e) { // weblogic throws an IllegalStateException when an error page is // served. // it's ok to ignore this, however for all other containers it // should be thrown // properly. if (Container.get() != Container.WEBLOGIC) throw e; else { e.printStackTrace(); } return null; } } /** * Apply {@link com.opensymphony.module.sitemesh.Decorator} to * {@link com.opensymphony.module.sitemesh.Page} and write to the response. */ protected void applyDecorator(Page page, Decorator decorator, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { request.setAttribute(PAGE, page); ServletContext context = filterConfig.getServletContext(); // see if the URI path (webapp) is set if (decorator.getURIPath() != null) { // in a security conscious environment, the servlet container // may return null for a given URL if (context.getContext(decorator.getURIPath()) != null) { context = context.getContext(decorator.getURIPath()); } } // get the dispatcher for the decorator RequestDispatcher dispatcher = context .getRequestDispatcher(decorator.getPage()); // create a wrapper around the response dispatcher.include(request, response); // set the headers specified as decorator init params while (decorator.getInitParameterNames().hasNext()) { String initParam = (String) decorator.getInitParameterNames() .next(); if (initParam.startsWith("header.")) { response.setHeader(initParam.substring(initParam .indexOf('.')), decorator .getInitParameter(initParam)); } } request.removeAttribute(PAGE); } catch (RuntimeException e) { // added a print message here because otherwise Tomcat swallows // the error and you never see it = bad! if (Container.get() == Container.TOMCAT) e.printStackTrace(); throw e; } } /** Write the original page data to the response. */ private void writeOriginal(HttpServletRequest request, HttpServletResponse response, Page page) throws IOException { // page.getContentLength() not right! // response.setContentLength(page.getContentLength()); if (request.getAttribute(USING_STREAM).equals(Boolean.TRUE)) { PrintWriter writer = new PrintWriter(response.getOutputStream()); page.writePage(writer); // flush writer to underlying outputStream writer.flush(); response.getOutputStream().flush(); } else { page.writePage(response.getWriter()); response.getWriter().flush(); } } }

2005-08-05

限制对Web资源的访问(续)

2005-08-04

eclipse中cvs对比remote文件显示为乱码,原因是eclipse中windows-->Preferences...-->General-->Content Types中对的扩展名设置的编码不正确 修正此问题方法: 对应的扩展名设置合适的字符编码,然后点击update,then OK:) But 安装myeclipse4M2后对应jspf的更新可能无效,此时怎么改也是无效的:( 原因是IBM中的jspmodel.jar的 com.ibm.sse.model.jsp.contenttype.JSPResourceEncodingDetector的 getSpecDefaultEncoding()返回ISO8859-1,目前我是把此反编译让getSpecDefaultEncoding()返回 UTF-8,anything will be fine:)

2005-08-02

代理服务器的缓存问题,可以致使请求页面的结果不对! 特别在struts应用中action完成sendRedirect到指定页面,而此页面uri就是提交发起的页面,此时action服务器端是执行了,sendRedirect页面服务上没有执行.原因是sendRedirect有一交互,服务器端发一sendReirect指令给浏览器,浏览器请求sendRedirect页面时代理服务器此时认为此页面已是最新就不再向服务器发出请求了,从而导致结果出不对