Save This Page
Home » sitemesh-2.3 » com.opensymphony » sitemesh » webapp » [javadoc | source]
    1   package com.opensymphony.sitemesh.webapp;
    2   
    3   import com.opensymphony.module.sitemesh.Config;
    4   import com.opensymphony.module.sitemesh.Factory;
    5   import com.opensymphony.sitemesh.Content;
    6   import com.opensymphony.sitemesh.Decorator;
    7   import com.opensymphony.sitemesh.DecoratorSelector;
    8   import com.opensymphony.sitemesh.ContentProcessor;
    9   import com.opensymphony.sitemesh.compatability.DecoratorMapper2DecoratorSelector;
   10   import com.opensymphony.sitemesh.compatability.PageParser2ContentProcessor;
   11   
   12   import javax.servlet;
   13   import javax.servlet.http.HttpServletRequest;
   14   import javax.servlet.http.HttpServletResponse;
   15   import java.io.IOException;
   16   
   17   /**
   18    * Core Filter for integrating SiteMesh into a Java web application.
   19    *
   20    * @author Joe Walnes
   21    * @author Scott Farquhar
   22    * @since SiteMesh 3
   23    */
   24   public class SiteMeshFilter implements Filter {
   25   
   26       private FilterConfig filterConfig;
   27       private ContainerTweaks containerTweaks;
   28   
   29       public void init(FilterConfig filterConfig) {
   30           this.filterConfig = filterConfig;
   31           containerTweaks = new ContainerTweaks();
   32       }
   33   
   34       public void destroy() {
   35           filterConfig = null;
   36           containerTweaks = null;
   37       }
   38   
   39       /**
   40        * Main method of the Filter.
   41        * <p>Checks if the Filter has been applied this request. If not, parses the page
   42        * and applies {@link com.opensymphony.module.sitemesh.Decorator} (if found).
   43        */
   44       public void doFilter(ServletRequest rq, ServletResponse rs, FilterChain chain)
   45               throws IOException, ServletException {
   46   
   47           HttpServletRequest request = (HttpServletRequest) rq;
   48           HttpServletResponse response = (HttpServletResponse) rs;
   49           ServletContext servletContext = filterConfig.getServletContext();
   50   
   51           SiteMeshWebAppContext webAppContext = new SiteMeshWebAppContext(request, response, servletContext);
   52   
   53           ContentProcessor contentProcessor = initContentProcessor(webAppContext);
   54           DecoratorSelector decoratorSelector = initDecoratorSelector(webAppContext);
   55   
   56           if (filterAlreadyAppliedForRequest(request)) {
   57               // Prior to Servlet 2.4 spec, it was unspecified whether the filter should be called again upon an include().
   58               chain.doFilter(request, response);
   59               return;
   60           }
   61   
   62           if (!contentProcessor.handles(webAppContext)) {
   63               // Optimization: If the content doesn't need to be processed, bypass SiteMesh.
   64               chain.doFilter(request, response);
   65               return;
   66           }
   67   
   68           if (containerTweaks.shouldAutoCreateSession()) {
   69               // Some containers (such as Tomcat 4) will not allow sessions to be created in the decorator.
   70               // (i.e after the response has been committed).
   71               request.getSession(true);
   72           }
   73   
   74           try {
   75   
   76               Content content = obtainContent(contentProcessor, webAppContext, request, response, chain);
   77   
   78               if (content == null) {
   79                   return;
   80               }
   81   
   82               Decorator decorator = decoratorSelector.selectDecorator(content, webAppContext);
   83               decorator.render(content, webAppContext);
   84   
   85           } catch (IllegalStateException e) {
   86               // Some containers (such as WebLogic) throw an IllegalStateException when an error page is served.
   87               // It may be ok to ignore this. However, for safety it is propegated if possible.
   88               if (!containerTweaks.shouldIgnoreIllegalStateExceptionOnErrorPage()) {
   89                   throw e;
   90               }
   91           } catch (RuntimeException e) {
   92               if (containerTweaks.shouldLogUnhandledExceptions()) {
   93                   // Some containers (such as Tomcat 4) swallow RuntimeExceptions in filters.
   94                   servletContext.log("Unhandled exception occurred whilst decorating page", e);
   95               }
   96               throw e;
   97           }
   98   
   99       }
  100   
  101       protected ContentProcessor initContentProcessor(SiteMeshWebAppContext webAppContext) {
  102           // TODO: Remove heavy coupling on horrible SM2 Factory
  103           Factory factory = Factory.getInstance(new Config(filterConfig));
  104           factory.refresh();
  105           return new PageParser2ContentProcessor(factory);
  106       }
  107   
  108       protected DecoratorSelector initDecoratorSelector(SiteMeshWebAppContext webAppContext) {
  109           // TODO: Remove heavy coupling on horrible SM2 Factory
  110           Factory factory = Factory.getInstance(new Config(filterConfig));
  111           factory.refresh();
  112           return new DecoratorMapper2DecoratorSelector(factory.getDecoratorMapper());
  113       }
  114   
  115       /**
  116        * Continue in filter-chain, writing all content to buffer and parsing
  117        * into returned {@link com.opensymphony.module.sitemesh.Page} object. If
  118        * {@link com.opensymphony.module.sitemesh.Page} is not parseable, null is returned.
  119        */
  120       private Content obtainContent(ContentProcessor contentProcessor, SiteMeshWebAppContext webAppContext,
  121                                     HttpServletRequest request, HttpServletResponse response, FilterChain chain)
  122               throws IOException, ServletException {
  123   
  124           ContentBufferingResponse contentBufferingResponse = new ContentBufferingResponse(response, contentProcessor, webAppContext);
  125           chain.doFilter(request, contentBufferingResponse);
  126           // TODO: check if another servlet or filter put a page object in the request
  127           //            Content result = request.getAttribute(PAGE);
  128           //            if (result == null) {
  129           //                // parse the page
  130           //                result = pageResponse.getPage();
  131           //            }
  132           webAppContext.setUsingStream(contentBufferingResponse.isUsingStream());
  133           return contentBufferingResponse.getContent();
  134       }
  135   
  136       private boolean filterAlreadyAppliedForRequest(HttpServletRequest request) {
  137           final String alreadyAppliedKey = "com.opensymphony.sitemesh.APPLIED_ONCE";
  138           if (request.getAttribute(alreadyAppliedKey) == Boolean.TRUE) {
  139               return true;
  140           } else {
  141               request.setAttribute(alreadyAppliedKey, Boolean.TRUE);
  142               return false;
  143           }
  144       }
  145   
  146   }

Save This Page
Home » sitemesh-2.3 » com.opensymphony » sitemesh » webapp » [javadoc | source]