/* * Copyright (C) 2000 - 2008 TagServlet Ltd * * This file is part of Open BlueDragon (OpenBD) CFML Server Engine. * * OpenBD is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * Free Software Foundation,version 3. * * OpenBD is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenBD. If not, see http://www.gnu.org/licenses/ * * Additional permission under GNU GPL version 3 section 7 * * If you modify this Program, or any covered work, by linking or combining * it with any of the JARS listed in the README.txt (or a modified version of * (that library), containing parts covered by the terms of that JAR, the * licensors of this Program grant you additional permission to convey the * resulting work. * README.txt @ http://www.openbluedragon.org/license/README.txt * * http://www.openbluedragon.org/ */ package com.naryx.tagfusion.servlet.jsp; import java.io.IOException; import javax.servlet.RequestDispatcher; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpSession; import com.naryx.tagfusion.cfm.engine.catchDataFactory; import com.naryx.tagfusion.cfm.engine.cfCatchData; import com.naryx.tagfusion.cfm.engine.cfSession; import com.naryx.tagfusion.cfm.engine.cfmAbortException; import com.naryx.tagfusion.cfm.engine.cfmRunTimeException; //import javax.servlet.jsp.*; /** * This class is modelled to be a subclass of javax.servlet.jsp.PageContext, * but it's not because we don't really want to support all of the abstract * methods defined by PageContext. Also, we need to change the signatures of * the forward() and include() methods to throw cfmRunTimeException, which we * can't do if this class extends PageContext. * * The PageContext abstract methods are still here (commented-out), in case we * ever decide that we need or want to implement any of them. */ public class CfmlPageContext //extends PageContext { private cfSession _session; private CfmlJspWriter writer; public CfmlPageContext( cfSession session ) { _session = session; writer = new CfmlJspWriter(_session); } /** * <p> * The initialize method is called to initialize an uninitialized PageContext * so that it may be used by a JSP Implementation class to service an * incoming request and response within it's _jspService() method. * * <p> * This method is typically called from JspFactory.getPageContext() in * order to initialize state. * * <p> * This method is required to create an initial JspWriter, and associate * the "out" name in page scope with this newly created object. * * <p> * This method should not be used by page or tag library authors. * * @param servlet The Servlet that is associated with this PageContext * @param request The currently pending request for this Servlet * @param response The currently pending response for this Servlet * @param errorPageURL The value of the errorpage attribute from the page directive or null * @param needsSession The value of the session attribute from the page directive * @param bufferSize The value of the buffer attribute from the page directive * @param autoFlush The value of the autoflush attribute from the page directive * * @throws IOException during creation of JspWriter * @throws IllegalStateException if out not correctly initialized */ // public void initialize( Servlet servlet, ServletRequest request, ServletResponse response, // String errorPageURL, boolean needsSession, int bufferSize, // boolean autoFlush) throws IllegalStateException // { // } /** * <p> * This method shall "reset" the internal state of a PageContext, releasing * all internal references, and preparing the PageContext for potential * reuse by a later invocation of initialize(). This method is typically * called from JspFactory.releasePageContext(). * * <p> * Subclasses shall envelope this method. * * <p> * This method should not be used by page or tag library authors. * */ // public void release() // { // _session = null; // } /** * Register the name and object specified with page scope semantics. * * @param name the name of the attribute to set * @param attribute the object to associate with the name * * @throws NullPointerException if the name or object is null */ // public void setAttribute( String name, Object attribute ) // { // } /** * register the name and object specified with appropriate scope semantics * * @param name the name of the attribute to set * @param o the object to associate with the name * @param scope the scope with which to associate the name/object * * @throws NullPointerException if the name or object is null * @throws IllegalArgumentException if the scope is invalid * */ // public void setAttribute( String name, Object o, int scope ) // { // } /** * Return the object associated with the name in the page scope or null * if not found. * * @param name the name of the attribute to get * * @throws NullPointerException if the name is null * @throws IllegalArgumentException if the scope is invalid */ // public Object getAttribute( String name ) // { // return null; // } /** * Return the object associated with the name in the specified * scope or null if not found. * * @param name the name of the attribute to set * @param scope the scope with which to associate the name/object * * @throws NullPointerException if the name is null * @throws IllegalArgumentException if the scope is invalid */ // public Object getAttribute( String name, int scope ) // { // return null; // } /** * Searches for the named attribute in page, request, session (if valid), * and application scope(s) in order and returns the value associated or * null. * * @return the value associated or null */ // public Object findAttribute( String name ) // { // return null; // } /** * Remove the object reference associated with the given name, * look in all scopes in the scope order. * * @param name The name of the object to remove. */ // public void removeAttribute( String name ) // { // } /** * Remove the object reference associated with the specified name * in the given scope. * * @param name The name of the object to remove. * @param scope The scope where to look. */ // public void removeAttribute( String name, int scope ) // { // } /** * Get the scope where a given attribute is defined. * * @return the scope of the object associated with the name specified or 0 */ // public int getAttributesScope( String name ) // { // return -1; // } /** * Enumerate all the attributes in a given scope * * @return an enumeration of names (java.lang.String) of all the attributes the specified scope */ // public Enumeration getAttributeNamesInScope( int scope ) // { // return null; // } /** * The current value of the out object (a JspWriter). * * @return the current JspWriter stream being used for client response */ public CfmlJspWriter getOut() { return writer; } /** * The current value of the session object (an HttpSession). * * @return the HttpSession for this PageContext or null */ public HttpSession getSession() { return _session.REQ.getSession(); } /** * The current value of the page object (a Servlet). * * @return the Page implementation class instance (Servlet) associated with this PageContext */ // public Object getPage() // { // return null; // } /** * The current value of the request object (a ServletRequest). * * @return The ServletRequest for this PageContext */ public ServletRequest getRequest() { return _session.REQ; } /** * The current value of the response object (a ServletResponse). * * @return the ServletResponse for this PageContext */ public ServletResponse getResponse() { return _session.RES; } /** * The current value of the exception object (an Exception). * * @return any exception passed to this as an errorpage */ // public Exception getException() // { // return null; // } /** * The ServletConfig instance. * * @return the ServletConfig for this PageContext */ // public ServletConfig getServletConfig() // { // return null; // } /** * The ServletContext instance. * * @return the ServletContext for this PageContext */ public ServletContext getServletContext() { return _session.CTX; } /** * <p> * This method is used to re-direct, or "forward" the current ServletRequest and ServletResponse to another * active component in the application. * </p> * <p> * If the <I> relativeUrlPath </I> begins with a "/" then the URL specified * is calculated relative to the DOCROOT of the <code> ServletContext </code> * for this JSP. If the path does not begin with a "/" then the URL * specified is calculated relative to the URL of the request that was * mapped to the calling JSP. * </p> * <p> * It is only valid to call this method from a <code> Thread </code> * executing within a <code> _jspService(...) </code> method of a JSP. * </p> * <p> * Once this method has been called successfully, it is illegal for the * calling <code> Thread </code> to attempt to modify the <code> * ServletResponse </code> object. Any such attempt to do so, shall result * in undefined behavior. Typically, callers immediately return from * <code> _jspService(...) </code> after calling this method. * </p> * * @param relativeUrlPath specifies the relative URL path to the target resource as described above * * @throws ServletException * @throws IOException * * @throws IllegalArgumentException if target resource URL is unresolvable * @throws IllegalStateException if <code> ServletResponse </code> is not in a state where a forward can be performed * @throws SecurityException if target resource cannot be accessed by caller */ public void forward( String relativeUrlPath ) throws cfmRunTimeException //ServletException { /** * From the JSP 2.0 spec on <jsp:forward/> : * * (1) If the page output is buffered, the buffer is cleared prior to forwarding. * (2) If the page output is buffered and the buffer was flushed, an attempt to * forward the request will result in an IllegalStateException. * (3) If the page output was unbuffered and anything has been written to it, an * attempt to forward the request will result in an IllegalStateException. * * These conditions are handled by the RequestDispatcher.forward() method, * (note that item 3 doesn't apply to us since we're always buffered). */ //--[ Attempt to get the RequestDispatcher RequestDispatcher rd = _session.REQ.getRequestDispatcher( relativeUrlPath ); if ( rd == null ) { throw new cfmRunTimeException( catchDataFactory.generalException( "errorCode.runtimeError", "cfinclude.missingFile", new String[]{relativeUrlPath} ) ); } try { rd.forward( _session.REQ, _session.RES.getResponse() ); _session.abortAfterForward(); // throws cfmAbortException } catch ( cfmAbortException aE ) { throw aE; // catch and rethrow here so it's not caught as Exception below } catch ( IllegalStateException iE ) { cfCatchData catchData = new cfCatchData(); catchData.setType( cfCatchData.TYPE_TEMPLATE ); catchData.setDetail( "Unable to forward request because the page has been flushed" ); catchData.setMessage( "Cannot forward request" ); throw new cfmRunTimeException( catchData ); } catch ( Exception sE ) { // ServletException, IOException throw new cfmRunTimeException( catchDataFactory.extendedException( "errorCode.runtimeError", "cfinclude.pageExecution", new String[]{relativeUrlPath}, sE.getMessage()) ); } } /** * <p> * Causes the resource specified to be processed as part of the current * ServletRequest and ServletResponse being processed by the calling Thread. * The output of the target resources processing of the request is written * directly to the ServletResponse output stream. * </p> * <p> * The current JspWriter "out" for this JSP is flushed as a side-effect * of this call, prior to processing the include. * </p> * <p> * If the <I> relativeUrlPath </I> begins with a "/" then the URL specified * is calculated relative to the DOCROOT of the <code> ServletContext </code> * for this JSP. If the path does not begin with a "/" then the URL * specified is calculated relative to the URL of the request that was * mapped to the calling JSP. * </p> * <p> * It is only valid to call this method from a <code> Thread </code> * executing within a <code> _jspService(...) </code> method of a JSP. * </p> * * @param relativeUrlPath specifies the relative URL path to the target resource to be included * * @throws ServletException * @throws IOException * * @throws IllegalArgumentException if the target resource URL is unresolvable * @throws SecurityException if target resource cannot be accessed by caller * */ public void include( String relativeUrlPath ) throws cfmRunTimeException //ServletException, IOException { //--[ Attempt to get the RequestDispatcher RequestDispatcher rd = _session.REQ.getRequestDispatcher( relativeUrlPath ); if ( rd == null ) { throw new cfmRunTimeException( catchDataFactory.generalException( "errorCode.runtimeError", "cfinclude.missingFile", new String[]{relativeUrlPath} ) ); } //---[ Now that the servlet has been found, trigger its execution try { _session.RES.setJspInclude( true ); _session.REQ.setAttribute( cfSession.ATTR_NAME, _session ); rd.include( _session.REQ, _session.RES ); } catch ( ServletException se ) { try { // this is for WebLogic: try passing the original response object _session.RES.setJspInclude( false ); _session.pageFlush(); rd.include( _session.REQ, _session.RES.getResponse() ); } catch ( ServletException e ) { throwIncludeError( e, relativeUrlPath ); } catch ( IOException e ) { throwIncludeError( e, relativeUrlPath ); } } catch ( IOException e ) { throwIncludeError( e, relativeUrlPath ); } finally { _session.REQ.removeAttribute( cfSession.ATTR_NAME ); _session.RES.setJspInclude( false ); } } private static void throwIncludeError( Exception e, String relativeUrlPath ) throws cfmRunTimeException { throw new cfmRunTimeException( catchDataFactory.extendedException( "errorCode.runtimeError", "cfinclude.pageExecution", new String[]{relativeUrlPath}, e.getMessage()) ); } /** * <p> * This method is intended to process an unhandled "page" level exception * by redirecting the exception to either the specified error page for this * JSP, or if none was specified, to perform some implementation dependent * action. * * <p> * A JSP implementation class shall typically clean up any local state * prior to invoking this and will return immediately thereafter. It is * illegal to generate any output to the client, or to modify any * ServletResponse state after invoking this call. * * <p> * This method is kept for backwards compatiblity reasons. Newly * generated code should use PageContext.handlePageException(Throwable). * * @param e the exception to be handled * * @throws ServletException * @throws IOException * * @throws NullPointerException if the exception is null * @throws SecurityException if target resource cannot be accessed by caller * * @see #handlePageException(Throwable) */ // public void handlePageException( Exception e ) throws ServletException, IOException // { // throw new ServletException( "Not Implemented" ); // } /** * <p> * This method is identical to the handlePageException(Exception), * except that it accepts a Throwable. This is the preferred method * to use as it allows proper implementation of the errorpage * semantics. * * <p> * This method is intended to process an unhandled "page" level exception * by redirecting the exception to either the specified error page for this * JSP, or if none was specified, to perform some implementation dependent * action. * * <p> * A JSP implementation class shall typically clean up any local state * prior to invoking this and will return immediately thereafter. It is * illegal to generate any output to the client, or to modify any * ServletResponse state after invoking this call. * * @param t the throwable to be handled * * @throws ServletException * @throws IOException * * @throws NullPointerException if the exception is null * @throws SecurityException if target resource cannot be accessed by caller * * @see #handlePageException(Exception) */ // public void handlePageException(Throwable t) throws ServletException, IOException // { // throw new ServletException( "Not Implemented" ); // } }