All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.jasper.runtime.JspContextWrapper Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 static org.apache.jasper.JasperMessages.MESSAGES;

import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.el.ELContext;
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;


/**
 * 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
 * @author Jacob Hookom
 */
@SuppressWarnings("deprecation") // Have to support old JSP EL API
public class JspContextWrapper extends PageContext implements VariableResolver {

	// Invoking JSP context
    private final PageContext invokingJspCtxt;

    private final transient HashMap pageAttributes;

	// ArrayList of NESTED scripting variables
    private final ArrayList nestedVars;

	// ArrayList of AT_BEGIN scripting variables
    private final ArrayList atBeginVars;

	// ArrayList of AT_END scripting variables
    private final ArrayList atEndVars;

    private final Map aliases;

    private final HashMap originalNestedVars;

    private ServletContext servletContext = null;

    private ELContext elContext = null;

    private final PageContext rootJspCtxt;

    public JspContextWrapper(JspContext jspContext,
            ArrayList nestedVars, ArrayList atBeginVars,
            ArrayList atEndVars, Map aliases) {
		this.invokingJspCtxt = (PageContext) jspContext;
        if (jspContext instanceof JspContextWrapper) {
            rootJspCtxt = ((JspContextWrapper)jspContext).rootJspCtxt;
        }
        else {
            rootJspCtxt = invokingJspCtxt;
        }
		this.nestedVars = nestedVars;
		this.atBeginVars = atBeginVars;
		this.atEndVars = atEndVars;
        this.pageAttributes = new HashMap<>(16);
		this.aliases = aliases;

		if (nestedVars != null) {
            this.originalNestedVars = new HashMap<>(nestedVars.size());
        } else {
            this.originalNestedVars = null;
		}
		syncBeginTagFile();
	}

    @Override
	public void initialize(Servlet servlet, ServletRequest request,
			ServletResponse response, String errorPageURL,
			boolean needsSession, int bufferSize, boolean autoFlush)
			throws IOException, IllegalStateException, IllegalArgumentException {
	}

    @Override
	public Object getAttribute(String name) {

		if (name == null) {
			throw MESSAGES.nullAttributeName();
		}

		return pageAttributes.get(name);
	}

    @Override
	public Object getAttribute(String name, int scope) {

		if (name == null) {
			throw MESSAGES.nullAttributeName();
		}

		if (scope == PAGE_SCOPE) {
			return pageAttributes.get(name);
		}

        return rootJspCtxt.getAttribute(name, scope);
	}

    @Override
	public void setAttribute(String name, Object value) {

		if (name == null) {
			throw MESSAGES.nullAttributeName();
		}

		if (value != null) {
			pageAttributes.put(name, value);
		} else {
			removeAttribute(name, PAGE_SCOPE);
		}
	}

    @Override
	public void setAttribute(String name, Object value, int scope) {

		if (name == null) {
			throw MESSAGES.nullAttributeName();
		}

		if (scope == PAGE_SCOPE) {
			if (value != null) {
				pageAttributes.put(name, value);
			} else {
				removeAttribute(name, PAGE_SCOPE);
			}
		} else {
            rootJspCtxt.setAttribute(name, value, scope);
		}
	}

	public Object findAttribute(String name) {

		if (name == null) {
			throw MESSAGES.nullAttributeName();
		}

		Object o = pageAttributes.get(name);
		if (o == null) {
            o = rootJspCtxt.getAttribute(name, REQUEST_SCOPE);
			if (o == null) {
				if (getSession() != null) {
                    o = rootJspCtxt.getAttribute(name, SESSION_SCOPE);
				}
				if (o == null) {
                    o = rootJspCtxt.getAttribute(name, APPLICATION_SCOPE);
				}
			}
		}

		return o;
	}

	public void removeAttribute(String name) {

		if (name == null) {
			throw MESSAGES.nullAttributeName();
		}

		pageAttributes.remove(name);
        rootJspCtxt.removeAttribute(name, REQUEST_SCOPE);
		if (getSession() != null) {
            rootJspCtxt.removeAttribute(name, SESSION_SCOPE);
		}
        rootJspCtxt.removeAttribute(name, APPLICATION_SCOPE);
	}

    @Override
	public void removeAttribute(String name, int scope) {

		if (name == null) {
			throw MESSAGES.nullAttributeName();
		}

		if (scope == PAGE_SCOPE) {
			pageAttributes.remove(name);
		} else {
            rootJspCtxt.removeAttribute(name, scope);
		}
	}

    @Override
	public int getAttributesScope(String name) {

		if (name == null) {
			throw MESSAGES.nullAttributeName();
		}

		if (pageAttributes.get(name) != null) {
			return PAGE_SCOPE;
		} else {
            return rootJspCtxt.getAttributesScope(name);
		}
	}

    @Override
	public Enumeration getAttributeNamesInScope(int scope) {
		if (scope == PAGE_SCOPE) {
			return Collections.enumeration(pageAttributes.keySet());
		}

        return rootJspCtxt.getAttributeNamesInScope(scope);
	}

    @Override
	public void release() {
		invokingJspCtxt.release();
	}

    @Override
	public JspWriter getOut() {
        return rootJspCtxt.getOut();
	}

    @Override
	public HttpSession getSession() {
        return rootJspCtxt.getSession();
	}

    @Override
	public Object getPage() {
		return invokingJspCtxt.getPage();
	}

    @Override
	public ServletRequest getRequest() {
		return invokingJspCtxt.getRequest();
	}

    @Override
	public ServletResponse getResponse() {
        return rootJspCtxt.getResponse();
	}

    @Override
	public Exception getException() {
		return invokingJspCtxt.getException();
	}

    @Override
	public ServletConfig getServletConfig() {
		return invokingJspCtxt.getServletConfig();
	}

    @Override
	public ServletContext getServletContext() {
        if (servletContext == null) {
            servletContext = rootJspCtxt.getServletContext();
        }
        return servletContext;
	}

    @Override
	public void forward(String relativeUrlPath) throws ServletException,
			IOException {
		invokingJspCtxt.forward(relativeUrlPath);
	}

    @Override
	public void include(String relativeUrlPath) throws ServletException,
			IOException {
		invokingJspCtxt.include(relativeUrlPath);
	}

    @Override
	public void include(String relativeUrlPath, boolean flush)
			throws ServletException, IOException {
        invokingJspCtxt.include(relativeUrlPath, false);
	}

    @Override
    @Deprecated
	public VariableResolver getVariableResolver() {
		return this;
	}

    @Override
	public BodyContent pushBody() {
		return invokingJspCtxt.pushBody();
	}

    @Override
	public JspWriter pushBody(Writer writer) {
		return invokingJspCtxt.pushBody(writer);
	}

    @Override
	public JspWriter popBody() {
		return invokingJspCtxt.popBody();
	}

    @Override
    @Deprecated
	public ExpressionEvaluator getExpressionEvaluator() {
		return invokingJspCtxt.getExpressionEvaluator();
	}

    @Override
	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);
	}

    @Override
	public void handlePageException(Throwable t) throws IOException,
			ServletException {
		invokingJspCtxt.handlePageException(t);
	}

	/**
	 * VariableResolver interface
	 */
    @Override
    @Deprecated
	public Object resolveVariable(String pName) throws ELException {
		ELContext ctx = this.getELContext();
		return ctx.getELResolver().getValue(ctx, null, pName);
	}

	/**
	 * Synchronize variables at begin of tag file
	 */
	public void syncBeginTagFile() {
		saveNestedVariables();
	}

	/**
     * Synchronize variables before fragment invocation
	 */
	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 = 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 = 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 = 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 = aliases.get(varName);
		if (alias == null) {
			return varName;
		}
		return alias;
	}

	//private ELContextImpl elContext;

    @Override
	public ELContext getELContext() {
        // instead decorate!!!

        if (elContext == null) {
            elContext = rootJspCtxt.getELContext();
        }
        return elContext;

        /*
		if (this.elContext != null) {
			JspFactory jspFact = JspFactory.getDefaultFactory();
			ServletContext servletContext = this.getServletContext();
			JspApplicationContextImpl jspCtx = (JspApplicationContextImpl) jspFact
					.getJspApplicationContext(servletContext);
			this.elContext = jspCtx.createELContext(this);
		}
		return this.elContext;
        */
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy