Save This Page
Home » sitemesh-2.3 » com.opensymphony.module » sitemesh » taglib » page » [javadoc | source]
    1   /*
    2    * Title:        ApplyDecoratorTag
    3    * Description:
    4    *
    5    * This software is published under the terms of the OpenSymphony Software
    6    * License version 1.1, of which a copy has been included with this
    7    * distribution in the LICENSE.txt file.
    8    */
    9   
   10   package com.opensymphony.module.sitemesh.taglib.page;
   11   
   12   import com.opensymphony.module.sitemesh;
   13   import com.opensymphony.module.sitemesh.filter.PageRequestWrapper;
   14   import com.opensymphony.module.sitemesh.filter.PageResponseWrapper;
   15   
   16   import javax.servlet.RequestDispatcher;
   17   import javax.servlet.ServletException;
   18   import javax.servlet.http.HttpServletRequest;
   19   import javax.servlet.http.HttpServletResponse;
   20   import javax.servlet.jsp.JspException;
   21   import javax.servlet.jsp.tagext.BodyTagSupport;
   22   import java.io.IOException;
   23   import java.io.BufferedReader;
   24   import java.io.InputStreamReader;
   25   import java.util.HashMap;
   26   import java.util.Iterator;
   27   import java.util.Map;
   28   import java.net.URL;
   29   import java.net.URLConnection;
   30   import java.net.MalformedURLException;
   31   
   32   /**
   33    * This tag inserts an external resource as a panel into the current Page.
   34    *
   35    * <p>The page attribute should point to the panel resource
   36    * which should expose an entire page (e.g. another JSP file producing
   37    * HTML). This attribute can be relative to the page it is being called
   38    * from or an absolute path from the context-root.</p>
   39    *
   40    * <p><strong>OR</strong></p>
   41    *
   42    * <p>If the page attribute is not specified, the body content is parsed
   43    * into the {@link com.opensymphony.module.sitemesh.Page} object and has
   44    * the {@link com.opensymphony.module.sitemesh.Decorator} applied.</p>
   45    *
   46    * <p>The (optional) decorator attribute is the name of the
   47    * {@link com.opensymphony.module.sitemesh.Decorator}
   48    * to apply to the included page. Note that the implementation of
   49    * {@link com.opensymphony.module.sitemesh.DecoratorMapper} can overide this.</p>
   50    *
   51    * @author <a href="mailto:joe@truemesh.com">Joe Walnes</a>
   52    * @version $Revision: 1.6 $
   53    */
   54   public class ApplyDecoratorTag extends BodyTagSupport implements RequestConstants {
   55       private String page = null;
   56       private String decorator = null;
   57   
   58       private String contentType = null;
   59       private String encoding = null;
   60   
   61       private Map params = new HashMap(6);
   62       private Config config = null;
   63       private DecoratorMapper decoratorMapper = null;
   64       private Factory factory;
   65   
   66       /**
   67        * Tag attribute: URI of page to include.
   68        * Can be relative to page being called from, or absolute
   69        * path from context-root of web-app.
   70        */
   71       public void setPage(String page) {
   72           this.page = page;
   73       }
   74   
   75       /**
   76        * Add a parameter to the page. This has a package level
   77        * access modifier so ParamTag can also call it.
   78        */
   79       void addParam(String name, String value) {
   80           params.put(name, value);
   81       }
   82   
   83       /**
   84        * Tag attribute: If set, this value will override the 'title'
   85        * property of the page. This is a convenience utility and is
   86        * identical to specifing a 'page:param name=title' tag.
   87        */
   88       public void setTitle(String title) {
   89           addParam("title", title);
   90       }
   91   
   92       /**
   93        * Tag attribute: If set, this value will override the 'id'
   94        * property of the page. This is a convenience utility and is
   95        * identical to specifing a 'page:param name=id' tag.
   96        */
   97       public void setId(String id) {
   98           addParam("id", id);
   99       }
  100   
  101       /**
  102        * Tag attribute: Name of Decorator to apply to Page.
  103        * This is passed to DecoratorMapper to retrieve appropriate
  104        * Decorator. DecoratorMapper may override if needed.
  105        *
  106        * @see com.opensymphony.module.sitemesh.DecoratorMapper
  107        */
  108       public void setName(String decorator) {
  109           if (decorator != null) this.decorator = decorator;
  110       }
  111   
  112       /** @deprecated Use setName() instead. */
  113       public void setDecorator(String decorator) {
  114           setName(decorator);
  115       }
  116   
  117       public void setContentType(String contentType) {
  118           this.contentType = contentType;
  119       }
  120   
  121       public void setEncoding(String encoding) {
  122           this.encoding = encoding;
  123       }
  124   
  125       public int doStartTag() {
  126           if (config == null) {
  127               // set context if not already set
  128               config = new Config(pageContext.getServletConfig());
  129               factory = Factory.getInstance(config);
  130               decoratorMapper = factory.getDecoratorMapper();
  131           }
  132           // return page == null ? EVAL_BODY_BUFFERED : SKIP_BODY;
  133           return EVAL_BODY_BUFFERED;
  134       }
  135   
  136       /** Ensure that external page contents are included in bodycontent. */
  137       public int doAfterBody() throws JspException {
  138           return SKIP_BODY;
  139       }
  140   
  141       /** Standard taglib method: apply decorator to page. */
  142       public int doEndTag() throws JspException {
  143           try {
  144               // if composite decorator, remember last page
  145               Page oldPage = (Page) pageContext.getRequest().getAttribute(PAGE);
  146   
  147               // parse bodycontent into Page object
  148               PageParser parser = Factory.getInstance(config).getPageParser(contentType != null ? contentType : "text/html");
  149               Page pageObj = null;
  150   
  151               if (page == null) {
  152                   // inline content
  153                   pageObj = parser.parse(bodyContent.getString().toCharArray());
  154               }
  155               else if (page.startsWith("http://") || page.startsWith("https://")) {
  156                   try {
  157                       URL url = new URL(page);
  158                       URLConnection urlConn = url.openConnection();
  159                       urlConn.setUseCaches(true);
  160                       BufferedReader in = new BufferedReader(
  161                               new InputStreamReader(urlConn.getInputStream()));
  162   
  163                       StringBuffer sbuf = new StringBuffer();
  164                       char[] buf = new char[1000];
  165                       for (; ;) {
  166                           int moved = in.read(buf);
  167                           if (moved < 0) break;
  168                           sbuf.append(buf, 0, moved);
  169                       }
  170                       in.close();
  171                       pageObj = parser.parse(sbuf.toString().toCharArray());
  172                   }
  173                   catch (MalformedURLException e) {
  174                       trace(e);
  175                       throw new JspException(e.toString());
  176                   }
  177                   catch (IOException e) {
  178                       trace(e);
  179                       throw new JspException(e.toString());
  180                   }
  181               }
  182               else {
  183                   // external content
  184                   String fullPath = page;
  185                   if (fullPath.length() > 0 && fullPath.charAt(0) != '/') {
  186                       HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
  187   
  188                       // find absolute path if relative supplied
  189                       String thisPath = request.getServletPath();
  190   
  191                       // check if it did not return null (could occur when the servlet container
  192                       // does not use a servlet to serve the requested resouce)
  193                       if (thisPath == null) {
  194                           String requestURI = request.getRequestURI();
  195                           if (request.getPathInfo() != null) {
  196                               // strip the pathInfo from the requestURI
  197                               thisPath = requestURI.substring(0, requestURI.indexOf(request.getPathInfo()));
  198                           }
  199                           else {
  200                               thisPath = requestURI;
  201                           }
  202                       }
  203   
  204                       fullPath = thisPath.substring(0, thisPath.lastIndexOf('/') + 1) + fullPath;
  205                       int dotdot;
  206                       while ((dotdot = fullPath.indexOf("..")) > -1) {
  207                           int prevSlash = fullPath.lastIndexOf('/', dotdot - 2);
  208                           fullPath = fullPath.substring(0, prevSlash) + fullPath.substring(dotdot + 2);
  209                       }
  210                   }
  211   
  212                   // include page using filter response
  213                   RequestDispatcher rd = pageContext.getServletContext().getRequestDispatcher(fullPath);
  214                   PageRequestWrapper pageRequest = new PageRequestWrapper((HttpServletRequest) pageContext.getRequest());
  215                   PageResponseWrapper pageResponse = new PageResponseWrapper((HttpServletResponse) pageContext.getResponse(), factory);
  216   
  217                   StringBuffer sb = new StringBuffer(contentType != null ? contentType : "text/html");
  218                   if (encoding != null) {
  219                       sb.append(";charset=").append(encoding);
  220                   }
  221                   pageResponse.setContentType(sb.toString());
  222   
  223                   // if rd == null, then the panel was not found, but this isn't correct, so we need to spit out
  224                   // something appropriate. What this is, well...I don't know yet.
  225                   if (rd == null) {
  226                       throw new ApplyDecoratorException("The specified resource in applyDecorator tag (" + fullPath + ") was not found.");
  227                   }
  228                   rd.include(pageRequest, pageResponse);
  229                   pageObj = pageResponse.getPage();
  230               }
  231   
  232               // If pageObj == null, then the panel source had some weird error in
  233               // it. Stop writing bugs like this. They're ugly and they make you smell funny.
  234               if (pageObj == null) {
  235                   throw new ApplyDecoratorException(page + " did not create a valid page to decorate.");
  236               }
  237   
  238               // add extra params to Page
  239               Iterator paramKeys = params.keySet().iterator();
  240               while (paramKeys.hasNext()) {
  241                   String k = (String) paramKeys.next();
  242                   String v = (String) params.get(k);
  243                   pageObj.addProperty(k, v);
  244               }
  245   
  246               // get decorator
  247               if (decorator == null) decorator = "";
  248               pageObj.setRequest((HttpServletRequest) pageContext.getRequest());
  249               pageContext.getRequest().setAttribute(DECORATOR, decorator);
  250               Decorator d = decoratorMapper.getDecorator(((HttpServletRequest) pageContext.getRequest()), pageObj);
  251               pageContext.getRequest().removeAttribute(DECORATOR);
  252   
  253               // apply decorator
  254               if (d != null && d.getPage() != null) {
  255                   pageContext.getRequest().setAttribute(PAGE, pageObj);
  256                   pageContext.include(d.getPage());
  257               }
  258               else {
  259                   throw new JspException("Cannot locate inline Decorator: " + decorator);
  260               }
  261   
  262               // clean up
  263               pageContext.getRequest().setAttribute(PAGE, oldPage);
  264           }
  265           catch (IOException e) {
  266               trace(e);
  267               throw new JspException(e.toString());
  268           }
  269           catch (ServletException e) {
  270               trace(e);
  271               throw new JspException(e.toString());
  272           }
  273           catch (ApplyDecoratorException e) {
  274               try {
  275                   pageContext.getOut().println(e.getMessage());
  276               }
  277               catch (IOException ioe) {
  278                   System.err.println("IOException thrown in applyDecorator tag: " + e.toString());
  279               }
  280           }
  281           return EVAL_PAGE;
  282       }
  283   
  284       /** Release all attributes */
  285       public void release() {
  286           params.clear();
  287           super.release();
  288       }
  289   
  290       /** Log exception generated by taglib. */
  291       public static void trace(Exception e) {
  292           e.printStackTrace();
  293       }
  294   
  295       class ApplyDecoratorException extends Exception {
  296           public ApplyDecoratorException(String s) {
  297               super(s);
  298           }
  299       }
  300   }

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