001    /* 
002     * This file is part of the Echo Point Project.  This project is a collection
003     * of Components that have extended the Echo Web Application Framework.
004     *
005     * Version: MPL 1.1/GPL 2.0/LGPL 2.1
006     *
007     * The contents of this file are subject to the Mozilla Public License Version
008     * 1.1 (the "License"); you may not use this file except in compliance with
009     * the License. You may obtain a copy of the License at
010     * http://www.mozilla.org/MPL/
011     *
012     * Software distributed under the License is distributed on an "AS IS" basis,
013     * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
014     * for the specific language governing rights and limitations under the
015     * License.
016     *
017     * Alternatively, the contents of this file may be used under the terms of
018     * either the GNU General Public License Version 2 or later (the "GPL"), or
019     * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
020     * in which case the provisions of the GPL or the LGPL are applicable instead
021     * of those above. If you wish to allow use of your version of this file only
022     * under the terms of either the GPL or the LGPL, and not to allow others to
023     * use your version of this file under the terms of the MPL, indicate your
024     * decision by deleting the provisions above and replace them with the notice
025     * and other provisions required by the GPL or the LGPL. If you do not delete
026     * the provisions above, a recipient may use your version of this file under
027     * the terms of any one of the MPL, the GPL or the LGPL.
028     */
029    package echopoint.template.ui;
030    
031    import java.io.*;
032    
033    import javax.servlet.Servlet;
034    import javax.servlet.ServletException;
035    import javax.servlet.http.HttpServletRequest;
036    import javax.servlet.http.HttpServletResponse;
037    import javax.servlet.jsp.JspFactory;
038    import javax.servlet.jsp.JspWriter;
039    import javax.servlet.jsp.PageContext;
040    
041    import nextapp.echo.webcontainer.Connection;
042    
043    import org.w3c.dom.Element;
044    
045    import echopoint.template.JspTemplateDataSource;
046    import echopoint.template.TemplateDataSource;
047    import echopoint.util.io.CapturedHttpServletResponse;
048    import echopoint.util.throwable.ThrowableKit;
049    
050    /** 
051     * <code>JspXHTMLTemplateCompiler</code> can compile
052     * XHTML source template data from JSP page
053     * into a XHTML DO Element.
054     */
055    
056    public class JspXHTMLTemplateCompiler extends XHTMLTemplateCompiler {
057    
058            /**
059             * @see echopoint.template.ui.TemplateCompiler#compileTemplateDataIntoXHTML(nextapp.echo.webcontainer.Connection, echopoint.template.TemplateDataSource)
060             */
061            public Element compileTemplateDataIntoXHTML(Connection c, TemplateDataSource tds) throws Exception {
062                    // we dont use the TDS input stream because it does know 
063                    // where to get the stream
064                    InputStream inputStream = jspExecute(c,(JspTemplateDataSource) tds);
065            return compileXHTML(inputStream,tds);
066            }
067    
068        public String templateDataAsString(Connection c, TemplateDataSource tds) throws Exception {
069            InputStream inputStream = jspExecute(c,(JspTemplateDataSource) tds);
070            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
071            StringBuilder sb = new StringBuilder();
072    
073            String line = null;
074            try {
075                while ((line = reader.readLine()) != null) {
076                    sb.append(line + "\n");
077                }
078            } finally {
079                    inputStream.close();
080            }
081    
082            return sb.toString();
083    
084        }
085            
086            /**
087             * Executes a JSP page for a given JspTemplateDataSource.  The content
088             * of the JSP page is captured and is ready for XHTML parsing afterwards
089             * 
090             * @param c - connection
091             * @param jspTemplateDataSource - datasource 
092             * @return an InputStream of the captured JSP output
093             */
094            private InputStream jspExecute(Connection c, JspTemplateDataSource jspTemplateDataSource) {
095                    String jspPath  = jspTemplateDataSource.getJspPath();
096                    Servlet servlet = c.getServlet();
097                    HttpServletRequest request = c.getRequest();
098                    HttpServletResponse wrappedResponse = c.getResponse();
099                    CapturedHttpServletResponse response = new CapturedHttpServletResponse(wrappedResponse,jspTemplateDataSource.getCharacterEncoding());
100                    
101                    String requestAttributes[] = jspTemplateDataSource.getAttributeNames();
102                    try {
103                            //
104                            // setup Request variables from the JspTemplateDataSource
105                            for (int i = 0; i < requestAttributes.length; i++) {
106                                    String name = requestAttributes[i];
107                                    request.setAttribute(name,jspTemplateDataSource.getAttribute(name));
108                            }
109                            //
110                            // and get the content into out captured response
111                            jspInclude(true,jspPath,servlet,request,response);
112                    } finally {
113                            //
114                            // tear down Request variables 
115                            for (int i = 0; i < requestAttributes.length; i++) {
116                                    String name = requestAttributes[i];
117                                    request.removeAttribute(name);
118                            }
119                    }
120                    
121                    //
122                    // now we have captured the JSP output, we need to reverse that
123                    // and return it as an InputStream.
124                    return response.getCapturedInputStream();
125            }
126            
127            /**
128             * Include the JSP template content by using the PageContext.include mechanism
129             */
130            private void jspInclude(boolean isLoudErrorsUsed, String jspPath, Servlet servlet, HttpServletRequest request, HttpServletResponse response) {
131                    JspFactory factory = null;
132                    PageContext pc = null;
133                    PrintWriter out = null;
134                    try {
135                            out = response.getWriter();
136                            factory = JspFactory.getDefaultFactory();
137    
138                            pc = factory.getPageContext(servlet, request, response, null, true, JspWriter.NO_BUFFER, true);
139    
140                            if (pc != null) {
141                                    ///////////////////////////////////////////////
142                                    // include the page
143                                    ///////////////////////////////////////////////
144                                    pc.include(jspPath);
145    
146                                    factory.releasePageContext(pc);
147                                    pc = null;
148                                    
149                            } else {
150                                    ///////////////////////////////////////////////
151                                    // we have no page context, it cant be output
152                                    ///////////////////////////////////////////////
153                                    throw new ServletException("Unable to obtain JSP PageContext object");
154                            }
155                    } catch (ServletException e) {
156                            if (isLoudErrorsUsed) {
157                                    out.println("<div style=\"background:red;color:white;font-size:12;border-width:1; border-style:solid; border-color:black; padding:4; margin:4\" >");
158                                    out.println("<blink><b>");
159                                    out.println("<p>JSP Exception : '<em>" + e + "</em>'</p>");
160                                    out.println("</b></blink></div>");
161                            } else {
162                                    out.println("<!-- ");
163                                    out.println("JSP Exception : '" + e + "'");
164                                    out.println(" -->");
165                            }
166                    } catch (IOException e) {
167                            throw ThrowableKit.makeRuntimeException(e);
168                    } finally {
169                            // cleanup the factory and page context
170                            if (factory != null && pc != null)
171                                    factory.releasePageContext(pc);
172                    }
173            }
174                    
175    
176    }