970 lines
31 KiB
Java
970 lines
31 KiB
Java
/*
|
|
* 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 java.io.IOException;
|
|
import java.io.Writer;
|
|
import java.security.AccessController;
|
|
import java.security.PrivilegedAction;
|
|
import java.security.PrivilegedActionException;
|
|
import java.security.PrivilegedExceptionAction;
|
|
import java.util.Collections;
|
|
import java.util.Enumeration;
|
|
import java.util.HashMap;
|
|
import java.util.Set;
|
|
|
|
import javax.el.ELContext;
|
|
import javax.el.ELException;
|
|
import javax.el.ExpressionFactory;
|
|
import javax.el.ImportHandler;
|
|
import javax.el.ValueExpression;
|
|
import javax.servlet.RequestDispatcher;
|
|
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.HttpServletRequest;
|
|
import javax.servlet.http.HttpServletResponse;
|
|
import javax.servlet.http.HttpSession;
|
|
import javax.servlet.jsp.JspException;
|
|
import javax.servlet.jsp.JspFactory;
|
|
import javax.servlet.jsp.JspWriter;
|
|
import javax.servlet.jsp.PageContext;
|
|
import javax.servlet.jsp.tagext.BodyContent;
|
|
|
|
import org.apache.jasper.Constants;
|
|
import org.apache.jasper.compiler.Localizer;
|
|
import org.apache.jasper.el.ELContextImpl;
|
|
import org.apache.jasper.runtime.JspContextWrapper.ELContextWrapper;
|
|
import org.apache.jasper.security.SecurityUtil;
|
|
|
|
/**
|
|
* Implementation of the PageContext class from the JSP spec. Also doubles as a
|
|
* VariableResolver for the EL.
|
|
*
|
|
* @author Anil K. Vijendran
|
|
* @author Larry Cable
|
|
* @author Hans Bergsten
|
|
* @author Pierre Delisle
|
|
* @author Mark Roth
|
|
* @author Jan Luehe
|
|
* @author Jacob Hookom
|
|
*/
|
|
public class PageContextImpl extends PageContext {
|
|
|
|
private static final JspFactory jspf = JspFactory.getDefaultFactory();
|
|
|
|
private BodyContentImpl[] outs;
|
|
|
|
private int depth;
|
|
|
|
// per-servlet state
|
|
private Servlet servlet;
|
|
|
|
private ServletConfig config;
|
|
|
|
private ServletContext context;
|
|
|
|
private JspApplicationContextImpl applicationContext;
|
|
|
|
private String errorPageURL;
|
|
|
|
// page-scope attributes
|
|
private final transient HashMap<String, Object> attributes;
|
|
|
|
// per-request state
|
|
private transient ServletRequest request;
|
|
|
|
private transient ServletResponse response;
|
|
|
|
private transient HttpSession session;
|
|
|
|
private transient ELContextImpl elContext;
|
|
|
|
private boolean isIncluded;
|
|
|
|
|
|
// initial output stream
|
|
private transient JspWriter out;
|
|
|
|
private transient JspWriterImpl baseOut;
|
|
|
|
/*
|
|
* Constructor.
|
|
*/
|
|
PageContextImpl() {
|
|
this.outs = new BodyContentImpl[0];
|
|
this.attributes = new HashMap<>(16);
|
|
this.depth = -1;
|
|
}
|
|
|
|
@Override
|
|
public void initialize(Servlet servlet, ServletRequest request,
|
|
ServletResponse response, String errorPageURL,
|
|
boolean needsSession, int bufferSize, boolean autoFlush)
|
|
throws IOException {
|
|
|
|
// initialize state
|
|
this.servlet = servlet;
|
|
this.config = servlet.getServletConfig();
|
|
this.context = config.getServletContext();
|
|
this.errorPageURL = errorPageURL;
|
|
this.request = request;
|
|
this.response = response;
|
|
|
|
// initialize application context
|
|
this.applicationContext = JspApplicationContextImpl.getInstance(context);
|
|
|
|
// Setup session (if required)
|
|
if (request instanceof HttpServletRequest && needsSession)
|
|
this.session = ((HttpServletRequest) request).getSession();
|
|
if (needsSession && session == null)
|
|
throw new IllegalStateException(
|
|
"Page needs a session and none is available");
|
|
|
|
// initialize the initial out ...
|
|
depth = -1;
|
|
if (bufferSize == JspWriter.DEFAULT_BUFFER) {
|
|
bufferSize = Constants.DEFAULT_BUFFER_SIZE;
|
|
}
|
|
if (this.baseOut == null) {
|
|
this.baseOut = new JspWriterImpl(response, bufferSize, autoFlush);
|
|
} else {
|
|
this.baseOut.init(response, bufferSize, autoFlush);
|
|
}
|
|
this.out = baseOut;
|
|
|
|
// register names/values as per spec
|
|
setAttribute(OUT, this.out);
|
|
setAttribute(REQUEST, request);
|
|
setAttribute(RESPONSE, response);
|
|
|
|
if (session != null)
|
|
setAttribute(SESSION, session);
|
|
|
|
setAttribute(PAGE, servlet);
|
|
setAttribute(CONFIG, config);
|
|
setAttribute(PAGECONTEXT, this);
|
|
setAttribute(APPLICATION, context);
|
|
|
|
isIncluded = request.getAttribute(
|
|
RequestDispatcher.INCLUDE_SERVLET_PATH) != null;
|
|
}
|
|
|
|
@Override
|
|
public void release() {
|
|
out = baseOut;
|
|
try {
|
|
if (isIncluded) {
|
|
((JspWriterImpl) out).flushBuffer();
|
|
// push it into the including jspWriter
|
|
} else {
|
|
// Old code:
|
|
// out.flush();
|
|
// Do not flush the buffer even if we're not included (i.e.
|
|
// we are the main page. The servlet will flush it and close
|
|
// the stream.
|
|
((JspWriterImpl) out).flushBuffer();
|
|
}
|
|
} catch (IOException ex) {
|
|
IllegalStateException ise = new IllegalStateException(Localizer.getMessage("jsp.error.flush"), ex);
|
|
throw ise;
|
|
} finally {
|
|
servlet = null;
|
|
config = null;
|
|
context = null;
|
|
applicationContext = null;
|
|
elContext = null;
|
|
errorPageURL = null;
|
|
request = null;
|
|
response = null;
|
|
depth = -1;
|
|
baseOut.recycle();
|
|
session = null;
|
|
attributes.clear();
|
|
for (BodyContentImpl body: outs) {
|
|
body.recycle();
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public Object getAttribute(final String name) {
|
|
|
|
if (name == null) {
|
|
throw new NullPointerException(Localizer
|
|
.getMessage("jsp.error.attribute.null_name"));
|
|
}
|
|
|
|
if (SecurityUtil.isPackageProtectionEnabled()) {
|
|
return AccessController.doPrivileged(
|
|
new PrivilegedAction<Object>() {
|
|
@Override
|
|
public Object run() {
|
|
return doGetAttribute(name);
|
|
}
|
|
});
|
|
} else {
|
|
return doGetAttribute(name);
|
|
}
|
|
|
|
}
|
|
|
|
private Object doGetAttribute(String name) {
|
|
return attributes.get(name);
|
|
}
|
|
|
|
@Override
|
|
public Object getAttribute(final String name, final int scope) {
|
|
|
|
if (name == null) {
|
|
throw new NullPointerException(Localizer
|
|
.getMessage("jsp.error.attribute.null_name"));
|
|
}
|
|
|
|
if (SecurityUtil.isPackageProtectionEnabled()) {
|
|
return AccessController.doPrivileged(
|
|
new PrivilegedAction<Object>() {
|
|
@Override
|
|
public Object run() {
|
|
return doGetAttribute(name, scope);
|
|
}
|
|
});
|
|
} else {
|
|
return doGetAttribute(name, scope);
|
|
}
|
|
|
|
}
|
|
|
|
private Object doGetAttribute(String name, int scope) {
|
|
switch (scope) {
|
|
case PAGE_SCOPE:
|
|
return attributes.get(name);
|
|
|
|
case REQUEST_SCOPE:
|
|
return request.getAttribute(name);
|
|
|
|
case SESSION_SCOPE:
|
|
if (session == null) {
|
|
throw new IllegalStateException(Localizer
|
|
.getMessage("jsp.error.page.noSession"));
|
|
}
|
|
return session.getAttribute(name);
|
|
|
|
case APPLICATION_SCOPE:
|
|
return context.getAttribute(name);
|
|
|
|
default:
|
|
throw new IllegalArgumentException("Invalid scope");
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void setAttribute(final String name, final Object attribute) {
|
|
|
|
if (name == null) {
|
|
throw new NullPointerException(Localizer
|
|
.getMessage("jsp.error.attribute.null_name"));
|
|
}
|
|
|
|
if (SecurityUtil.isPackageProtectionEnabled()) {
|
|
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
|
@Override
|
|
public Void run() {
|
|
doSetAttribute(name, attribute);
|
|
return null;
|
|
}
|
|
});
|
|
} else {
|
|
doSetAttribute(name, attribute);
|
|
}
|
|
}
|
|
|
|
private void doSetAttribute(String name, Object attribute) {
|
|
if (attribute != null) {
|
|
attributes.put(name, attribute);
|
|
} else {
|
|
removeAttribute(name, PAGE_SCOPE);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void setAttribute(final String name, final Object o, final int scope) {
|
|
|
|
if (name == null) {
|
|
throw new NullPointerException(Localizer
|
|
.getMessage("jsp.error.attribute.null_name"));
|
|
}
|
|
|
|
if (SecurityUtil.isPackageProtectionEnabled()) {
|
|
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
|
@Override
|
|
public Void run() {
|
|
doSetAttribute(name, o, scope);
|
|
return null;
|
|
}
|
|
});
|
|
} else {
|
|
doSetAttribute(name, o, scope);
|
|
}
|
|
|
|
}
|
|
|
|
private void doSetAttribute(String name, Object o, int scope) {
|
|
if (o != null) {
|
|
switch (scope) {
|
|
case PAGE_SCOPE:
|
|
attributes.put(name, o);
|
|
break;
|
|
|
|
case REQUEST_SCOPE:
|
|
request.setAttribute(name, o);
|
|
break;
|
|
|
|
case SESSION_SCOPE:
|
|
if (session == null) {
|
|
throw new IllegalStateException(Localizer
|
|
.getMessage("jsp.error.page.noSession"));
|
|
}
|
|
session.setAttribute(name, o);
|
|
break;
|
|
|
|
case APPLICATION_SCOPE:
|
|
context.setAttribute(name, o);
|
|
break;
|
|
|
|
default:
|
|
throw new IllegalArgumentException("Invalid scope");
|
|
}
|
|
} else {
|
|
removeAttribute(name, scope);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void removeAttribute(final String name, final int scope) {
|
|
|
|
if (name == null) {
|
|
throw new NullPointerException(Localizer
|
|
.getMessage("jsp.error.attribute.null_name"));
|
|
}
|
|
if (SecurityUtil.isPackageProtectionEnabled()) {
|
|
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
|
@Override
|
|
public Void run() {
|
|
doRemoveAttribute(name, scope);
|
|
return null;
|
|
}
|
|
});
|
|
} else {
|
|
doRemoveAttribute(name, scope);
|
|
}
|
|
}
|
|
|
|
private void doRemoveAttribute(String name, int scope) {
|
|
switch (scope) {
|
|
case PAGE_SCOPE:
|
|
attributes.remove(name);
|
|
break;
|
|
|
|
case REQUEST_SCOPE:
|
|
request.removeAttribute(name);
|
|
break;
|
|
|
|
case SESSION_SCOPE:
|
|
if (session == null) {
|
|
throw new IllegalStateException(Localizer
|
|
.getMessage("jsp.error.page.noSession"));
|
|
}
|
|
session.removeAttribute(name);
|
|
break;
|
|
|
|
case APPLICATION_SCOPE:
|
|
context.removeAttribute(name);
|
|
break;
|
|
|
|
default:
|
|
throw new IllegalArgumentException("Invalid scope");
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public int getAttributesScope(final String name) {
|
|
|
|
if (name == null) {
|
|
throw new NullPointerException(Localizer
|
|
.getMessage("jsp.error.attribute.null_name"));
|
|
}
|
|
|
|
if (SecurityUtil.isPackageProtectionEnabled()) {
|
|
return (AccessController
|
|
.doPrivileged(new PrivilegedAction<Integer>() {
|
|
@Override
|
|
public Integer run() {
|
|
return Integer.valueOf(doGetAttributeScope(name));
|
|
}
|
|
})).intValue();
|
|
} else {
|
|
return doGetAttributeScope(name);
|
|
}
|
|
}
|
|
|
|
private int doGetAttributeScope(String name) {
|
|
if (attributes.get(name) != null)
|
|
return PAGE_SCOPE;
|
|
|
|
if (request.getAttribute(name) != null)
|
|
return REQUEST_SCOPE;
|
|
|
|
if (session != null) {
|
|
try {
|
|
if (session.getAttribute(name) != null)
|
|
return SESSION_SCOPE;
|
|
} catch(IllegalStateException ise) {
|
|
// Session has been invalidated.
|
|
// Ignore and fall through to application scope.
|
|
}
|
|
}
|
|
|
|
if (context.getAttribute(name) != null)
|
|
return APPLICATION_SCOPE;
|
|
|
|
return 0;
|
|
}
|
|
|
|
@Override
|
|
public Object findAttribute(final String name) {
|
|
if (SecurityUtil.isPackageProtectionEnabled()) {
|
|
return AccessController.doPrivileged(
|
|
new PrivilegedAction<Object>() {
|
|
@Override
|
|
public Object run() {
|
|
if (name == null) {
|
|
throw new NullPointerException(Localizer
|
|
.getMessage("jsp.error.attribute.null_name"));
|
|
}
|
|
|
|
return doFindAttribute(name);
|
|
}
|
|
});
|
|
} else {
|
|
if (name == null) {
|
|
throw new NullPointerException(Localizer
|
|
.getMessage("jsp.error.attribute.null_name"));
|
|
}
|
|
|
|
return doFindAttribute(name);
|
|
}
|
|
}
|
|
|
|
private Object doFindAttribute(String name) {
|
|
|
|
Object o = attributes.get(name);
|
|
if (o != null)
|
|
return o;
|
|
|
|
o = request.getAttribute(name);
|
|
if (o != null)
|
|
return o;
|
|
|
|
if (session != null) {
|
|
try {
|
|
o = session.getAttribute(name);
|
|
} catch(IllegalStateException ise) {
|
|
// Session has been invalidated.
|
|
// Ignore and fall through to application scope.
|
|
}
|
|
if (o != null)
|
|
return o;
|
|
}
|
|
|
|
return context.getAttribute(name);
|
|
}
|
|
|
|
@Override
|
|
public Enumeration<String> getAttributeNamesInScope(final int scope) {
|
|
if (SecurityUtil.isPackageProtectionEnabled()) {
|
|
return AccessController.doPrivileged(
|
|
new PrivilegedAction<Enumeration<String>>() {
|
|
@Override
|
|
public Enumeration<String> run() {
|
|
return doGetAttributeNamesInScope(scope);
|
|
}
|
|
});
|
|
} else {
|
|
return doGetAttributeNamesInScope(scope);
|
|
}
|
|
}
|
|
|
|
private Enumeration<String> doGetAttributeNamesInScope(int scope) {
|
|
switch (scope) {
|
|
case PAGE_SCOPE:
|
|
return Collections.enumeration(attributes.keySet());
|
|
|
|
case REQUEST_SCOPE:
|
|
return request.getAttributeNames();
|
|
|
|
case SESSION_SCOPE:
|
|
if (session == null) {
|
|
throw new IllegalStateException(Localizer
|
|
.getMessage("jsp.error.page.noSession"));
|
|
}
|
|
return session.getAttributeNames();
|
|
|
|
case APPLICATION_SCOPE:
|
|
return context.getAttributeNames();
|
|
|
|
default:
|
|
throw new IllegalArgumentException("Invalid scope");
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void removeAttribute(final String name) {
|
|
|
|
if (name == null) {
|
|
throw new NullPointerException(Localizer
|
|
.getMessage("jsp.error.attribute.null_name"));
|
|
}
|
|
|
|
if (SecurityUtil.isPackageProtectionEnabled()) {
|
|
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
|
@Override
|
|
public Void run() {
|
|
doRemoveAttribute(name);
|
|
return null;
|
|
}
|
|
});
|
|
} else {
|
|
doRemoveAttribute(name);
|
|
}
|
|
}
|
|
|
|
private void doRemoveAttribute(String name) {
|
|
removeAttribute(name, PAGE_SCOPE);
|
|
removeAttribute(name, REQUEST_SCOPE);
|
|
if( session != null ) {
|
|
try {
|
|
removeAttribute(name, SESSION_SCOPE);
|
|
} catch(IllegalStateException ise) {
|
|
// Session has been invalidated.
|
|
// Ignore and fall throw to application scope.
|
|
}
|
|
}
|
|
removeAttribute(name, APPLICATION_SCOPE);
|
|
}
|
|
|
|
@Override
|
|
public JspWriter getOut() {
|
|
return out;
|
|
}
|
|
|
|
@Override
|
|
public HttpSession getSession() {
|
|
return session;
|
|
}
|
|
|
|
@Override
|
|
public ServletConfig getServletConfig() {
|
|
return config;
|
|
}
|
|
|
|
@Override
|
|
public ServletContext getServletContext() {
|
|
return config.getServletContext();
|
|
}
|
|
|
|
@Override
|
|
public ServletRequest getRequest() {
|
|
return request;
|
|
}
|
|
|
|
@Override
|
|
public ServletResponse getResponse() {
|
|
return response;
|
|
}
|
|
|
|
/**
|
|
* Returns the exception associated with this page context, if any.
|
|
* <p>
|
|
* Added wrapping for Throwables to avoid ClassCastException: see Bugzilla
|
|
* 31171 for details.
|
|
*
|
|
* @return The Exception associated with this page context, if any.
|
|
*/
|
|
@Override
|
|
public Exception getException() {
|
|
Throwable t = JspRuntimeLibrary.getThrowable(request);
|
|
|
|
// Only wrap if needed
|
|
if ((t != null) && (!(t instanceof Exception))) {
|
|
t = new JspException(t);
|
|
}
|
|
|
|
return (Exception) t;
|
|
}
|
|
|
|
@Override
|
|
public Object getPage() {
|
|
return servlet;
|
|
}
|
|
|
|
private final String getAbsolutePathRelativeToContext(String relativeUrlPath) {
|
|
String path = relativeUrlPath;
|
|
|
|
if (!path.startsWith("/")) {
|
|
String uri = (String) request.getAttribute(
|
|
RequestDispatcher.INCLUDE_SERVLET_PATH);
|
|
if (uri == null)
|
|
uri = ((HttpServletRequest) request).getServletPath();
|
|
String baseURI = uri.substring(0, uri.lastIndexOf('/'));
|
|
path = baseURI + '/' + path;
|
|
}
|
|
|
|
return path;
|
|
}
|
|
|
|
@Override
|
|
public void include(String relativeUrlPath) throws ServletException,
|
|
IOException {
|
|
JspRuntimeLibrary
|
|
.include(request, response, relativeUrlPath, out, true);
|
|
}
|
|
|
|
@Override
|
|
public void include(final String relativeUrlPath, final boolean flush)
|
|
throws ServletException, IOException {
|
|
if (SecurityUtil.isPackageProtectionEnabled()) {
|
|
try {
|
|
AccessController.doPrivileged(
|
|
new PrivilegedExceptionAction<Void>() {
|
|
@Override
|
|
public Void run() throws Exception {
|
|
doInclude(relativeUrlPath, flush);
|
|
return null;
|
|
}
|
|
});
|
|
} catch (PrivilegedActionException e) {
|
|
Exception ex = e.getException();
|
|
if (ex instanceof IOException) {
|
|
throw (IOException) ex;
|
|
} else {
|
|
throw (ServletException) ex;
|
|
}
|
|
}
|
|
} else {
|
|
doInclude(relativeUrlPath, flush);
|
|
}
|
|
}
|
|
|
|
private void doInclude(String relativeUrlPath, boolean flush)
|
|
throws ServletException, IOException {
|
|
JspRuntimeLibrary.include(request, response, relativeUrlPath, out,
|
|
flush);
|
|
}
|
|
|
|
@Override
|
|
@Deprecated
|
|
public javax.servlet.jsp.el.VariableResolver getVariableResolver() {
|
|
return new org.apache.jasper.el.VariableResolverImpl(
|
|
this.getELContext());
|
|
}
|
|
|
|
@Override
|
|
public void forward(final String relativeUrlPath) throws ServletException,
|
|
IOException {
|
|
if (SecurityUtil.isPackageProtectionEnabled()) {
|
|
try {
|
|
AccessController.doPrivileged(
|
|
new PrivilegedExceptionAction<Void>() {
|
|
@Override
|
|
public Void run() throws Exception {
|
|
doForward(relativeUrlPath);
|
|
return null;
|
|
}
|
|
});
|
|
} catch (PrivilegedActionException e) {
|
|
Exception ex = e.getException();
|
|
if (ex instanceof IOException) {
|
|
throw (IOException) ex;
|
|
} else {
|
|
throw (ServletException) ex;
|
|
}
|
|
}
|
|
} else {
|
|
doForward(relativeUrlPath);
|
|
}
|
|
}
|
|
|
|
private void doForward(String relativeUrlPath) throws ServletException,
|
|
IOException {
|
|
|
|
// JSP.4.5 If the buffer was flushed, throw IllegalStateException
|
|
try {
|
|
out.clear();
|
|
baseOut.clear();
|
|
} catch (IOException ex) {
|
|
IllegalStateException ise = new IllegalStateException(Localizer
|
|
.getMessage("jsp.error.attempt_to_clear_flushed_buffer"));
|
|
ise.initCause(ex);
|
|
throw ise;
|
|
}
|
|
|
|
// Make sure that the response object is not the wrapper for include
|
|
while (response instanceof ServletResponseWrapperInclude) {
|
|
response = ((ServletResponseWrapperInclude) response).getResponse();
|
|
}
|
|
|
|
final String path = getAbsolutePathRelativeToContext(relativeUrlPath);
|
|
String includeUri = (String) request.getAttribute(
|
|
RequestDispatcher.INCLUDE_SERVLET_PATH);
|
|
|
|
if (includeUri != null)
|
|
request.removeAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH);
|
|
try {
|
|
context.getRequestDispatcher(path).forward(request, response);
|
|
} finally {
|
|
if (includeUri != null)
|
|
request.setAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH,
|
|
includeUri);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public BodyContent pushBody() {
|
|
return (BodyContent) pushBody(null);
|
|
}
|
|
|
|
@Override
|
|
public JspWriter pushBody(Writer writer) {
|
|
depth++;
|
|
if (depth >= outs.length) {
|
|
BodyContentImpl[] newOuts = new BodyContentImpl[depth + 1];
|
|
for (int i = 0; i < outs.length; i++) {
|
|
newOuts[i] = outs[i];
|
|
}
|
|
newOuts[depth] = new BodyContentImpl(out);
|
|
outs = newOuts;
|
|
}
|
|
|
|
outs[depth].setWriter(writer);
|
|
out = outs[depth];
|
|
|
|
// Update the value of the "out" attribute in the page scope
|
|
// attribute namespace of this PageContext
|
|
setAttribute(OUT, out);
|
|
|
|
return outs[depth];
|
|
}
|
|
|
|
@Override
|
|
public JspWriter popBody() {
|
|
depth--;
|
|
if (depth >= 0) {
|
|
out = outs[depth];
|
|
} else {
|
|
out = baseOut;
|
|
}
|
|
|
|
// Update the value of the "out" attribute in the page scope
|
|
// attribute namespace of this PageContext
|
|
setAttribute(OUT, out);
|
|
|
|
return out;
|
|
}
|
|
|
|
/**
|
|
* Provides programmatic access to the ExpressionEvaluator. The JSP
|
|
* Container must return a valid instance of an ExpressionEvaluator that can
|
|
* parse EL expressions.
|
|
*/
|
|
@Override
|
|
@Deprecated
|
|
public javax.servlet.jsp.el.ExpressionEvaluator getExpressionEvaluator() {
|
|
return new org.apache.jasper.el.ExpressionEvaluatorImpl(
|
|
this.applicationContext.getExpressionFactory());
|
|
}
|
|
|
|
@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(final Throwable t) throws IOException,
|
|
ServletException {
|
|
if (t == null)
|
|
throw new NullPointerException("null Throwable");
|
|
|
|
if (SecurityUtil.isPackageProtectionEnabled()) {
|
|
try {
|
|
AccessController.doPrivileged(
|
|
new PrivilegedExceptionAction<Void>() {
|
|
@Override
|
|
public Void run() throws Exception {
|
|
doHandlePageException(t);
|
|
return null;
|
|
}
|
|
});
|
|
} catch (PrivilegedActionException e) {
|
|
Exception ex = e.getException();
|
|
if (ex instanceof IOException) {
|
|
throw (IOException) ex;
|
|
} else {
|
|
throw (ServletException) ex;
|
|
}
|
|
}
|
|
} else {
|
|
doHandlePageException(t);
|
|
}
|
|
|
|
}
|
|
|
|
@SuppressWarnings("deprecation") // Still jave to support old JSP EL
|
|
private void doHandlePageException(Throwable t) throws IOException,
|
|
ServletException {
|
|
|
|
if (errorPageURL != null && !errorPageURL.equals("")) {
|
|
|
|
/*
|
|
* Set request attributes. Do not set the
|
|
* javax.servlet.error.exception attribute here (instead, set in the
|
|
* generated servlet code for the error page) in order to prevent
|
|
* the ErrorReportValve, which is invoked as part of forwarding the
|
|
* request to the error page, from throwing it if the response has
|
|
* not been committed (the response will have been committed if the
|
|
* error page is a JSP page).
|
|
*/
|
|
request.setAttribute(PageContext.EXCEPTION, t);
|
|
request.setAttribute(RequestDispatcher.ERROR_STATUS_CODE,
|
|
Integer.valueOf(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
|
|
request.setAttribute(RequestDispatcher.ERROR_REQUEST_URI,
|
|
((HttpServletRequest) request).getRequestURI());
|
|
request.setAttribute(RequestDispatcher.ERROR_SERVLET_NAME,
|
|
config.getServletName());
|
|
try {
|
|
forward(errorPageURL);
|
|
} catch (IllegalStateException ise) {
|
|
include(errorPageURL);
|
|
}
|
|
|
|
// The error page could be inside an include.
|
|
|
|
Object newException =
|
|
request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
|
|
|
|
// t==null means the attribute was not set.
|
|
if ((newException != null) && (newException == t)) {
|
|
request.removeAttribute(RequestDispatcher.ERROR_EXCEPTION);
|
|
}
|
|
|
|
// now clear the error code - to prevent double handling.
|
|
request.removeAttribute(RequestDispatcher.ERROR_STATUS_CODE);
|
|
request.removeAttribute(RequestDispatcher.ERROR_REQUEST_URI);
|
|
request.removeAttribute(RequestDispatcher.ERROR_SERVLET_NAME);
|
|
request.removeAttribute(PageContext.EXCEPTION);
|
|
|
|
} else {
|
|
// Otherwise throw the exception wrapped inside a ServletException.
|
|
// Set the exception as the root cause in the ServletException
|
|
// to get a stack trace for the real problem
|
|
if (t instanceof IOException)
|
|
throw (IOException) t;
|
|
if (t instanceof ServletException)
|
|
throw (ServletException) t;
|
|
if (t instanceof RuntimeException)
|
|
throw (RuntimeException) t;
|
|
|
|
Throwable rootCause = null;
|
|
if (t instanceof JspException || t instanceof ELException ||
|
|
t instanceof javax.servlet.jsp.el.ELException) {
|
|
rootCause =t.getCause();
|
|
}
|
|
|
|
if (rootCause != null) {
|
|
throw new ServletException(t.getClass().getName() + ": "
|
|
+ t.getMessage(), rootCause);
|
|
}
|
|
|
|
throw new ServletException(t);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Proprietary method to evaluate EL expressions. XXX - This method should
|
|
* go away once the EL interpreter moves out of JSTL and into its own
|
|
* project. For now, this is necessary because the standard machinery is too
|
|
* slow.
|
|
*
|
|
* @param expression
|
|
* The expression to be evaluated
|
|
* @param expectedType
|
|
* The expected resulting type
|
|
* @param pageContext
|
|
* The page context
|
|
* @param functionMap
|
|
* Maps prefix and name to Method
|
|
* @return The result of the evaluation
|
|
* @throws ELException If an error occurs during the evaluation
|
|
*/
|
|
public static Object proprietaryEvaluate(final String expression,
|
|
final Class<?> expectedType, final PageContext pageContext,
|
|
final ProtectedFunctionMapper functionMap)
|
|
throws ELException {
|
|
final ExpressionFactory exprFactory = jspf.getJspApplicationContext(pageContext.getServletContext()).getExpressionFactory();
|
|
ELContext ctx = pageContext.getELContext();
|
|
ELContextImpl ctxImpl;
|
|
if (ctx instanceof ELContextWrapper) {
|
|
ctxImpl = (ELContextImpl) ((ELContextWrapper) ctx).getWrappedELContext();
|
|
} else {
|
|
ctxImpl = (ELContextImpl) ctx;
|
|
}
|
|
ctxImpl.setFunctionMapper(functionMap);
|
|
ValueExpression ve = exprFactory.createValueExpression(ctx, expression, expectedType);
|
|
return ve.getValue(ctx);
|
|
}
|
|
|
|
@Override
|
|
public ELContext getELContext() {
|
|
if (elContext == null) {
|
|
elContext = applicationContext.createELContext(this);
|
|
if (servlet instanceof JspSourceImports) {
|
|
ImportHandler ih = elContext.getImportHandler();
|
|
Set<String> packageImports = ((JspSourceImports) servlet).getPackageImports();
|
|
if (packageImports != null) {
|
|
for (String packageImport : packageImports) {
|
|
ih.importPackage(packageImport);
|
|
}
|
|
}
|
|
Set<String> classImports = ((JspSourceImports) servlet).getClassImports();
|
|
if (classImports != null) {
|
|
for (String classImport : classImports) {
|
|
ih.importClass(classImport);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return this.elContext;
|
|
}
|
|
}
|