| /* |
| * Copyright 1999,2004 The Apache Software Foundation. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.jasper.runtime; |
| |
| import java.io.IOException; |
| import java.io.Writer; |
| import java.util.ArrayList; |
| import java.util.Enumeration; |
| import java.util.Hashtable; |
| import java.util.Iterator; |
| import java.util.Map; |
| |
| import javax.servlet.Servlet; |
| import javax.servlet.ServletConfig; |
| import javax.servlet.ServletContext; |
| import javax.servlet.ServletException; |
| import javax.servlet.ServletRequest; |
| import javax.servlet.ServletResponse; |
| import javax.servlet.http.HttpSession; |
| import javax.servlet.jsp.JspContext; |
| import javax.servlet.jsp.JspWriter; |
| import javax.servlet.jsp.PageContext; |
| import javax.servlet.jsp.el.ELException; |
| import javax.servlet.jsp.el.ExpressionEvaluator; |
| import javax.servlet.jsp.el.VariableResolver; |
| import javax.servlet.jsp.tagext.BodyContent; |
| import javax.servlet.jsp.tagext.VariableInfo; |
| |
| import org.apache.commons.el.VariableResolverImpl; |
| import org.apache.jasper.compiler.Localizer; |
| |
| /** |
| * Implementation of a JSP Context Wrapper. |
| * |
| * The JSP Context Wrapper is a JspContext created and maintained by a tag |
| * handler implementation. It wraps the Invoking JSP Context, that is, the |
| * JspContext instance passed to the tag handler by the invoking page via |
| * setJspContext(). |
| * |
| * @author Kin-man Chung |
| * @author Jan Luehe |
| */ |
| public class JspContextWrapper |
| extends PageContext implements VariableResolver { |
| |
| // Invoking JSP context |
| private PageContext invokingJspCtxt; |
| |
| private transient Hashtable pageAttributes; |
| |
| // ArrayList of NESTED scripting variables |
| private ArrayList nestedVars; |
| |
| // ArrayList of AT_BEGIN scripting variables |
| private ArrayList atBeginVars; |
| |
| // ArrayList of AT_END scripting variables |
| private ArrayList atEndVars; |
| |
| private Map aliases; |
| |
| private Hashtable originalNestedVars; |
| |
| /** |
| * The variable resolver, for evaluating EL expressions. |
| */ |
| private VariableResolverImpl variableResolver |
| = new VariableResolverImpl(this); |
| |
| public JspContextWrapper(JspContext jspContext, ArrayList nestedVars, |
| ArrayList atBeginVars, ArrayList atEndVars, |
| Map aliases) { |
| this.invokingJspCtxt = (PageContext) jspContext; |
| this.nestedVars = nestedVars; |
| this.atBeginVars = atBeginVars; |
| this.atEndVars = atEndVars; |
| this.pageAttributes = new Hashtable(16); |
| this.aliases = aliases; |
| |
| if (nestedVars != null) { |
| this.originalNestedVars = new Hashtable(nestedVars.size()); |
| } |
| syncBeginTagFile(); |
| } |
| |
| public void initialize(Servlet servlet, ServletRequest request, |
| ServletResponse response, String errorPageURL, |
| boolean needsSession, int bufferSize, |
| boolean autoFlush) |
| throws IOException, IllegalStateException, IllegalArgumentException |
| { |
| } |
| |
| public Object getAttribute(String name) { |
| |
| if (name == null) { |
| throw new NullPointerException( |
| Localizer.getMessage("jsp.error.attribute.null_name")); |
| } |
| |
| return pageAttributes.get(name); |
| } |
| |
| public Object getAttribute(String name, int scope) { |
| |
| if (name == null) { |
| throw new NullPointerException( |
| Localizer.getMessage("jsp.error.attribute.null_name")); |
| } |
| |
| if (scope == PAGE_SCOPE) { |
| return pageAttributes.get(name); |
| } |
| |
| return invokingJspCtxt.getAttribute(name, scope); |
| } |
| |
| public void setAttribute(String name, Object value) { |
| |
| if (name == null) { |
| throw new NullPointerException( |
| Localizer.getMessage("jsp.error.attribute.null_name")); |
| } |
| |
| if (value != null) { |
| pageAttributes.put(name, value); |
| } else { |
| removeAttribute(name, PAGE_SCOPE); |
| } |
| } |
| |
| public void setAttribute(String name, Object value, int scope) { |
| |
| if (name == null) { |
| throw new NullPointerException( |
| Localizer.getMessage("jsp.error.attribute.null_name")); |
| } |
| |
| if (scope == PAGE_SCOPE) { |
| if (value != null) { |
| pageAttributes.put(name, value); |
| } else { |
| removeAttribute(name, PAGE_SCOPE); |
| } |
| } else { |
| invokingJspCtxt.setAttribute(name, value, scope); |
| } |
| } |
| |
| public Object findAttribute(String name) { |
| |
| if (name == null) { |
| throw new NullPointerException( |
| Localizer.getMessage("jsp.error.attribute.null_name")); |
| } |
| |
| Object o = pageAttributes.get(name); |
| if (o == null) { |
| o = invokingJspCtxt.getAttribute(name, REQUEST_SCOPE); |
| if (o == null) { |
| if (getSession() != null) { |
| o = invokingJspCtxt.getAttribute(name, SESSION_SCOPE); |
| } |
| if (o == null) { |
| o = invokingJspCtxt.getAttribute(name, APPLICATION_SCOPE); |
| } |
| } |
| } |
| |
| return o; |
| } |
| |
| public void removeAttribute(String name) { |
| |
| if (name == null) { |
| throw new NullPointerException( |
| Localizer.getMessage("jsp.error.attribute.null_name")); |
| } |
| |
| pageAttributes.remove(name); |
| invokingJspCtxt.removeAttribute(name, REQUEST_SCOPE); |
| if (getSession() != null) { |
| invokingJspCtxt.removeAttribute(name, SESSION_SCOPE); |
| } |
| invokingJspCtxt.removeAttribute(name, APPLICATION_SCOPE); |
| } |
| |
| public void removeAttribute(String name, int scope) { |
| |
| if (name == null) { |
| throw new NullPointerException( |
| Localizer.getMessage("jsp.error.attribute.null_name")); |
| } |
| |
| if (scope == PAGE_SCOPE){ |
| pageAttributes.remove(name); |
| } else { |
| invokingJspCtxt.removeAttribute(name, scope); |
| } |
| } |
| |
| public int getAttributesScope(String name) { |
| |
| if (name == null) { |
| throw new NullPointerException( |
| Localizer.getMessage("jsp.error.attribute.null_name")); |
| } |
| |
| if (pageAttributes.get(name) != null) { |
| return PAGE_SCOPE; |
| } else { |
| return invokingJspCtxt.getAttributesScope(name); |
| } |
| } |
| |
| public Enumeration getAttributeNamesInScope(int scope) { |
| if (scope == PAGE_SCOPE) { |
| return pageAttributes.keys(); |
| } |
| |
| return invokingJspCtxt.getAttributeNamesInScope(scope); |
| } |
| |
| public void release() { |
| invokingJspCtxt.release(); |
| } |
| |
| public JspWriter getOut() { |
| return invokingJspCtxt.getOut(); |
| } |
| |
| public HttpSession getSession() { |
| return invokingJspCtxt.getSession(); |
| } |
| |
| public Object getPage() { |
| return invokingJspCtxt.getPage(); |
| } |
| |
| public ServletRequest getRequest() { |
| return invokingJspCtxt.getRequest(); |
| } |
| |
| public ServletResponse getResponse() { |
| return invokingJspCtxt.getResponse(); |
| } |
| |
| public Exception getException() { |
| return invokingJspCtxt.getException(); |
| } |
| |
| public ServletConfig getServletConfig() { |
| return invokingJspCtxt.getServletConfig(); |
| } |
| |
| public ServletContext getServletContext() { |
| return invokingJspCtxt.getServletContext(); |
| } |
| |
| public void forward(String relativeUrlPath) |
| throws ServletException, IOException |
| { |
| invokingJspCtxt.forward(relativeUrlPath); |
| } |
| |
| public void include(String relativeUrlPath) |
| throws ServletException, IOException |
| { |
| invokingJspCtxt.include(relativeUrlPath); |
| } |
| |
| public void include(String relativeUrlPath, boolean flush) |
| throws ServletException, IOException { |
| include(relativeUrlPath, false); // XXX |
| } |
| |
| public VariableResolver getVariableResolver() { |
| return this; |
| } |
| |
| public BodyContent pushBody() { |
| return invokingJspCtxt.pushBody(); |
| } |
| |
| public JspWriter pushBody(Writer writer) { |
| return invokingJspCtxt.pushBody(writer); |
| } |
| |
| public JspWriter popBody() { |
| return invokingJspCtxt.popBody(); |
| } |
| |
| public ExpressionEvaluator getExpressionEvaluator() { |
| return invokingJspCtxt.getExpressionEvaluator(); |
| } |
| |
| public void handlePageException(Exception ex) |
| throws IOException, ServletException |
| { |
| // Should never be called since handleException() called with a |
| // Throwable in the generated servlet. |
| handlePageException((Throwable) ex); |
| } |
| |
| public void handlePageException(Throwable t) |
| throws IOException, ServletException |
| { |
| invokingJspCtxt.handlePageException(t); |
| } |
| |
| /** |
| * VariableResolver interface |
| */ |
| public Object resolveVariable( String pName ) throws ELException |
| { |
| return variableResolver.resolveVariable(pName); |
| } |
| |
| /** |
| * Synchronize variables at begin of tag file |
| */ |
| public void syncBeginTagFile() { |
| saveNestedVariables(); |
| } |
| |
| /** |
| * Synchronize variables before fragment invokation |
| */ |
| public void syncBeforeInvoke() { |
| copyTagToPageScope(VariableInfo.NESTED); |
| copyTagToPageScope(VariableInfo.AT_BEGIN); |
| } |
| |
| /** |
| * Synchronize variables at end of tag file |
| */ |
| public void syncEndTagFile() { |
| copyTagToPageScope(VariableInfo.AT_BEGIN); |
| copyTagToPageScope(VariableInfo.AT_END); |
| restoreNestedVariables(); |
| } |
| |
| /** |
| * Copies the variables of the given scope from the virtual page scope of |
| * this JSP context wrapper to the page scope of the invoking JSP context. |
| * |
| * @param scope variable scope (one of NESTED, AT_BEGIN, or AT_END) |
| */ |
| private void copyTagToPageScope(int scope) { |
| Iterator iter = null; |
| |
| switch (scope) { |
| case VariableInfo.NESTED: |
| if (nestedVars != null) { |
| iter = nestedVars.iterator(); |
| } |
| break; |
| case VariableInfo.AT_BEGIN: |
| if (atBeginVars != null) { |
| iter = atBeginVars.iterator(); |
| } |
| break; |
| case VariableInfo.AT_END: |
| if (atEndVars != null) { |
| iter = atEndVars.iterator(); |
| } |
| break; |
| } |
| |
| while ((iter != null) && iter.hasNext()) { |
| String varName = (String) iter.next(); |
| Object obj = getAttribute(varName); |
| varName = findAlias(varName); |
| if (obj != null) { |
| invokingJspCtxt.setAttribute(varName, obj); |
| } else { |
| invokingJspCtxt.removeAttribute(varName, PAGE_SCOPE); |
| } |
| } |
| } |
| |
| /** |
| * Saves the values of any NESTED variables that are present in |
| * the invoking JSP context, so they can later be restored. |
| */ |
| private void saveNestedVariables() { |
| if (nestedVars != null) { |
| Iterator iter = nestedVars.iterator(); |
| while (iter.hasNext()) { |
| String varName = (String) iter.next(); |
| varName = findAlias(varName); |
| Object obj = invokingJspCtxt.getAttribute(varName); |
| if (obj != null) { |
| originalNestedVars.put(varName, obj); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Restores the values of any NESTED variables in the invoking JSP |
| * context. |
| */ |
| private void restoreNestedVariables() { |
| if (nestedVars != null) { |
| Iterator iter = nestedVars.iterator(); |
| while (iter.hasNext()) { |
| String varName = (String) iter.next(); |
| varName = findAlias(varName); |
| Object obj = originalNestedVars.get(varName); |
| if (obj != null) { |
| invokingJspCtxt.setAttribute(varName, obj); |
| } else { |
| invokingJspCtxt.removeAttribute(varName, PAGE_SCOPE); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Checks to see if the given variable name is used as an alias, and if so, |
| * returns the variable name for which it is used as an alias. |
| * |
| * @param varName The variable name to check |
| * @return The variable name for which varName is used as an alias, or |
| * varName if it is not being used as an alias |
| */ |
| private String findAlias(String varName) { |
| |
| if (aliases == null) |
| return varName; |
| |
| String alias = (String) aliases.get(varName); |
| if (alias == null) { |
| return varName; |
| } |
| return alias; |
| } |
| } |
| |