init
This commit is contained in:
707
java/org/apache/jasper/runtime/BodyContentImpl.java
Normal file
707
java/org/apache/jasper/runtime/BodyContentImpl.java
Normal file
@@ -0,0 +1,707 @@
|
||||
/*
|
||||
* 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.CharArrayReader;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
import javax.servlet.jsp.JspWriter;
|
||||
import javax.servlet.jsp.tagext.BodyContent;
|
||||
|
||||
import org.apache.jasper.Constants;
|
||||
|
||||
/**
|
||||
* Write text to a character-output stream, buffering characters so as
|
||||
* to provide for the efficient writing of single characters, arrays,
|
||||
* and strings.
|
||||
*
|
||||
* Provide support for discarding for the output that has been buffered.
|
||||
*
|
||||
* @author Rajiv Mordani
|
||||
* @author Jan Luehe
|
||||
*/
|
||||
public class BodyContentImpl extends BodyContent {
|
||||
|
||||
private static final boolean LIMIT_BUFFER;
|
||||
private static final int TAG_BUFFER_SIZE;
|
||||
|
||||
static {
|
||||
if (System.getSecurityManager() == null) {
|
||||
LIMIT_BUFFER = Boolean.parseBoolean(System.getProperty(
|
||||
"org.apache.jasper.runtime.BodyContentImpl.LIMIT_BUFFER", "false"));
|
||||
TAG_BUFFER_SIZE = Integer.getInteger(
|
||||
"org.apache.jasper.runtime.BodyContentImpl.BUFFER_SIZE",
|
||||
Constants.DEFAULT_TAG_BUFFER_SIZE).intValue();
|
||||
} else {
|
||||
LIMIT_BUFFER = AccessController.doPrivileged(
|
||||
new PrivilegedAction<Boolean>() {
|
||||
@Override
|
||||
public Boolean run() {
|
||||
return Boolean.valueOf(System.getProperty(
|
||||
"org.apache.jasper.runtime.BodyContentImpl.LIMIT_BUFFER",
|
||||
"false"));
|
||||
}
|
||||
}
|
||||
).booleanValue();
|
||||
TAG_BUFFER_SIZE = AccessController.doPrivileged(
|
||||
new PrivilegedAction<Integer>() {
|
||||
@Override
|
||||
public Integer run() {
|
||||
return Integer.getInteger(
|
||||
"org.apache.jasper.runtime.BodyContentImpl.BUFFER_SIZE",
|
||||
Constants.DEFAULT_TAG_BUFFER_SIZE);
|
||||
}
|
||||
}
|
||||
).intValue();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private char[] cb;
|
||||
private int nextChar;
|
||||
private boolean closed;
|
||||
|
||||
/**
|
||||
* Enclosed writer to which any output is written
|
||||
*/
|
||||
private Writer writer;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param enclosingWriter The wrapped writer
|
||||
*/
|
||||
public BodyContentImpl(JspWriter enclosingWriter) {
|
||||
super(enclosingWriter);
|
||||
cb = new char[TAG_BUFFER_SIZE];
|
||||
bufferSize = cb.length;
|
||||
nextChar = 0;
|
||||
closed = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a single character.
|
||||
* @param c The char to write
|
||||
* @throws IOException Error writing to wrapped writer
|
||||
*/
|
||||
@Override
|
||||
public void write(int c) throws IOException {
|
||||
if (writer != null) {
|
||||
writer.write(c);
|
||||
} else {
|
||||
ensureOpen();
|
||||
if (nextChar >= bufferSize) {
|
||||
reAllocBuff (1);
|
||||
}
|
||||
cb[nextChar++] = (char) c;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a portion of an array of characters.
|
||||
*
|
||||
* <p> Ordinarily this method stores characters from the given array into
|
||||
* this stream's buffer, flushing the buffer to the underlying stream as
|
||||
* needed. If the requested length is at least as large as the buffer,
|
||||
* however, then this method will flush the buffer and write the characters
|
||||
* directly to the underlying stream. Thus redundant
|
||||
* <code>DiscardableBufferedWriter</code>s will not copy data
|
||||
* unnecessarily.
|
||||
*
|
||||
* @param cbuf A character array
|
||||
* @param off Offset from which to start reading characters
|
||||
* @param len Number of characters to write
|
||||
* @throws IOException Error writing to wrapped writer
|
||||
*/
|
||||
@Override
|
||||
public void write(char[] cbuf, int off, int len) throws IOException {
|
||||
if (writer != null) {
|
||||
writer.write(cbuf, off, len);
|
||||
} else {
|
||||
ensureOpen();
|
||||
|
||||
if ((off < 0) || (off > cbuf.length) || (len < 0) ||
|
||||
((off + len) > cbuf.length) || ((off + len) < 0)) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
} else if (len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (len >= bufferSize - nextChar)
|
||||
reAllocBuff (len);
|
||||
|
||||
System.arraycopy(cbuf, off, cb, nextChar, len);
|
||||
nextChar+=len;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an array of characters. This method cannot be inherited from the
|
||||
* Writer class because it must suppress I/O exceptions.
|
||||
* @param buf Content to write
|
||||
* @throws IOException Error writing to wrapped writer
|
||||
*/
|
||||
@Override
|
||||
public void write(char[] buf) throws IOException {
|
||||
if (writer != null) {
|
||||
writer.write(buf);
|
||||
} else {
|
||||
write(buf, 0, buf.length);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a portion of a String.
|
||||
*
|
||||
* @param s String to be written
|
||||
* @param off Offset from which to start reading characters
|
||||
* @param len Number of characters to be written
|
||||
* @throws IOException Error writing to wrapped writer
|
||||
*/
|
||||
@Override
|
||||
public void write(String s, int off, int len) throws IOException {
|
||||
if (writer != null) {
|
||||
writer.write(s, off, len);
|
||||
} else {
|
||||
ensureOpen();
|
||||
if (len >= bufferSize - nextChar)
|
||||
reAllocBuff(len);
|
||||
|
||||
s.getChars(off, off + len, cb, nextChar);
|
||||
nextChar += len;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a string. This method cannot be inherited from the Writer class
|
||||
* because it must suppress I/O exceptions.
|
||||
* @param s String to be written
|
||||
* @throws IOException Error writing to wrapped writer
|
||||
*/
|
||||
@Override
|
||||
public void write(String s) throws IOException {
|
||||
if (writer != null) {
|
||||
writer.write(s);
|
||||
} else {
|
||||
write(s, 0, s.length());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a line separator. The line separator string is defined by the
|
||||
* system property <code>line.separator</code>, and is not necessarily a
|
||||
* single newline ('\n') character.
|
||||
*
|
||||
* @throws IOException Error writing to wrapped writer
|
||||
*/
|
||||
@Override
|
||||
public void newLine() throws IOException {
|
||||
if (writer != null) {
|
||||
writer.write(System.lineSeparator());
|
||||
} else {
|
||||
write(System.lineSeparator());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a boolean value. The string produced by <code>{@link
|
||||
* java.lang.String#valueOf(boolean)}</code> is translated into bytes
|
||||
* according to the platform's default character encoding, and these bytes
|
||||
* are written in exactly the manner of the <code>{@link
|
||||
* #write(int)}</code> method.
|
||||
*
|
||||
* @param b The <code>boolean</code> to be printed
|
||||
* @throws IOException Error writing to wrapped writer
|
||||
*/
|
||||
@Override
|
||||
public void print(boolean b) throws IOException {
|
||||
if (writer != null) {
|
||||
writer.write(b ? "true" : "false");
|
||||
} else {
|
||||
write(b ? "true" : "false");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a character. The character is translated into one or more bytes
|
||||
* according to the platform's default character encoding, and these bytes
|
||||
* are written in exactly the manner of the <code>{@link
|
||||
* #write(int)}</code> method.
|
||||
*
|
||||
* @param c The <code>char</code> to be printed
|
||||
* @throws IOException Error writing to wrapped writer
|
||||
*/
|
||||
@Override
|
||||
public void print(char c) throws IOException {
|
||||
if (writer != null) {
|
||||
writer.write(String.valueOf(c));
|
||||
} else {
|
||||
write(String.valueOf(c));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an integer. The string produced by <code>{@link
|
||||
* java.lang.String#valueOf(int)}</code> is translated into bytes according
|
||||
* to the platform's default character encoding, and these bytes are
|
||||
* written in exactly the manner of the <code>{@link #write(int)}</code>
|
||||
* method.
|
||||
*
|
||||
* @param i The <code>int</code> to be printed
|
||||
* @throws IOException Error writing to wrapped writer
|
||||
*/
|
||||
@Override
|
||||
public void print(int i) throws IOException {
|
||||
if (writer != null) {
|
||||
writer.write(String.valueOf(i));
|
||||
} else {
|
||||
write(String.valueOf(i));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a long integer. The string produced by <code>{@link
|
||||
* java.lang.String#valueOf(long)}</code> is translated into bytes
|
||||
* according to the platform's default character encoding, and these bytes
|
||||
* are written in exactly the manner of the
|
||||
* <code>{@link #write(int)}</code> method.
|
||||
*
|
||||
* @param l The <code>long</code> to be printed
|
||||
* @throws IOException Error writing to wrapped writer
|
||||
*/
|
||||
@Override
|
||||
public void print(long l) throws IOException {
|
||||
if (writer != null) {
|
||||
writer.write(String.valueOf(l));
|
||||
} else {
|
||||
write(String.valueOf(l));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a floating-point number. The string produced by <code>{@link
|
||||
* java.lang.String#valueOf(float)}</code> is translated into bytes
|
||||
* according to the platform's default character encoding, and these bytes
|
||||
* are written in exactly the manner of the
|
||||
* <code>{@link #write(int)}</code> method.
|
||||
*
|
||||
* @param f The <code>float</code> to be printed
|
||||
* @throws IOException Error writing to wrapped writer
|
||||
*/
|
||||
@Override
|
||||
public void print(float f) throws IOException {
|
||||
if (writer != null) {
|
||||
writer.write(String.valueOf(f));
|
||||
} else {
|
||||
write(String.valueOf(f));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a double-precision floating-point number. The string produced by
|
||||
* <code>{@link java.lang.String#valueOf(double)}</code> is translated into
|
||||
* bytes according to the platform's default character encoding, and these
|
||||
* bytes are written in exactly the manner of the <code>{@link
|
||||
* #write(int)}</code> method.
|
||||
*
|
||||
* @param d The <code>double</code> to be printed
|
||||
* @throws IOException Error writing to wrapped writer
|
||||
*/
|
||||
@Override
|
||||
public void print(double d) throws IOException {
|
||||
if (writer != null) {
|
||||
writer.write(String.valueOf(d));
|
||||
} else {
|
||||
write(String.valueOf(d));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an array of characters. The characters are converted into bytes
|
||||
* according to the platform's default character encoding, and these bytes
|
||||
* are written in exactly the manner of the
|
||||
* <code>{@link #write(int)}</code> method.
|
||||
*
|
||||
* @param s The array of chars to be printed
|
||||
*
|
||||
* @throws NullPointerException If <code>s</code> is <code>null</code>
|
||||
* @throws IOException Error writing to wrapped writer
|
||||
*/
|
||||
@Override
|
||||
public void print(char[] s) throws IOException {
|
||||
if (writer != null) {
|
||||
writer.write(s);
|
||||
} else {
|
||||
write(s);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a string. If the argument is <code>null</code> then the string
|
||||
* <code>"null"</code> is printed. Otherwise, the string's characters are
|
||||
* converted into bytes according to the platform's default character
|
||||
* encoding, and these bytes are written in exactly the manner of the
|
||||
* <code>{@link #write(int)}</code> method.
|
||||
*
|
||||
* @param s The <code>String</code> to be printed
|
||||
* @throws IOException Error writing to wrapped writer
|
||||
*/
|
||||
@Override
|
||||
public void print(String s) throws IOException {
|
||||
if (s == null) s = "null";
|
||||
if (writer != null) {
|
||||
writer.write(s);
|
||||
} else {
|
||||
write(s);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an object. The string produced by the <code>{@link
|
||||
* java.lang.String#valueOf(Object)}</code> method is translated into bytes
|
||||
* according to the platform's default character encoding, and these bytes
|
||||
* are written in exactly the manner of the
|
||||
* <code>{@link #write(int)}</code> method.
|
||||
*
|
||||
* @param obj The <code>Object</code> to be printed
|
||||
* @throws IOException Error writing to wrapped writer
|
||||
*/
|
||||
@Override
|
||||
public void print(Object obj) throws IOException {
|
||||
if (writer != null) {
|
||||
writer.write(String.valueOf(obj));
|
||||
} else {
|
||||
write(String.valueOf(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminate the current line by writing the line separator string. The
|
||||
* line separator string is defined by the system property
|
||||
* <code>line.separator</code>, and is not necessarily a single newline
|
||||
* character (<code>'\n'</code>).
|
||||
*
|
||||
* @throws IOException Error writing to wrapped writer
|
||||
*/
|
||||
@Override
|
||||
public void println() throws IOException {
|
||||
newLine();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a boolean value and then terminate the line. This method behaves
|
||||
* as though it invokes <code>{@link #print(boolean)}</code> and then
|
||||
* <code>{@link #println()}</code>.
|
||||
*
|
||||
* @param x The <code>boolean</code> to be printed
|
||||
* @throws IOException Error writing to wrapped writer
|
||||
*/
|
||||
@Override
|
||||
public void println(boolean x) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a character and then terminate the line. This method behaves as
|
||||
* though it invokes <code>{@link #print(char)}</code> and then
|
||||
* <code>{@link #println()}</code>.
|
||||
*
|
||||
* @param x The <code>char</code> to be printed
|
||||
* @throws IOException Error writing to wrapped writer
|
||||
*/
|
||||
@Override
|
||||
public void println(char x) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an integer and then terminate the line. This method behaves as
|
||||
* though it invokes <code>{@link #print(int)}</code> and then
|
||||
* <code>{@link #println()}</code>.
|
||||
*
|
||||
* @param x The <code>int</code> to be printed
|
||||
* @throws IOException Error writing to wrapped writer
|
||||
*/
|
||||
@Override
|
||||
public void println(int x) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a long integer and then terminate the line. This method behaves
|
||||
* as though it invokes <code>{@link #print(long)}</code> and then
|
||||
* <code>{@link #println()}</code>.
|
||||
*
|
||||
* @param x The <code>long</code> to be printed
|
||||
* @throws IOException Error writing to wrapped writer
|
||||
*/
|
||||
@Override
|
||||
public void println(long x) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a floating-point number and then terminate the line. This method
|
||||
* behaves as though it invokes <code>{@link #print(float)}</code> and then
|
||||
* <code>{@link #println()}</code>.
|
||||
*
|
||||
* @param x The <code>float</code> to be printed
|
||||
* @throws IOException Error writing to wrapped writer
|
||||
*/
|
||||
@Override
|
||||
public void println(float x) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a double-precision floating-point number and then terminate the
|
||||
* line. This method behaves as though it invokes <code>{@link
|
||||
* #print(double)}</code> and then <code>{@link #println()}</code>.
|
||||
*
|
||||
* @param x The <code>double</code> to be printed
|
||||
* @throws IOException Error writing to wrapped writer
|
||||
*/
|
||||
@Override
|
||||
public void println(double x) throws IOException{
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an array of characters and then terminate the line. This method
|
||||
* behaves as though it invokes <code>{@link #print(char[])}</code> and
|
||||
* then <code>{@link #println()}</code>.
|
||||
*
|
||||
* @param x The <code>char</code> array to be printed
|
||||
* @throws IOException Error writing to wrapped writer
|
||||
*/
|
||||
@Override
|
||||
public void println(char x[]) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a String and then terminate the line. This method behaves as
|
||||
* though it invokes <code>{@link #print(String)}</code> and then
|
||||
* <code>{@link #println()}</code>.
|
||||
*
|
||||
* @param x The string to be printed
|
||||
* @throws IOException Error writing to wrapped writer
|
||||
*/
|
||||
@Override
|
||||
public void println(String x) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an Object and then terminate the line. This method behaves as
|
||||
* though it invokes <code>{@link #print(Object)}</code> and then
|
||||
* <code>{@link #println()}</code>.
|
||||
*
|
||||
* @param x The object to be printed
|
||||
* @throws IOException Error writing to wrapped writer
|
||||
*/
|
||||
@Override
|
||||
public void println(Object x) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the contents of the buffer. If the buffer has been already
|
||||
* been flushed then the clear operation shall throw an IOException
|
||||
* to signal the fact that some data has already been irrevocably
|
||||
* written to the client response stream.
|
||||
*
|
||||
* @throws IOException If there is no wrapped writer
|
||||
*/
|
||||
@Override
|
||||
public void clear() throws IOException {
|
||||
if (writer != null) {
|
||||
throw new IOException();
|
||||
} else {
|
||||
nextChar = 0;
|
||||
if (LIMIT_BUFFER && (cb.length > TAG_BUFFER_SIZE)) {
|
||||
cb = new char[TAG_BUFFER_SIZE];
|
||||
bufferSize = cb.length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the current contents of the buffer. Unlike clear(), this
|
||||
* method will not throw an IOException if the buffer has already been
|
||||
* flushed. It merely clears the current content of the buffer and
|
||||
* returns.
|
||||
*
|
||||
* @throws IOException Should not happen
|
||||
*/
|
||||
@Override
|
||||
public void clearBuffer() throws IOException {
|
||||
if (writer == null) {
|
||||
this.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the stream, flushing it first. Once a stream has been closed,
|
||||
* further write() or flush() invocations will cause an IOException to be
|
||||
* thrown. Closing a previously-closed stream, however, has no effect.
|
||||
*
|
||||
* @throws IOException Error writing to wrapped writer
|
||||
*/
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (writer != null) {
|
||||
writer.close();
|
||||
} else {
|
||||
closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the size of the buffer used by the JspWriter.
|
||||
*
|
||||
* @return the size of the buffer in bytes, or 0 is unbuffered.
|
||||
*/
|
||||
@Override
|
||||
public int getBufferSize() {
|
||||
// According to the spec, the JspWriter returned by
|
||||
// JspContext.pushBody(java.io.Writer writer) must behave as
|
||||
// though it were unbuffered. This means that its getBufferSize()
|
||||
// must always return 0.
|
||||
return (writer == null) ? bufferSize : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of bytes unused in the buffer
|
||||
*/
|
||||
@Override
|
||||
public int getRemaining() {
|
||||
return (writer == null) ? bufferSize-nextChar : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the value of this BodyJspWriter as a Reader.
|
||||
* Note: this is after evaluation!! There are no scriptlets,
|
||||
* etc in this stream.
|
||||
*
|
||||
* @return the value of this BodyJspWriter as a Reader
|
||||
*/
|
||||
@Override
|
||||
public Reader getReader() {
|
||||
return (writer == null) ? new CharArrayReader (cb, 0, nextChar) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the value of the BodyJspWriter as a String.
|
||||
* Note: this is after evaluation!! There are no scriptlets,
|
||||
* etc in this stream.
|
||||
*
|
||||
* @return the value of the BodyJspWriter as a String
|
||||
*/
|
||||
@Override
|
||||
public String getString() {
|
||||
return (writer == null) ? new String(cb, 0, nextChar) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the contents of this BodyJspWriter into a Writer.
|
||||
* Subclasses are likely to do interesting things with the
|
||||
* implementation so some things are extra efficient.
|
||||
*
|
||||
* @param out The writer into which to place the contents of this body
|
||||
* evaluation
|
||||
* @throws IOException Error writing to writer
|
||||
*/
|
||||
@Override
|
||||
public void writeOut(Writer out) throws IOException {
|
||||
if (writer == null) {
|
||||
out.write(cb, 0, nextChar);
|
||||
// Flush not called as the writer passed could be a BodyContent and
|
||||
// it doesn't allow to flush.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the writer to which all output is written.
|
||||
*/
|
||||
void setWriter(Writer writer) {
|
||||
this.writer = writer;
|
||||
closed = false;
|
||||
if (writer == null) {
|
||||
clearBody();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method shall "reset" the internal state of a BodyContentImpl,
|
||||
* releasing all internal references, and preparing it for potential
|
||||
* reuse by a later invocation of {@link PageContextImpl#pushBody(Writer)}.
|
||||
*
|
||||
* <p>Note, that BodyContentImpl instances are usually owned by a
|
||||
* PageContextImpl instance, and PageContextImpl instances are recycled
|
||||
* and reused.
|
||||
*
|
||||
* @see PageContextImpl#release()
|
||||
*/
|
||||
protected void recycle() {
|
||||
this.writer = null;
|
||||
try {
|
||||
this.clear();
|
||||
} catch (IOException ex) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureOpen() throws IOException {
|
||||
if (closed) throw new IOException("Stream closed");
|
||||
}
|
||||
|
||||
/**
|
||||
* Reallocates buffer since the spec requires it to be unbounded.
|
||||
*/
|
||||
private void reAllocBuff(int len) {
|
||||
|
||||
if (bufferSize + len <= cb.length) {
|
||||
bufferSize = cb.length;
|
||||
return;
|
||||
}
|
||||
|
||||
if (len < cb.length) {
|
||||
len = cb.length;
|
||||
}
|
||||
|
||||
char[] tmp = new char[cb.length + len];
|
||||
System.arraycopy(cb, 0, tmp, 0, cb.length);
|
||||
cb = tmp;
|
||||
bufferSize = cb.length;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
60
java/org/apache/jasper/runtime/ExceptionUtils.java
Normal file
60
java/org/apache/jasper/runtime/ExceptionUtils.java
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.lang.reflect.InvocationTargetException;
|
||||
|
||||
|
||||
/**
|
||||
* Utilities for handling Throwables and Exceptions.
|
||||
*/
|
||||
public class ExceptionUtils {
|
||||
|
||||
/**
|
||||
* Checks whether the supplied Throwable is one that needs to be
|
||||
* rethrown and swallows all others.
|
||||
* @param t the Throwable to check
|
||||
*/
|
||||
public static void handleThrowable(Throwable t) {
|
||||
if (t instanceof ThreadDeath) {
|
||||
throw (ThreadDeath) t;
|
||||
}
|
||||
if (t instanceof StackOverflowError) {
|
||||
// Swallow silently - it should be recoverable
|
||||
return;
|
||||
}
|
||||
if (t instanceof VirtualMachineError) {
|
||||
throw (VirtualMachineError) t;
|
||||
}
|
||||
// All other instances of Throwable will be silently swallowed
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the supplied Throwable is an instance of
|
||||
* <code>InvocationTargetException</code> and returns the throwable that is
|
||||
* wrapped by it, if there is any.
|
||||
*
|
||||
* @param t the Throwable to check
|
||||
* @return <code>t</code> or <code>t.getCause()</code>
|
||||
*/
|
||||
public static Throwable unwrapInvocationTargetException(Throwable t) {
|
||||
if (t instanceof InvocationTargetException && t.getCause() != null) {
|
||||
return t.getCause();
|
||||
}
|
||||
return t;
|
||||
}
|
||||
}
|
||||
91
java/org/apache/jasper/runtime/HttpJspBase.java
Normal file
91
java/org/apache/jasper/runtime/HttpJspBase.java
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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 javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.jsp.HttpJspPage;
|
||||
|
||||
import org.apache.jasper.compiler.Localizer;
|
||||
|
||||
/**
|
||||
* This is the super class of all JSP-generated servlets.
|
||||
*
|
||||
* @author Anil K. Vijendran
|
||||
*/
|
||||
public abstract class HttpJspBase extends HttpServlet implements HttpJspPage {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected HttpJspBase() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void init(ServletConfig config)
|
||||
throws ServletException
|
||||
{
|
||||
super.init(config);
|
||||
jspInit();
|
||||
_jspInit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServletInfo() {
|
||||
return Localizer.getMessage("jsp.engine.info");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void destroy() {
|
||||
jspDestroy();
|
||||
_jspDestroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Entry point into service.
|
||||
*/
|
||||
@Override
|
||||
public final void service(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException
|
||||
{
|
||||
_jspService(request, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jspInit() {
|
||||
}
|
||||
|
||||
public void _jspInit() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jspDestroy() {
|
||||
}
|
||||
|
||||
protected void _jspDestroy() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract void _jspService(HttpServletRequest request,
|
||||
HttpServletResponse response)
|
||||
throws ServletException, IOException;
|
||||
}
|
||||
37
java/org/apache/jasper/runtime/InstanceManagerFactory.java
Normal file
37
java/org/apache/jasper/runtime/InstanceManagerFactory.java
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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 javax.servlet.ServletConfig;
|
||||
|
||||
import org.apache.tomcat.InstanceManager;
|
||||
|
||||
public class InstanceManagerFactory {
|
||||
|
||||
private InstanceManagerFactory() {
|
||||
}
|
||||
|
||||
public static InstanceManager getInstanceManager(ServletConfig config) {
|
||||
InstanceManager instanceManager =
|
||||
(InstanceManager) config.getServletContext().getAttribute(InstanceManager.class.getName());
|
||||
if (instanceManager == null) {
|
||||
throw new IllegalStateException("No org.apache.tomcat.InstanceManager set in ServletContext");
|
||||
}
|
||||
return instanceManager;
|
||||
}
|
||||
|
||||
}
|
||||
144
java/org/apache/jasper/runtime/JspApplicationContextImpl.java
Normal file
144
java/org/apache/jasper/runtime/JspApplicationContextImpl.java
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* 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.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.el.CompositeELResolver;
|
||||
import javax.el.ELContext;
|
||||
import javax.el.ELContextEvent;
|
||||
import javax.el.ELContextListener;
|
||||
import javax.el.ELResolver;
|
||||
import javax.el.ExpressionFactory;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.jsp.JspApplicationContext;
|
||||
import javax.servlet.jsp.JspContext;
|
||||
|
||||
import org.apache.jasper.Constants;
|
||||
import org.apache.jasper.el.ELContextImpl;
|
||||
import org.apache.jasper.el.JasperELResolver;
|
||||
|
||||
/**
|
||||
* Implementation of JspApplicationContext
|
||||
*
|
||||
* @author Jacob Hookom
|
||||
*/
|
||||
public class JspApplicationContextImpl implements JspApplicationContext {
|
||||
|
||||
private static final String KEY = JspApplicationContextImpl.class.getName();
|
||||
|
||||
private final ExpressionFactory expressionFactory =
|
||||
ExpressionFactory.newInstance();
|
||||
|
||||
private final List<ELContextListener> contextListeners = new ArrayList<>();
|
||||
|
||||
private final List<ELResolver> resolvers = new ArrayList<>();
|
||||
|
||||
private boolean instantiated = false;
|
||||
|
||||
private ELResolver resolver;
|
||||
|
||||
public JspApplicationContextImpl() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addELContextListener(ELContextListener listener) {
|
||||
if (listener == null) {
|
||||
throw new IllegalArgumentException("ELContextListener was null");
|
||||
}
|
||||
this.contextListeners.add(listener);
|
||||
}
|
||||
|
||||
public static JspApplicationContextImpl getInstance(ServletContext context) {
|
||||
if (context == null) {
|
||||
throw new IllegalArgumentException("ServletContext was null");
|
||||
}
|
||||
JspApplicationContextImpl impl = (JspApplicationContextImpl) context
|
||||
.getAttribute(KEY);
|
||||
if (impl == null) {
|
||||
impl = new JspApplicationContextImpl();
|
||||
context.setAttribute(KEY, impl);
|
||||
}
|
||||
return impl;
|
||||
}
|
||||
|
||||
public ELContextImpl createELContext(JspContext context) {
|
||||
if (context == null) {
|
||||
throw new IllegalArgumentException("JspContext was null");
|
||||
}
|
||||
|
||||
// create ELContext for JspContext
|
||||
final ELResolver r = this.createELResolver();
|
||||
ELContextImpl ctx;
|
||||
if (Constants.IS_SECURITY_ENABLED) {
|
||||
ctx = AccessController.doPrivileged(
|
||||
new PrivilegedAction<ELContextImpl>() {
|
||||
@Override
|
||||
public ELContextImpl run() {
|
||||
return new ELContextImpl(r);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
ctx = new ELContextImpl(r);
|
||||
}
|
||||
ctx.putContext(JspContext.class, context);
|
||||
|
||||
// alert all ELContextListeners
|
||||
fireListeners(ctx);
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
protected void fireListeners(ELContext elContext) {
|
||||
ELContextEvent event = new ELContextEvent(elContext);
|
||||
for (int i = 0; i < this.contextListeners.size(); i++) {
|
||||
this.contextListeners.get(i).contextCreated(event);
|
||||
}
|
||||
}
|
||||
|
||||
private ELResolver createELResolver() {
|
||||
this.instantiated = true;
|
||||
if (this.resolver == null) {
|
||||
CompositeELResolver r = new JasperELResolver(this.resolvers,
|
||||
expressionFactory.getStreamELResolver());
|
||||
this.resolver = r;
|
||||
}
|
||||
return this.resolver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addELResolver(ELResolver resolver) throws IllegalStateException {
|
||||
if (resolver == null) {
|
||||
throw new IllegalArgumentException("ELResolver was null");
|
||||
}
|
||||
if (this.instantiated) {
|
||||
throw new IllegalStateException(
|
||||
"cannot call addELResolver after the first request has been made");
|
||||
}
|
||||
this.resolvers.add(resolver);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionFactory getExpressionFactory() {
|
||||
return expressionFactory;
|
||||
}
|
||||
|
||||
}
|
||||
662
java/org/apache/jasper/runtime/JspContextWrapper.java
Normal file
662
java/org/apache/jasper/runtime/JspContextWrapper.java
Normal file
@@ -0,0 +1,662 @@
|
||||
/*
|
||||
* 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.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.el.ELContext;
|
||||
import javax.el.ELResolver;
|
||||
import javax.el.EvaluationListener;
|
||||
import javax.el.FunctionMapper;
|
||||
import javax.el.ImportHandler;
|
||||
import javax.el.VariableMapper;
|
||||
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.JspApplicationContext;
|
||||
import javax.servlet.jsp.JspContext;
|
||||
import javax.servlet.jsp.JspFactory;
|
||||
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.JspTag;
|
||||
import javax.servlet.jsp.tagext.VariableInfo;
|
||||
|
||||
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
|
||||
* @author Jacob Hookom
|
||||
*/
|
||||
@SuppressWarnings("deprecation") // Have to support old JSP EL API
|
||||
public class JspContextWrapper extends PageContext implements VariableResolver {
|
||||
|
||||
private final JspTag jspTag;
|
||||
|
||||
// Invoking JSP context
|
||||
private final PageContext invokingJspCtxt;
|
||||
|
||||
private final transient HashMap<String, Object> pageAttributes;
|
||||
|
||||
// ArrayList of NESTED scripting variables
|
||||
private final ArrayList<String> nestedVars;
|
||||
|
||||
// ArrayList of AT_BEGIN scripting variables
|
||||
private final ArrayList<String> atBeginVars;
|
||||
|
||||
// ArrayList of AT_END scripting variables
|
||||
private final ArrayList<String> atEndVars;
|
||||
|
||||
private final Map<String,String> aliases;
|
||||
|
||||
private final HashMap<String, Object> originalNestedVars;
|
||||
|
||||
private ServletContext servletContext = null;
|
||||
|
||||
private ELContext elContext = null;
|
||||
|
||||
private final PageContext rootJspCtxt;
|
||||
|
||||
public JspContextWrapper(JspTag jspTag, JspContext jspContext,
|
||||
ArrayList<String> nestedVars, ArrayList<String> atBeginVars,
|
||||
ArrayList<String> atEndVars, Map<String,String> aliases) {
|
||||
this.jspTag = jspTag;
|
||||
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 new NullPointerException(Localizer
|
||||
.getMessage("jsp.error.attribute.null_name"));
|
||||
}
|
||||
|
||||
return pageAttributes.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
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 rootJspCtxt.getAttribute(name, scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
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 {
|
||||
rootJspCtxt.setAttribute(name, value, scope);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
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 = 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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttribute(String name) {
|
||||
|
||||
if (name == null) {
|
||||
throw new NullPointerException(Localizer
|
||||
.getMessage("jsp.error.attribute.null_name"));
|
||||
}
|
||||
|
||||
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 new NullPointerException(Localizer
|
||||
.getMessage("jsp.error.attribute.null_name"));
|
||||
}
|
||||
|
||||
if (scope == PAGE_SCOPE) {
|
||||
pageAttributes.remove(name);
|
||||
} else {
|
||||
rootJspCtxt.removeAttribute(name, scope);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
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 rootJspCtxt.getAttributesScope(name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> 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<String> 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) {
|
||||
for (String varName : nestedVars) {
|
||||
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) {
|
||||
for (String varName : nestedVars) {
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ELContext getELContext() {
|
||||
if (elContext == null) {
|
||||
elContext = new ELContextWrapper(rootJspCtxt.getELContext(), jspTag, this);
|
||||
JspFactory factory = JspFactory.getDefaultFactory();
|
||||
JspApplicationContext jspAppCtxt = factory.getJspApplicationContext(servletContext);
|
||||
if (jspAppCtxt instanceof JspApplicationContextImpl) {
|
||||
((JspApplicationContextImpl) jspAppCtxt).fireListeners(elContext);
|
||||
}
|
||||
}
|
||||
return elContext;
|
||||
}
|
||||
|
||||
|
||||
static class ELContextWrapper extends ELContext {
|
||||
|
||||
private final ELContext wrapped;
|
||||
private final JspTag jspTag;
|
||||
private final PageContext pageContext;
|
||||
private ImportHandler importHandler;
|
||||
|
||||
private ELContextWrapper(ELContext wrapped, JspTag jspTag, PageContext pageContext) {
|
||||
this.wrapped = wrapped;
|
||||
this.jspTag = jspTag;
|
||||
this.pageContext = pageContext;
|
||||
}
|
||||
|
||||
ELContext getWrappedELContext() {
|
||||
return wrapped;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPropertyResolved(boolean resolved) {
|
||||
wrapped.setPropertyResolved(resolved);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPropertyResolved(Object base, Object property) {
|
||||
wrapped.setPropertyResolved(base, property);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPropertyResolved() {
|
||||
return wrapped.isPropertyResolved();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putContext(@SuppressWarnings("rawtypes") Class key, Object contextObject) {
|
||||
wrapped.putContext(key, contextObject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getContext(@SuppressWarnings("rawtypes") Class key) {
|
||||
if (key == JspContext.class) {
|
||||
return pageContext;
|
||||
}
|
||||
return wrapped.getContext(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImportHandler getImportHandler() {
|
||||
if (importHandler == null) {
|
||||
importHandler = new ImportHandler();
|
||||
if (jspTag instanceof JspSourceImports) {
|
||||
Set<String> packageImports = ((JspSourceImports) jspTag).getPackageImports();
|
||||
if (packageImports != null) {
|
||||
for (String packageImport : packageImports) {
|
||||
importHandler.importPackage(packageImport);
|
||||
}
|
||||
}
|
||||
Set<String> classImports = ((JspSourceImports) jspTag).getClassImports();
|
||||
if (classImports != null) {
|
||||
for (String classImport : classImports) {
|
||||
importHandler.importClass(classImport);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return importHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale getLocale() {
|
||||
return wrapped.getLocale();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLocale(Locale locale) {
|
||||
wrapped.setLocale(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEvaluationListener(EvaluationListener listener) {
|
||||
wrapped.addEvaluationListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EvaluationListener> getEvaluationListeners() {
|
||||
return wrapped.getEvaluationListeners();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyBeforeEvaluation(String expression) {
|
||||
wrapped.notifyBeforeEvaluation(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyAfterEvaluation(String expression) {
|
||||
wrapped.notifyAfterEvaluation(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyPropertyResolved(Object base, Object property) {
|
||||
wrapped.notifyPropertyResolved(base, property);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLambdaArgument(String name) {
|
||||
return wrapped.isLambdaArgument(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getLambdaArgument(String name) {
|
||||
return wrapped.getLambdaArgument(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterLambdaScope(Map<String, Object> arguments) {
|
||||
wrapped.enterLambdaScope(arguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitLambdaScope() {
|
||||
wrapped.exitLambdaScope();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convertToType(Object obj, Class<?> type) {
|
||||
return wrapped.convertToType(obj, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ELResolver getELResolver() {
|
||||
return wrapped.getELResolver();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FunctionMapper getFunctionMapper() {
|
||||
return wrapped.getFunctionMapper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VariableMapper getVariableMapper() {
|
||||
return wrapped.getVariableMapper();
|
||||
}
|
||||
}
|
||||
}
|
||||
220
java/org/apache/jasper/runtime/JspFactoryImpl.java
Normal file
220
java/org/apache/jasper/runtime/JspFactoryImpl.java
Normal file
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* 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.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.jsp.JspApplicationContext;
|
||||
import javax.servlet.jsp.JspEngineInfo;
|
||||
import javax.servlet.jsp.JspFactory;
|
||||
import javax.servlet.jsp.PageContext;
|
||||
|
||||
import org.apache.jasper.Constants;
|
||||
|
||||
/**
|
||||
* Implementation of JspFactory.
|
||||
*
|
||||
* @author Anil K. Vijendran
|
||||
*/
|
||||
public class JspFactoryImpl extends JspFactory {
|
||||
|
||||
private static final String SPEC_VERSION = "2.3";
|
||||
private static final boolean USE_POOL =
|
||||
Boolean.parseBoolean(System.getProperty("org.apache.jasper.runtime.JspFactoryImpl.USE_POOL", "true"));
|
||||
private static final int POOL_SIZE =
|
||||
Integer.parseInt(System.getProperty("org.apache.jasper.runtime.JspFactoryImpl.POOL_SIZE", "8"));
|
||||
|
||||
private final ThreadLocal<PageContextPool> localPool = new ThreadLocal<>();
|
||||
|
||||
@Override
|
||||
public PageContext getPageContext(Servlet servlet, ServletRequest request,
|
||||
ServletResponse response, String errorPageURL, boolean needsSession,
|
||||
int bufferSize, boolean autoflush) {
|
||||
|
||||
if( Constants.IS_SECURITY_ENABLED ) {
|
||||
PrivilegedGetPageContext dp = new PrivilegedGetPageContext(
|
||||
this, servlet, request, response, errorPageURL,
|
||||
needsSession, bufferSize, autoflush);
|
||||
return AccessController.doPrivileged(dp);
|
||||
} else {
|
||||
return internalGetPageContext(servlet, request, response,
|
||||
errorPageURL, needsSession,
|
||||
bufferSize, autoflush);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void releasePageContext(PageContext pc) {
|
||||
if( pc == null )
|
||||
return;
|
||||
if( Constants.IS_SECURITY_ENABLED ) {
|
||||
PrivilegedReleasePageContext dp = new PrivilegedReleasePageContext(
|
||||
this,pc);
|
||||
AccessController.doPrivileged(dp);
|
||||
} else {
|
||||
internalReleasePageContext(pc);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JspEngineInfo getEngineInfo() {
|
||||
return new JspEngineInfo() {
|
||||
@Override
|
||||
public String getSpecificationVersion() {
|
||||
return SPEC_VERSION;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private PageContext internalGetPageContext(Servlet servlet, ServletRequest request,
|
||||
ServletResponse response, String errorPageURL, boolean needsSession,
|
||||
int bufferSize, boolean autoflush) {
|
||||
|
||||
PageContext pc;
|
||||
if (USE_POOL) {
|
||||
PageContextPool pool = localPool.get();
|
||||
if (pool == null) {
|
||||
pool = new PageContextPool();
|
||||
localPool.set(pool);
|
||||
}
|
||||
pc = pool.get();
|
||||
if (pc == null) {
|
||||
pc = new PageContextImpl();
|
||||
}
|
||||
} else {
|
||||
pc = new PageContextImpl();
|
||||
}
|
||||
|
||||
try {
|
||||
pc.initialize(servlet, request, response, errorPageURL,
|
||||
needsSession, bufferSize, autoflush);
|
||||
} catch (IOException ioe) {
|
||||
// Implementation never throws IOE but can't change the signature
|
||||
// since it is part of the JSP API
|
||||
}
|
||||
|
||||
return pc;
|
||||
}
|
||||
|
||||
private void internalReleasePageContext(PageContext pc) {
|
||||
pc.release();
|
||||
if (USE_POOL && (pc instanceof PageContextImpl)) {
|
||||
localPool.get().put(pc);
|
||||
}
|
||||
}
|
||||
|
||||
private static class PrivilegedGetPageContext
|
||||
implements PrivilegedAction<PageContext> {
|
||||
|
||||
private JspFactoryImpl factory;
|
||||
private Servlet servlet;
|
||||
private ServletRequest request;
|
||||
private ServletResponse response;
|
||||
private String errorPageURL;
|
||||
private boolean needsSession;
|
||||
private int bufferSize;
|
||||
private boolean autoflush;
|
||||
|
||||
PrivilegedGetPageContext(JspFactoryImpl factory, Servlet servlet,
|
||||
ServletRequest request, ServletResponse response, String errorPageURL,
|
||||
boolean needsSession, int bufferSize, boolean autoflush) {
|
||||
this.factory = factory;
|
||||
this.servlet = servlet;
|
||||
this.request = request;
|
||||
this.response = response;
|
||||
this.errorPageURL = errorPageURL;
|
||||
this.needsSession = needsSession;
|
||||
this.bufferSize = bufferSize;
|
||||
this.autoflush = autoflush;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageContext run() {
|
||||
return factory.internalGetPageContext(servlet, request, response,
|
||||
errorPageURL, needsSession, bufferSize, autoflush);
|
||||
}
|
||||
}
|
||||
|
||||
private static class PrivilegedReleasePageContext
|
||||
implements PrivilegedAction<Void> {
|
||||
|
||||
private JspFactoryImpl factory;
|
||||
private PageContext pageContext;
|
||||
|
||||
PrivilegedReleasePageContext(JspFactoryImpl factory,
|
||||
PageContext pageContext) {
|
||||
this.factory = factory;
|
||||
this.pageContext = pageContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void run() {
|
||||
factory.internalReleasePageContext(pageContext);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class PageContextPool {
|
||||
|
||||
private final PageContext[] pool;
|
||||
|
||||
private int current = -1;
|
||||
|
||||
public PageContextPool() {
|
||||
this.pool = new PageContext[POOL_SIZE];
|
||||
}
|
||||
|
||||
public void put(PageContext o) {
|
||||
if (current < (POOL_SIZE - 1)) {
|
||||
current++;
|
||||
pool[current] = o;
|
||||
}
|
||||
}
|
||||
|
||||
public PageContext get() {
|
||||
PageContext item = null;
|
||||
if (current >= 0) {
|
||||
item = pool[current];
|
||||
current--;
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public JspApplicationContext getJspApplicationContext(
|
||||
final ServletContext context) {
|
||||
if (Constants.IS_SECURITY_ENABLED) {
|
||||
return AccessController.doPrivileged(
|
||||
new PrivilegedAction<JspApplicationContext>() {
|
||||
@Override
|
||||
public JspApplicationContext run() {
|
||||
return JspApplicationContextImpl.getInstance(context);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return JspApplicationContextImpl.getInstance(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
65
java/org/apache/jasper/runtime/JspFragmentHelper.java
Normal file
65
java/org/apache/jasper/runtime/JspFragmentHelper.java
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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 javax.servlet.jsp.JspContext;
|
||||
import javax.servlet.jsp.PageContext;
|
||||
import javax.servlet.jsp.tagext.JspFragment;
|
||||
import javax.servlet.jsp.tagext.JspTag;
|
||||
|
||||
/**
|
||||
* Helper class from which all Jsp Fragment helper classes extend.
|
||||
* This class allows for the emulation of numerous fragments within
|
||||
* a single class, which in turn reduces the load on the class loader
|
||||
* since there are potentially many JspFragments in a single page.
|
||||
* <p>
|
||||
* The class also provides various utility methods for JspFragment
|
||||
* implementations.
|
||||
*
|
||||
* @author Mark Roth
|
||||
*/
|
||||
public abstract class JspFragmentHelper extends JspFragment {
|
||||
|
||||
protected final int discriminator;
|
||||
protected final JspContext jspContext;
|
||||
protected final PageContext _jspx_page_context;
|
||||
protected final JspTag parentTag;
|
||||
|
||||
public JspFragmentHelper( int discriminator, JspContext jspContext,
|
||||
JspTag parentTag )
|
||||
{
|
||||
this.discriminator = discriminator;
|
||||
this.jspContext = jspContext;
|
||||
if(jspContext instanceof PageContext) {
|
||||
_jspx_page_context = (PageContext)jspContext;
|
||||
} else {
|
||||
_jspx_page_context = null;
|
||||
}
|
||||
this.parentTag = parentTag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JspContext getJspContext() {
|
||||
return this.jspContext;
|
||||
}
|
||||
|
||||
public JspTag getParentTag() {
|
||||
return this.parentTag;
|
||||
}
|
||||
|
||||
}
|
||||
983
java/org/apache/jasper/runtime/JspRuntimeLibrary.java
Normal file
983
java/org/apache/jasper/runtime/JspRuntimeLibrary.java
Normal file
@@ -0,0 +1,983 @@
|
||||
/*
|
||||
* 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.beans.PropertyEditor;
|
||||
import java.beans.PropertyEditorManager;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Enumeration;
|
||||
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.jsp.JspException;
|
||||
import javax.servlet.jsp.JspWriter;
|
||||
import javax.servlet.jsp.PageContext;
|
||||
import javax.servlet.jsp.tagext.BodyContent;
|
||||
import javax.servlet.jsp.tagext.BodyTag;
|
||||
import javax.servlet.jsp.tagext.Tag;
|
||||
|
||||
import org.apache.jasper.JasperException;
|
||||
import org.apache.jasper.compiler.Localizer;
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
import org.apache.tomcat.InstanceManager;
|
||||
|
||||
/**
|
||||
* Bunch of util methods that are used by code generated for useBean,
|
||||
* getProperty and setProperty.
|
||||
*
|
||||
* The __begin, __end stuff is there so that the JSP engine can
|
||||
* actually parse this file and inline them if people don't want
|
||||
* runtime dependencies on this class. However, I'm not sure if that
|
||||
* works so well right now. It got forgotten at some point. -akv
|
||||
*
|
||||
* @author Mandar Raje
|
||||
* @author Shawn Bayern
|
||||
*/
|
||||
public class JspRuntimeLibrary {
|
||||
|
||||
/**
|
||||
* Returns the value of the javax.servlet.error.exception request
|
||||
* attribute value, if present, otherwise the value of the
|
||||
* javax.servlet.jsp.jspException request attribute value.
|
||||
*
|
||||
* This method is called at the beginning of the generated servlet code
|
||||
* for a JSP error page, when the "exception" implicit scripting language
|
||||
* variable is initialized.
|
||||
* @param request The Servlet request
|
||||
* @return the throwable in the error attribute if any
|
||||
*/
|
||||
public static Throwable getThrowable(ServletRequest request) {
|
||||
Throwable error = (Throwable) request.getAttribute(
|
||||
RequestDispatcher.ERROR_EXCEPTION);
|
||||
if (error == null) {
|
||||
error = (Throwable) request.getAttribute(PageContext.EXCEPTION);
|
||||
if (error != null) {
|
||||
/*
|
||||
* The only place that sets JSP_EXCEPTION is
|
||||
* PageContextImpl.handlePageException(). It really should set
|
||||
* SERVLET_EXCEPTION, but that would interfere with the
|
||||
* ErrorReportValve. Therefore, if JSP_EXCEPTION is set, we
|
||||
* need to set SERVLET_EXCEPTION.
|
||||
*/
|
||||
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, error);
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
public static boolean coerceToBoolean(String s) {
|
||||
if (s == null || s.length() == 0)
|
||||
return false;
|
||||
else
|
||||
return Boolean.parseBoolean(s);
|
||||
}
|
||||
|
||||
public static byte coerceToByte(String s) {
|
||||
if (s == null || s.length() == 0)
|
||||
return (byte) 0;
|
||||
else
|
||||
return Byte.parseByte(s);
|
||||
}
|
||||
|
||||
public static char coerceToChar(String s) {
|
||||
if (s == null || s.length() == 0) {
|
||||
return (char) 0;
|
||||
} else {
|
||||
return s.charAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
public static double coerceToDouble(String s) {
|
||||
if (s == null || s.length() == 0)
|
||||
return 0;
|
||||
else
|
||||
return Double.parseDouble(s);
|
||||
}
|
||||
|
||||
public static float coerceToFloat(String s) {
|
||||
if (s == null || s.length() == 0)
|
||||
return 0;
|
||||
else
|
||||
return Float.parseFloat(s);
|
||||
}
|
||||
|
||||
public static int coerceToInt(String s) {
|
||||
if (s == null || s.length() == 0)
|
||||
return 0;
|
||||
else
|
||||
return Integer.parseInt(s);
|
||||
}
|
||||
|
||||
public static short coerceToShort(String s) {
|
||||
if (s == null || s.length() == 0)
|
||||
return (short) 0;
|
||||
else
|
||||
return Short.parseShort(s);
|
||||
}
|
||||
|
||||
public static long coerceToLong(String s) {
|
||||
if (s == null || s.length() == 0)
|
||||
return 0;
|
||||
else
|
||||
return Long.parseLong(s);
|
||||
}
|
||||
|
||||
public static Object coerce(String s, Class<?> target) {
|
||||
|
||||
boolean isNullOrEmpty = (s == null || s.length() == 0);
|
||||
|
||||
if (target == Boolean.class) {
|
||||
if (isNullOrEmpty) {
|
||||
s = "false";
|
||||
}
|
||||
return Boolean.valueOf(s);
|
||||
} else if (target == Byte.class) {
|
||||
if (isNullOrEmpty)
|
||||
return Byte.valueOf((byte) 0);
|
||||
else
|
||||
return Byte.valueOf(s);
|
||||
} else if (target == Character.class) {
|
||||
if (isNullOrEmpty)
|
||||
return Character.valueOf((char) 0);
|
||||
else {
|
||||
@SuppressWarnings("null")
|
||||
Character result = Character.valueOf(s.charAt(0));
|
||||
return result;
|
||||
}
|
||||
} else if (target == Double.class) {
|
||||
if (isNullOrEmpty)
|
||||
return Double.valueOf(0);
|
||||
else
|
||||
return Double.valueOf(s);
|
||||
} else if (target == Float.class) {
|
||||
if (isNullOrEmpty)
|
||||
return Float.valueOf(0);
|
||||
else
|
||||
return Float.valueOf(s);
|
||||
} else if (target == Integer.class) {
|
||||
if (isNullOrEmpty)
|
||||
return Integer.valueOf(0);
|
||||
else
|
||||
return Integer.valueOf(s);
|
||||
} else if (target == Short.class) {
|
||||
if (isNullOrEmpty)
|
||||
return Short.valueOf((short) 0);
|
||||
else
|
||||
return Short.valueOf(s);
|
||||
} else if (target == Long.class) {
|
||||
if (isNullOrEmpty)
|
||||
return Long.valueOf(0);
|
||||
else
|
||||
return Long.valueOf(s);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// __begin convertMethod
|
||||
public static Object convert(String propertyName, String s, Class<?> t,
|
||||
Class<?> propertyEditorClass)
|
||||
throws JasperException
|
||||
{
|
||||
try {
|
||||
if (s == null) {
|
||||
if (t.equals(Boolean.class) || t.equals(Boolean.TYPE))
|
||||
s = "false";
|
||||
else
|
||||
return null;
|
||||
}
|
||||
if (propertyEditorClass != null) {
|
||||
return getValueFromBeanInfoPropertyEditor(
|
||||
t, propertyName, s, propertyEditorClass);
|
||||
} else if ( t.equals(Boolean.class) || t.equals(Boolean.TYPE) ) {
|
||||
if (s.equalsIgnoreCase("on") || s.equalsIgnoreCase("true"))
|
||||
s = "true";
|
||||
else
|
||||
s = "false";
|
||||
return Boolean.valueOf(s);
|
||||
} else if ( t.equals(Byte.class) || t.equals(Byte.TYPE) ) {
|
||||
return Byte.valueOf(s);
|
||||
} else if (t.equals(Character.class) || t.equals(Character.TYPE)) {
|
||||
return s.length() > 0 ? Character.valueOf(s.charAt(0)) : null;
|
||||
} else if ( t.equals(Short.class) || t.equals(Short.TYPE) ) {
|
||||
return Short.valueOf(s);
|
||||
} else if ( t.equals(Integer.class) || t.equals(Integer.TYPE) ) {
|
||||
return Integer.valueOf(s);
|
||||
} else if ( t.equals(Float.class) || t.equals(Float.TYPE) ) {
|
||||
return Float.valueOf(s);
|
||||
} else if ( t.equals(Long.class) || t.equals(Long.TYPE) ) {
|
||||
return Long.valueOf(s);
|
||||
} else if ( t.equals(Double.class) || t.equals(Double.TYPE) ) {
|
||||
return Double.valueOf(s);
|
||||
} else if ( t.equals(String.class) ) {
|
||||
return s;
|
||||
} else if ( t.equals(java.io.File.class) ) {
|
||||
return new java.io.File(s);
|
||||
} else if (t.getName().equals("java.lang.Object")) {
|
||||
return new Object[] {s};
|
||||
} else {
|
||||
return getValueFromPropertyEditorManager(
|
||||
t, propertyName, s);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new JasperException(ex);
|
||||
}
|
||||
}
|
||||
// __end convertMethod
|
||||
|
||||
// __begin introspectMethod
|
||||
public static void introspect(Object bean, ServletRequest request)
|
||||
throws JasperException
|
||||
{
|
||||
Enumeration<String> e = request.getParameterNames();
|
||||
while ( e.hasMoreElements() ) {
|
||||
String name = e.nextElement();
|
||||
String value = request.getParameter(name);
|
||||
introspecthelper(bean, name, value, request, name, true);
|
||||
}
|
||||
}
|
||||
// __end introspectMethod
|
||||
|
||||
// __begin introspecthelperMethod
|
||||
public static void introspecthelper(Object bean, String prop,
|
||||
String value, ServletRequest request,
|
||||
String param, boolean ignoreMethodNF)
|
||||
throws JasperException {
|
||||
Method method = null;
|
||||
Class<?> type = null;
|
||||
Class<?> propertyEditorClass = null;
|
||||
try {
|
||||
java.beans.BeanInfo info
|
||||
= java.beans.Introspector.getBeanInfo(bean.getClass());
|
||||
if ( info != null ) {
|
||||
java.beans.PropertyDescriptor pd[]
|
||||
= info.getPropertyDescriptors();
|
||||
for (int i = 0 ; i < pd.length ; i++) {
|
||||
if ( pd[i].getName().equals(prop) ) {
|
||||
method = pd[i].getWriteMethod();
|
||||
type = pd[i].getPropertyType();
|
||||
propertyEditorClass = pd[i].getPropertyEditorClass();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (method != null && type != null) {
|
||||
if (type.isArray()) {
|
||||
if (request == null) {
|
||||
throw new JasperException(
|
||||
Localizer.getMessage("jsp.error.beans.setproperty.noindexset"));
|
||||
}
|
||||
Class<?> t = type.getComponentType();
|
||||
String[] values = request.getParameterValues(param);
|
||||
//XXX Please check.
|
||||
if(values == null) return;
|
||||
if(t.equals(String.class)) {
|
||||
method.invoke(bean, new Object[] { values });
|
||||
} else {
|
||||
createTypedArray (prop, bean, method, values, t,
|
||||
propertyEditorClass);
|
||||
}
|
||||
} else {
|
||||
if(value == null || (param != null && value.equals(""))) return;
|
||||
Object oval = convert(prop, value, type, propertyEditorClass);
|
||||
if ( oval != null )
|
||||
method.invoke(bean, new Object[] { oval });
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex);
|
||||
ExceptionUtils.handleThrowable(thr);
|
||||
throw new JasperException(ex);
|
||||
}
|
||||
if (!ignoreMethodNF && (method == null)) {
|
||||
if (type == null) {
|
||||
throw new JasperException(
|
||||
Localizer.getMessage("jsp.error.beans.noproperty",
|
||||
prop,
|
||||
bean.getClass().getName()));
|
||||
} else {
|
||||
throw new JasperException(
|
||||
Localizer.getMessage("jsp.error.beans.nomethod.setproperty",
|
||||
prop,
|
||||
type.getName(),
|
||||
bean.getClass().getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
// __end introspecthelperMethod
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// functions to convert builtin Java data types to string.
|
||||
//-------------------------------------------------------------------
|
||||
// __begin toStringMethod
|
||||
public static String toString(Object o) {
|
||||
return String.valueOf(o);
|
||||
}
|
||||
|
||||
public static String toString(byte b) {
|
||||
return Byte.toString(b);
|
||||
}
|
||||
|
||||
public static String toString(boolean b) {
|
||||
return Boolean.toString(b);
|
||||
}
|
||||
|
||||
public static String toString(short s) {
|
||||
return Short.toString(s);
|
||||
}
|
||||
|
||||
public static String toString(int i) {
|
||||
return Integer.toString(i);
|
||||
}
|
||||
|
||||
public static String toString(float f) {
|
||||
return Float.toString(f);
|
||||
}
|
||||
|
||||
public static String toString(long l) {
|
||||
return Long.toString(l);
|
||||
}
|
||||
|
||||
public static String toString(double d) {
|
||||
return Double.toString(d);
|
||||
}
|
||||
|
||||
public static String toString(char c) {
|
||||
return Character.toString(c);
|
||||
}
|
||||
// __end toStringMethod
|
||||
|
||||
|
||||
/**
|
||||
* Create a typed array.
|
||||
* This is a special case where params are passed through
|
||||
* the request and the property is indexed.
|
||||
* @param propertyName The property name
|
||||
* @param bean The bean
|
||||
* @param method The method
|
||||
* @param values Array values
|
||||
* @param t The class
|
||||
* @param propertyEditorClass The editor for the property
|
||||
* @throws JasperException An error occurred
|
||||
*/
|
||||
public static void createTypedArray(String propertyName,
|
||||
Object bean,
|
||||
Method method,
|
||||
String[] values,
|
||||
Class<?> t,
|
||||
Class<?> propertyEditorClass)
|
||||
throws JasperException {
|
||||
|
||||
try {
|
||||
if (propertyEditorClass != null) {
|
||||
Object[] tmpval = new Integer[values.length];
|
||||
for (int i=0; i<values.length; i++) {
|
||||
tmpval[i] = getValueFromBeanInfoPropertyEditor(
|
||||
t, propertyName, values[i], propertyEditorClass);
|
||||
}
|
||||
method.invoke (bean, new Object[] {tmpval});
|
||||
} else if (t.equals(Integer.class)) {
|
||||
Integer []tmpval = new Integer[values.length];
|
||||
for (int i = 0 ; i < values.length; i++)
|
||||
tmpval[i] = Integer.valueOf(values[i]);
|
||||
method.invoke (bean, new Object[] {tmpval});
|
||||
} else if (t.equals(Byte.class)) {
|
||||
Byte[] tmpval = new Byte[values.length];
|
||||
for (int i = 0 ; i < values.length; i++)
|
||||
tmpval[i] = Byte.valueOf(values[i]);
|
||||
method.invoke (bean, new Object[] {tmpval});
|
||||
} else if (t.equals(Boolean.class)) {
|
||||
Boolean[] tmpval = new Boolean[values.length];
|
||||
for (int i = 0 ; i < values.length; i++)
|
||||
tmpval[i] = Boolean.valueOf(values[i]);
|
||||
method.invoke (bean, new Object[] {tmpval});
|
||||
} else if (t.equals(Short.class)) {
|
||||
Short[] tmpval = new Short[values.length];
|
||||
for (int i = 0 ; i < values.length; i++)
|
||||
tmpval[i] = Short.valueOf(values[i]);
|
||||
method.invoke (bean, new Object[] {tmpval});
|
||||
} else if (t.equals(Long.class)) {
|
||||
Long[] tmpval = new Long[values.length];
|
||||
for (int i = 0 ; i < values.length; i++)
|
||||
tmpval[i] = Long.valueOf(values[i]);
|
||||
method.invoke (bean, new Object[] {tmpval});
|
||||
} else if (t.equals(Double.class)) {
|
||||
Double[] tmpval = new Double[values.length];
|
||||
for (int i = 0 ; i < values.length; i++)
|
||||
tmpval[i] = Double.valueOf(values[i]);
|
||||
method.invoke (bean, new Object[] {tmpval});
|
||||
} else if (t.equals(Float.class)) {
|
||||
Float[] tmpval = new Float[values.length];
|
||||
for (int i = 0 ; i < values.length; i++)
|
||||
tmpval[i] = Float.valueOf(values[i]);
|
||||
method.invoke (bean, new Object[] {tmpval});
|
||||
} else if (t.equals(Character.class)) {
|
||||
Character[] tmpval = new Character[values.length];
|
||||
for (int i = 0 ; i < values.length; i++)
|
||||
tmpval[i] = Character.valueOf(values[i].charAt(0));
|
||||
method.invoke (bean, new Object[] {tmpval});
|
||||
} else if (t.equals(int.class)) {
|
||||
int []tmpval = new int[values.length];
|
||||
for (int i = 0 ; i < values.length; i++)
|
||||
tmpval[i] = Integer.parseInt (values[i]);
|
||||
method.invoke (bean, new Object[] {tmpval});
|
||||
} else if (t.equals(byte.class)) {
|
||||
byte[] tmpval = new byte[values.length];
|
||||
for (int i = 0 ; i < values.length; i++)
|
||||
tmpval[i] = Byte.parseByte (values[i]);
|
||||
method.invoke (bean, new Object[] {tmpval});
|
||||
} else if (t.equals(boolean.class)) {
|
||||
boolean[] tmpval = new boolean[values.length];
|
||||
for (int i = 0 ; i < values.length; i++)
|
||||
tmpval[i] = Boolean.parseBoolean(values[i]);
|
||||
method.invoke (bean, new Object[] {tmpval});
|
||||
} else if (t.equals(short.class)) {
|
||||
short[] tmpval = new short[values.length];
|
||||
for (int i = 0 ; i < values.length; i++)
|
||||
tmpval[i] = Short.parseShort (values[i]);
|
||||
method.invoke (bean, new Object[] {tmpval});
|
||||
} else if (t.equals(long.class)) {
|
||||
long[] tmpval = new long[values.length];
|
||||
for (int i = 0 ; i < values.length; i++)
|
||||
tmpval[i] = Long.parseLong (values[i]);
|
||||
method.invoke (bean, new Object[] {tmpval});
|
||||
} else if (t.equals(double.class)) {
|
||||
double[] tmpval = new double[values.length];
|
||||
for (int i = 0 ; i < values.length; i++)
|
||||
tmpval[i] = Double.parseDouble(values[i]);
|
||||
method.invoke (bean, new Object[] {tmpval});
|
||||
} else if (t.equals(float.class)) {
|
||||
float[] tmpval = new float[values.length];
|
||||
for (int i = 0 ; i < values.length; i++)
|
||||
tmpval[i] = Float.parseFloat(values[i]);
|
||||
method.invoke (bean, new Object[] {tmpval});
|
||||
} else if (t.equals(char.class)) {
|
||||
char[] tmpval = new char[values.length];
|
||||
for (int i = 0 ; i < values.length; i++)
|
||||
tmpval[i] = values[i].charAt(0);
|
||||
method.invoke (bean, new Object[] {tmpval});
|
||||
} else {
|
||||
Object[] tmpval = new Integer[values.length];
|
||||
for (int i=0; i<values.length; i++) {
|
||||
tmpval[i] =
|
||||
getValueFromPropertyEditorManager(
|
||||
t, propertyName, values[i]);
|
||||
}
|
||||
method.invoke (bean, new Object[] {tmpval});
|
||||
}
|
||||
} catch (RuntimeException | ReflectiveOperationException ex) {
|
||||
Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex);
|
||||
ExceptionUtils.handleThrowable(thr);
|
||||
throw new JasperException ("error in invoking method", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape special shell characters.
|
||||
* @param unescString The string to shell-escape
|
||||
* @return The escaped shell string.
|
||||
*/
|
||||
public static String escapeQueryString(String unescString) {
|
||||
if (unescString == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
StringBuilder escStringBuilder = new StringBuilder();
|
||||
String shellSpChars = "&;`'\"|*?~<>^()[]{}$\\\n";
|
||||
|
||||
for (int index = 0; index < unescString.length(); index++) {
|
||||
char nextChar = unescString.charAt(index);
|
||||
|
||||
if (shellSpChars.indexOf(nextChar) != -1) {
|
||||
escStringBuilder.append('\\');
|
||||
}
|
||||
|
||||
escStringBuilder.append(nextChar);
|
||||
}
|
||||
return escStringBuilder.toString();
|
||||
}
|
||||
|
||||
// __begin lookupReadMethodMethod
|
||||
public static Object handleGetProperty(Object o, String prop)
|
||||
throws JasperException {
|
||||
if (o == null) {
|
||||
throw new JasperException(
|
||||
Localizer.getMessage("jsp.error.beans.nullbean"));
|
||||
}
|
||||
Object value = null;
|
||||
try {
|
||||
Method method = getReadMethod(o.getClass(), prop);
|
||||
value = method.invoke(o, (Object[]) null);
|
||||
} catch (Exception ex) {
|
||||
Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex);
|
||||
ExceptionUtils.handleThrowable(thr);
|
||||
throw new JasperException (ex);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
// __end lookupReadMethodMethod
|
||||
|
||||
// handles <jsp:setProperty> with EL expression for 'value' attribute
|
||||
public static void handleSetPropertyExpression(Object bean,
|
||||
String prop, String expression, PageContext pageContext,
|
||||
ProtectedFunctionMapper functionMapper )
|
||||
throws JasperException
|
||||
{
|
||||
try {
|
||||
Method method = getWriteMethod(bean.getClass(), prop);
|
||||
method.invoke(bean, new Object[] {
|
||||
PageContextImpl.proprietaryEvaluate(
|
||||
expression,
|
||||
method.getParameterTypes()[0],
|
||||
pageContext,
|
||||
functionMapper)
|
||||
});
|
||||
} catch (Exception ex) {
|
||||
Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex);
|
||||
ExceptionUtils.handleThrowable(thr);
|
||||
throw new JasperException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void handleSetProperty(Object bean, String prop,
|
||||
Object value)
|
||||
throws JasperException
|
||||
{
|
||||
try {
|
||||
Method method = getWriteMethod(bean.getClass(), prop);
|
||||
method.invoke(bean, new Object[] { value });
|
||||
} catch (Exception ex) {
|
||||
Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex);
|
||||
ExceptionUtils.handleThrowable(thr);
|
||||
throw new JasperException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void handleSetProperty(Object bean, String prop,
|
||||
int value)
|
||||
throws JasperException
|
||||
{
|
||||
try {
|
||||
Method method = getWriteMethod(bean.getClass(), prop);
|
||||
method.invoke(bean, new Object[] { Integer.valueOf(value) });
|
||||
} catch (Exception ex) {
|
||||
Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex);
|
||||
ExceptionUtils.handleThrowable(thr);
|
||||
throw new JasperException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void handleSetProperty(Object bean, String prop,
|
||||
short value)
|
||||
throws JasperException
|
||||
{
|
||||
try {
|
||||
Method method = getWriteMethod(bean.getClass(), prop);
|
||||
method.invoke(bean, new Object[] { Short.valueOf(value) });
|
||||
} catch (Exception ex) {
|
||||
Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex);
|
||||
ExceptionUtils.handleThrowable(thr);
|
||||
throw new JasperException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void handleSetProperty(Object bean, String prop,
|
||||
long value)
|
||||
throws JasperException
|
||||
{
|
||||
try {
|
||||
Method method = getWriteMethod(bean.getClass(), prop);
|
||||
method.invoke(bean, new Object[] { Long.valueOf(value) });
|
||||
} catch (Exception ex) {
|
||||
Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex);
|
||||
ExceptionUtils.handleThrowable(thr);
|
||||
throw new JasperException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void handleSetProperty(Object bean, String prop,
|
||||
double value)
|
||||
throws JasperException
|
||||
{
|
||||
try {
|
||||
Method method = getWriteMethod(bean.getClass(), prop);
|
||||
method.invoke(bean, new Object[] { Double.valueOf(value) });
|
||||
} catch (Exception ex) {
|
||||
Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex);
|
||||
ExceptionUtils.handleThrowable(thr);
|
||||
throw new JasperException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void handleSetProperty(Object bean, String prop,
|
||||
float value)
|
||||
throws JasperException
|
||||
{
|
||||
try {
|
||||
Method method = getWriteMethod(bean.getClass(), prop);
|
||||
method.invoke(bean, new Object[] { Float.valueOf(value) });
|
||||
} catch (Exception ex) {
|
||||
Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex);
|
||||
ExceptionUtils.handleThrowable(thr);
|
||||
throw new JasperException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void handleSetProperty(Object bean, String prop,
|
||||
char value)
|
||||
throws JasperException
|
||||
{
|
||||
try {
|
||||
Method method = getWriteMethod(bean.getClass(), prop);
|
||||
method.invoke(bean, new Object[] { Character.valueOf(value) });
|
||||
} catch (Exception ex) {
|
||||
Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex);
|
||||
ExceptionUtils.handleThrowable(thr);
|
||||
throw new JasperException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void handleSetProperty(Object bean, String prop,
|
||||
byte value)
|
||||
throws JasperException
|
||||
{
|
||||
try {
|
||||
Method method = getWriteMethod(bean.getClass(), prop);
|
||||
method.invoke(bean, new Object[] { Byte.valueOf(value) });
|
||||
} catch (Exception ex) {
|
||||
Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex);
|
||||
ExceptionUtils.handleThrowable(thr);
|
||||
throw new JasperException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void handleSetProperty(Object bean, String prop,
|
||||
boolean value)
|
||||
throws JasperException
|
||||
{
|
||||
try {
|
||||
Method method = getWriteMethod(bean.getClass(), prop);
|
||||
method.invoke(bean, new Object[] { Boolean.valueOf(value) });
|
||||
} catch (Exception ex) {
|
||||
Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex);
|
||||
ExceptionUtils.handleThrowable(thr);
|
||||
throw new JasperException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static Method getWriteMethod(Class<?> beanClass, String prop)
|
||||
throws JasperException {
|
||||
Method method = null;
|
||||
Class<?> type = null;
|
||||
try {
|
||||
java.beans.BeanInfo info = java.beans.Introspector.getBeanInfo(beanClass);
|
||||
java.beans.PropertyDescriptor pd[] = info.getPropertyDescriptors();
|
||||
for (int i = 0 ; i < pd.length ; i++) {
|
||||
if ( pd[i].getName().equals(prop) ) {
|
||||
method = pd[i].getWriteMethod();
|
||||
type = pd[i].getPropertyType();
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new JasperException (ex);
|
||||
}
|
||||
if (method == null) {
|
||||
if (type == null) {
|
||||
throw new JasperException(Localizer.getMessage(
|
||||
"jsp.error.beans.noproperty", prop, beanClass.getName()));
|
||||
} else {
|
||||
throw new JasperException(Localizer.getMessage(
|
||||
"jsp.error.beans.nomethod.setproperty",
|
||||
prop, type.getName(), beanClass.getName()));
|
||||
}
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
public static Method getReadMethod(Class<?> beanClass, String prop)
|
||||
throws JasperException {
|
||||
|
||||
Method method = null;
|
||||
Class<?> type = null;
|
||||
try {
|
||||
java.beans.BeanInfo info = java.beans.Introspector.getBeanInfo(beanClass);
|
||||
java.beans.PropertyDescriptor pd[] = info.getPropertyDescriptors();
|
||||
for (int i = 0 ; i < pd.length ; i++) {
|
||||
if (pd[i].getName().equals(prop)) {
|
||||
method = pd[i].getReadMethod();
|
||||
type = pd[i].getPropertyType();
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new JasperException (ex);
|
||||
}
|
||||
if (method == null) {
|
||||
if (type == null) {
|
||||
throw new JasperException(Localizer.getMessage(
|
||||
"jsp.error.beans.noproperty", prop, beanClass.getName()));
|
||||
} else {
|
||||
throw new JasperException(Localizer.getMessage(
|
||||
"jsp.error.beans.nomethod", prop, beanClass.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
return method;
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
// PropertyEditor Support
|
||||
|
||||
public static Object getValueFromBeanInfoPropertyEditor(
|
||||
Class<?> attrClass, String attrName, String attrValue,
|
||||
Class<?> propertyEditorClass)
|
||||
throws JasperException
|
||||
{
|
||||
try {
|
||||
PropertyEditor pe = (PropertyEditor)propertyEditorClass.getConstructor().newInstance();
|
||||
pe.setAsText(attrValue);
|
||||
return pe.getValue();
|
||||
} catch (Exception ex) {
|
||||
throw new JasperException(
|
||||
Localizer.getMessage("jsp.error.beans.property.conversion",
|
||||
attrValue, attrClass.getName(), attrName,
|
||||
ex.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
public static Object getValueFromPropertyEditorManager(
|
||||
Class<?> attrClass, String attrName, String attrValue)
|
||||
throws JasperException
|
||||
{
|
||||
try {
|
||||
PropertyEditor propEditor =
|
||||
PropertyEditorManager.findEditor(attrClass);
|
||||
if (propEditor != null) {
|
||||
propEditor.setAsText(attrValue);
|
||||
return propEditor.getValue();
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
Localizer.getMessage("jsp.error.beans.propertyeditor.notregistered"));
|
||||
}
|
||||
} catch (IllegalArgumentException ex) {
|
||||
throw new JasperException(
|
||||
Localizer.getMessage("jsp.error.beans.property.conversion",
|
||||
attrValue, attrClass.getName(), attrName,
|
||||
ex.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************
|
||||
// General Purpose Runtime Methods
|
||||
// ************************************************************************
|
||||
|
||||
|
||||
/**
|
||||
* Convert a possibly relative resource path into a context-relative
|
||||
* resource path that starts with a '/'.
|
||||
*
|
||||
* @param request The servlet request we are processing
|
||||
* @param relativePath The possibly relative resource path
|
||||
* @return an absolute path
|
||||
*/
|
||||
public static String getContextRelativePath(ServletRequest request,
|
||||
String relativePath) {
|
||||
|
||||
if (relativePath.startsWith("/"))
|
||||
return relativePath;
|
||||
if (!(request instanceof HttpServletRequest))
|
||||
return relativePath;
|
||||
HttpServletRequest hrequest = (HttpServletRequest) request;
|
||||
String uri = (String) request.getAttribute(
|
||||
RequestDispatcher.INCLUDE_SERVLET_PATH);
|
||||
if (uri != null) {
|
||||
String pathInfo = (String)
|
||||
request.getAttribute(RequestDispatcher.INCLUDE_PATH_INFO);
|
||||
if (pathInfo == null) {
|
||||
if (uri.lastIndexOf('/') >= 0)
|
||||
uri = uri.substring(0, uri.lastIndexOf('/'));
|
||||
}
|
||||
}
|
||||
else {
|
||||
uri = hrequest.getServletPath();
|
||||
if (uri.lastIndexOf('/') >= 0)
|
||||
uri = uri.substring(0, uri.lastIndexOf('/'));
|
||||
}
|
||||
return uri + '/' + relativePath;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Perform a RequestDispatcher.include() operation, with optional flushing
|
||||
* of the response beforehand.
|
||||
*
|
||||
* @param request The servlet request we are processing
|
||||
* @param response The servlet response we are processing
|
||||
* @param relativePath The relative path of the resource to be included
|
||||
* @param out The Writer to whom we are currently writing
|
||||
* @param flush Should we flush before the include is processed?
|
||||
*
|
||||
* @exception IOException if thrown by the included servlet
|
||||
* @exception ServletException if thrown by the included servlet
|
||||
*/
|
||||
public static void include(ServletRequest request,
|
||||
ServletResponse response,
|
||||
String relativePath,
|
||||
JspWriter out,
|
||||
boolean flush)
|
||||
throws IOException, ServletException {
|
||||
|
||||
if (flush && !(out instanceof BodyContent))
|
||||
out.flush();
|
||||
|
||||
// FIXME - It is tempting to use request.getRequestDispatcher() to
|
||||
// resolve a relative path directly, but Catalina currently does not
|
||||
// take into account whether the caller is inside a RequestDispatcher
|
||||
// include or not. Whether Catalina *should* take that into account
|
||||
// is a spec issue currently under review. In the mean time,
|
||||
// replicate Jasper's previous behavior
|
||||
|
||||
String resourcePath = getContextRelativePath(request, relativePath);
|
||||
RequestDispatcher rd = request.getRequestDispatcher(resourcePath);
|
||||
|
||||
rd.include(request,
|
||||
new ServletResponseWrapperInclude(response, out));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* URL encodes a string, based on the supplied character encoding.
|
||||
* This performs the same function as java.next.URLEncode.encode
|
||||
* in J2SDK1.4, and should be removed if the only platform supported
|
||||
* is 1.4 or higher.
|
||||
* @param s The String to be URL encoded.
|
||||
* @param enc The character encoding
|
||||
* @return The URL encoded String
|
||||
*/
|
||||
public static String URLEncode(String s, String enc) {
|
||||
|
||||
if (s == null) {
|
||||
return "null";
|
||||
}
|
||||
|
||||
if (enc == null) {
|
||||
enc = "ISO-8859-1"; // The default request encoding
|
||||
}
|
||||
|
||||
StringBuilder out = new StringBuilder(s.length());
|
||||
ByteArrayOutputStream buf = new ByteArrayOutputStream();
|
||||
OutputStreamWriter writer = null;
|
||||
try {
|
||||
writer = new OutputStreamWriter(buf, enc);
|
||||
} catch (java.io.UnsupportedEncodingException ex) {
|
||||
// Use the default encoding?
|
||||
writer = new OutputStreamWriter(buf);
|
||||
}
|
||||
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
int c = s.charAt(i);
|
||||
if (c == ' ') {
|
||||
out.append('+');
|
||||
} else if (isSafeChar(c)) {
|
||||
out.append((char)c);
|
||||
} else {
|
||||
// convert to external encoding before hex conversion
|
||||
try {
|
||||
writer.write(c);
|
||||
writer.flush();
|
||||
} catch(IOException e) {
|
||||
buf.reset();
|
||||
continue;
|
||||
}
|
||||
byte[] ba = buf.toByteArray();
|
||||
for (int j = 0; j < ba.length; j++) {
|
||||
out.append('%');
|
||||
// Converting each byte in the buffer
|
||||
out.append(Character.forDigit((ba[j]>>4) & 0xf, 16));
|
||||
out.append(Character.forDigit(ba[j] & 0xf, 16));
|
||||
}
|
||||
buf.reset();
|
||||
}
|
||||
}
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
private static boolean isSafeChar(int c) {
|
||||
if (c >= 'a' && c <= 'z') {
|
||||
return true;
|
||||
}
|
||||
if (c >= 'A' && c <= 'Z') {
|
||||
return true;
|
||||
}
|
||||
if (c >= '0' && c <= '9') {
|
||||
return true;
|
||||
}
|
||||
if (c == '-' || c == '_' || c == '.' || c == '!' ||
|
||||
c == '~' || c == '*' || c == '\'' || c == '(' || c == ')') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public static JspWriter startBufferedBody(PageContext pageContext, BodyTag tag)
|
||||
throws JspException {
|
||||
BodyContent out = pageContext.pushBody();
|
||||
tag.setBodyContent(out);
|
||||
tag.doInitBody();
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
public static void releaseTag(Tag tag, InstanceManager instanceManager, boolean reused) {
|
||||
// Caller ensures pool is non-null if reuse is true
|
||||
if (!reused) {
|
||||
releaseTag(tag, instanceManager);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected static void releaseTag(Tag tag, InstanceManager instanceManager) {
|
||||
try {
|
||||
tag.release();
|
||||
} catch (Throwable t) {
|
||||
ExceptionUtils.handleThrowable(t);
|
||||
Log log = LogFactory.getLog(JspRuntimeLibrary.class);
|
||||
log.warn(Localizer.getMessage("jsp.warning.tagRelease", tag.getClass().getName()), t);
|
||||
}
|
||||
try {
|
||||
instanceManager.destroyInstance(tag);
|
||||
} catch (Exception e) {
|
||||
Throwable t = ExceptionUtils.unwrapInvocationTargetException(e);
|
||||
ExceptionUtils.handleThrowable(t);
|
||||
Log log = LogFactory.getLog(JspRuntimeLibrary.class);
|
||||
log.warn(Localizer.getMessage("jsp.warning.tagPreDestroy", tag.getClass().getName()), t);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
40
java/org/apache/jasper/runtime/JspSourceDependent.java
Normal file
40
java/org/apache/jasper/runtime/JspSourceDependent.java
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.util.Map;
|
||||
|
||||
/**
|
||||
* Interface for tracking the source files dependencies, for the purpose
|
||||
* of compiling out of date pages. This is used for
|
||||
* 1) files that are included by page directives
|
||||
* 2) files that are included by include-prelude and include-coda in jsp:config
|
||||
* 3) files that are tag files and referenced
|
||||
* 4) TLDs referenced
|
||||
*/
|
||||
|
||||
public interface JspSourceDependent {
|
||||
|
||||
/**
|
||||
* Returns a map of file names and last modified time where the current page
|
||||
* has a source dependency on the file.
|
||||
* @return the map of dependent resources
|
||||
*/
|
||||
public Map<String,Long> getDependants();
|
||||
|
||||
}
|
||||
30
java/org/apache/jasper/runtime/JspSourceImports.java
Normal file
30
java/org/apache/jasper/runtime/JspSourceImports.java
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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.util.Set;
|
||||
|
||||
/**
|
||||
* The EL engine needs access to the imports used in the JSP page to configure
|
||||
* the ELContext. The imports are available at compile time but the ELContext
|
||||
* is created lazily per page. This interface exposes the imports at runtime so
|
||||
* that they may be added to the ELContext when it is created.
|
||||
*/
|
||||
public interface JspSourceImports {
|
||||
Set<String> getPackageImports();
|
||||
Set<String> getClassImports();
|
||||
}
|
||||
597
java/org/apache/jasper/runtime/JspWriterImpl.java
Normal file
597
java/org/apache/jasper/runtime/JspWriterImpl.java
Normal file
@@ -0,0 +1,597 @@
|
||||
/*
|
||||
* 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 javax.servlet.ServletResponse;
|
||||
import javax.servlet.jsp.JspWriter;
|
||||
|
||||
import org.apache.jasper.Constants;
|
||||
import org.apache.jasper.compiler.Localizer;
|
||||
import org.apache.jasper.security.SecurityUtil;
|
||||
|
||||
/**
|
||||
* Write text to a character-output stream, buffering characters so as
|
||||
* to provide for the efficient writing of single characters, arrays,
|
||||
* and strings.
|
||||
*
|
||||
* Provide support for discarding for the output that has been
|
||||
* buffered.
|
||||
*
|
||||
* This needs revisiting when the buffering problems in the JSP spec
|
||||
* are fixed -akv
|
||||
*
|
||||
* @author Anil K. Vijendran
|
||||
*/
|
||||
public class JspWriterImpl extends JspWriter {
|
||||
|
||||
private Writer out;
|
||||
private ServletResponse response;
|
||||
private char cb[];
|
||||
private int nextChar;
|
||||
private boolean flushed = false;
|
||||
private boolean closed = false;
|
||||
|
||||
public JspWriterImpl() {
|
||||
super( Constants.DEFAULT_BUFFER_SIZE, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new buffered character-output stream that uses an output
|
||||
* buffer of the given size.
|
||||
*
|
||||
* @param response A Servlet Response
|
||||
* @param sz Output-buffer size, a positive integer
|
||||
* @param autoFlush <code>true</code> to automatically flush on buffer
|
||||
* full, <code>false</code> to throw an overflow exception in that case
|
||||
* @exception IllegalArgumentException If sz is <= 0
|
||||
*/
|
||||
public JspWriterImpl(ServletResponse response, int sz,
|
||||
boolean autoFlush) {
|
||||
super(sz, autoFlush);
|
||||
if (sz < 0)
|
||||
throw new IllegalArgumentException("Buffer size <= 0");
|
||||
this.response = response;
|
||||
cb = sz == 0 ? null : new char[sz];
|
||||
nextChar = 0;
|
||||
}
|
||||
|
||||
void init( ServletResponse response, int sz, boolean autoFlush ) {
|
||||
this.response= response;
|
||||
if( sz > 0 && ( cb == null || sz > cb.length ) )
|
||||
cb=new char[sz];
|
||||
nextChar = 0;
|
||||
this.autoFlush=autoFlush;
|
||||
this.bufferSize=sz;
|
||||
}
|
||||
|
||||
/**
|
||||
* Package-level access
|
||||
*/
|
||||
void recycle() {
|
||||
flushed = false;
|
||||
closed = false;
|
||||
out = null;
|
||||
nextChar = 0;
|
||||
response = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush the output buffer to the underlying character stream, without
|
||||
* flushing the stream itself. This method is non-private only so that it
|
||||
* may be invoked by PrintStream.
|
||||
* @throws IOException Error writing buffered data
|
||||
*/
|
||||
protected final void flushBuffer() throws IOException {
|
||||
if (bufferSize == 0)
|
||||
return;
|
||||
flushed = true;
|
||||
ensureOpen();
|
||||
if (nextChar == 0)
|
||||
return;
|
||||
initOut();
|
||||
out.write(cb, 0, nextChar);
|
||||
nextChar = 0;
|
||||
}
|
||||
|
||||
private void initOut() throws IOException {
|
||||
if (out == null) {
|
||||
out = response.getWriter();
|
||||
}
|
||||
}
|
||||
|
||||
private String getLocalizeMessage(final String message){
|
||||
if (SecurityUtil.isPackageProtectionEnabled()){
|
||||
return AccessController.doPrivileged(new PrivilegedAction<String>(){
|
||||
@Override
|
||||
public String run(){
|
||||
return Localizer.getMessage(message);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return Localizer.getMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Discard the output buffer.
|
||||
*/
|
||||
@Override
|
||||
public final void clear() throws IOException {
|
||||
if ((bufferSize == 0) && (out != null))
|
||||
// clear() is illegal after any unbuffered output (JSP.5.5)
|
||||
throw new IllegalStateException(
|
||||
getLocalizeMessage("jsp.error.ise_on_clear"));
|
||||
if (flushed)
|
||||
throw new IOException(
|
||||
getLocalizeMessage("jsp.error.attempt_to_clear_flushed_buffer"));
|
||||
ensureOpen();
|
||||
nextChar = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearBuffer() throws IOException {
|
||||
if (bufferSize == 0)
|
||||
throw new IllegalStateException(
|
||||
getLocalizeMessage("jsp.error.ise_on_clear"));
|
||||
ensureOpen();
|
||||
nextChar = 0;
|
||||
}
|
||||
|
||||
private final void bufferOverflow() throws IOException {
|
||||
throw new IOException(getLocalizeMessage("jsp.error.overflow"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush the stream.
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
flushBuffer();
|
||||
if (out != null) {
|
||||
out.flush();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the stream.
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (response == null || closed)
|
||||
// multiple calls to close is OK
|
||||
return;
|
||||
flush();
|
||||
if (out != null)
|
||||
out.close();
|
||||
out = null;
|
||||
closed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of bytes unused in the buffer
|
||||
*/
|
||||
@Override
|
||||
public int getRemaining() {
|
||||
return bufferSize - nextChar;
|
||||
}
|
||||
|
||||
/** check to make sure that the stream has not been closed */
|
||||
private void ensureOpen() throws IOException {
|
||||
if (response == null || closed)
|
||||
throw new IOException("Stream closed");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write a single character.
|
||||
*/
|
||||
@Override
|
||||
public void write(int c) throws IOException {
|
||||
ensureOpen();
|
||||
if (bufferSize == 0) {
|
||||
initOut();
|
||||
out.write(c);
|
||||
}
|
||||
else {
|
||||
if (nextChar >= bufferSize)
|
||||
if (autoFlush)
|
||||
flushBuffer();
|
||||
else
|
||||
bufferOverflow();
|
||||
cb[nextChar++] = (char) c;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Our own little min method, to avoid loading java.lang.Math if we've run
|
||||
* out of file descriptors and we're trying to print a stack trace.
|
||||
*/
|
||||
private static int min(int a, int b) {
|
||||
if (a < b) return a;
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a portion of an array of characters.
|
||||
*
|
||||
* <p> Ordinarily this method stores characters from the given array into
|
||||
* this stream's buffer, flushing the buffer to the underlying stream as
|
||||
* needed. If the requested length is at least as large as the buffer,
|
||||
* however, then this method will flush the buffer and write the characters
|
||||
* directly to the underlying stream. Thus redundant
|
||||
* <code>DiscardableBufferedWriter</code>s will not copy data unnecessarily.
|
||||
*
|
||||
* @param cbuf A character array
|
||||
* @param off Offset from which to start reading characters
|
||||
* @param len Number of characters to write
|
||||
*/
|
||||
@Override
|
||||
public void write(char cbuf[], int off, int len)
|
||||
throws IOException
|
||||
{
|
||||
ensureOpen();
|
||||
|
||||
if (bufferSize == 0) {
|
||||
initOut();
|
||||
out.write(cbuf, off, len);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((off < 0) || (off > cbuf.length) || (len < 0) ||
|
||||
((off + len) > cbuf.length) || ((off + len) < 0)) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
} else if (len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (len >= bufferSize) {
|
||||
/* If the request length exceeds the size of the output buffer,
|
||||
flush the buffer and then write the data directly. In this
|
||||
way buffered streams will cascade harmlessly. */
|
||||
if (autoFlush)
|
||||
flushBuffer();
|
||||
else
|
||||
bufferOverflow();
|
||||
initOut();
|
||||
out.write(cbuf, off, len);
|
||||
return;
|
||||
}
|
||||
|
||||
int b = off, t = off + len;
|
||||
while (b < t) {
|
||||
int d = min(bufferSize - nextChar, t - b);
|
||||
System.arraycopy(cbuf, b, cb, nextChar, d);
|
||||
b += d;
|
||||
nextChar += d;
|
||||
if (nextChar >= bufferSize)
|
||||
if (autoFlush)
|
||||
flushBuffer();
|
||||
else
|
||||
bufferOverflow();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an array of characters. This method cannot be inherited from the
|
||||
* Writer class because it must suppress I/O exceptions.
|
||||
*/
|
||||
@Override
|
||||
public void write(char buf[]) throws IOException {
|
||||
write(buf, 0, buf.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a portion of a String.
|
||||
*
|
||||
* @param s String to be written
|
||||
* @param off Offset from which to start reading characters
|
||||
* @param len Number of characters to be written
|
||||
*/
|
||||
@Override
|
||||
public void write(String s, int off, int len) throws IOException {
|
||||
ensureOpen();
|
||||
if (bufferSize == 0) {
|
||||
initOut();
|
||||
out.write(s, off, len);
|
||||
return;
|
||||
}
|
||||
int b = off, t = off + len;
|
||||
while (b < t) {
|
||||
int d = min(bufferSize - nextChar, t - b);
|
||||
s.getChars(b, b + d, cb, nextChar);
|
||||
b += d;
|
||||
nextChar += d;
|
||||
if (nextChar >= bufferSize)
|
||||
if (autoFlush)
|
||||
flushBuffer();
|
||||
else
|
||||
bufferOverflow();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write a line separator. The line separator string is defined by the
|
||||
* system property <code>line.separator</code>, and is not necessarily a
|
||||
* single newline ('\n') character.
|
||||
*
|
||||
* @exception IOException If an I/O error occurs
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void newLine() throws IOException {
|
||||
write(System.lineSeparator());
|
||||
}
|
||||
|
||||
|
||||
/* Methods that do not terminate lines */
|
||||
|
||||
/**
|
||||
* Print a boolean value. The string produced by <code>{@link
|
||||
* java.lang.String#valueOf(boolean)}</code> is translated into bytes
|
||||
* according to the platform's default character encoding, and these bytes
|
||||
* are written in exactly the manner of the <code>{@link
|
||||
* #write(int)}</code> method.
|
||||
*
|
||||
* @param b The <code>boolean</code> to be printed
|
||||
*/
|
||||
@Override
|
||||
public void print(boolean b) throws IOException {
|
||||
write(b ? "true" : "false");
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a character. The character is translated into one or more bytes
|
||||
* according to the platform's default character encoding, and these bytes
|
||||
* are written in exactly the manner of the <code>{@link
|
||||
* #write(int)}</code> method.
|
||||
*
|
||||
* @param c The <code>char</code> to be printed
|
||||
*/
|
||||
@Override
|
||||
public void print(char c) throws IOException {
|
||||
write(String.valueOf(c));
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an integer. The string produced by <code>{@link
|
||||
* java.lang.String#valueOf(int)}</code> is translated into bytes according
|
||||
* to the platform's default character encoding, and these bytes are
|
||||
* written in exactly the manner of the <code>{@link #write(int)}</code>
|
||||
* method.
|
||||
*
|
||||
* @param i The <code>int</code> to be printed
|
||||
*/
|
||||
@Override
|
||||
public void print(int i) throws IOException {
|
||||
write(String.valueOf(i));
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a long integer. The string produced by <code>{@link
|
||||
* java.lang.String#valueOf(long)}</code> is translated into bytes
|
||||
* according to the platform's default character encoding, and these bytes
|
||||
* are written in exactly the manner of the <code>{@link #write(int)}</code>
|
||||
* method.
|
||||
*
|
||||
* @param l The <code>long</code> to be printed
|
||||
*/
|
||||
@Override
|
||||
public void print(long l) throws IOException {
|
||||
write(String.valueOf(l));
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a floating-point number. The string produced by <code>{@link
|
||||
* java.lang.String#valueOf(float)}</code> is translated into bytes
|
||||
* according to the platform's default character encoding, and these bytes
|
||||
* are written in exactly the manner of the <code>{@link #write(int)}</code>
|
||||
* method.
|
||||
*
|
||||
* @param f The <code>float</code> to be printed
|
||||
*/
|
||||
@Override
|
||||
public void print(float f) throws IOException {
|
||||
write(String.valueOf(f));
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a double-precision floating-point number. The string produced by
|
||||
* <code>{@link java.lang.String#valueOf(double)}</code> is translated into
|
||||
* bytes according to the platform's default character encoding, and these
|
||||
* bytes are written in exactly the manner of the <code>{@link
|
||||
* #write(int)}</code> method.
|
||||
*
|
||||
* @param d The <code>double</code> to be printed
|
||||
*/
|
||||
@Override
|
||||
public void print(double d) throws IOException {
|
||||
write(String.valueOf(d));
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an array of characters. The characters are converted into bytes
|
||||
* according to the platform's default character encoding, and these bytes
|
||||
* are written in exactly the manner of the <code>{@link #write(int)}</code>
|
||||
* method.
|
||||
*
|
||||
* @param s The array of chars to be printed
|
||||
*
|
||||
* @throws NullPointerException If <code>s</code> is <code>null</code>
|
||||
*/
|
||||
@Override
|
||||
public void print(char s[]) throws IOException {
|
||||
write(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a string. If the argument is <code>null</code> then the string
|
||||
* <code>"null"</code> is printed. Otherwise, the string's characters are
|
||||
* converted into bytes according to the platform's default character
|
||||
* encoding, and these bytes are written in exactly the manner of the
|
||||
* <code>{@link #write(int)}</code> method.
|
||||
*
|
||||
* @param s The <code>String</code> to be printed
|
||||
*/
|
||||
@Override
|
||||
public void print(String s) throws IOException {
|
||||
if (s == null) {
|
||||
s = "null";
|
||||
}
|
||||
write(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an object. The string produced by the <code>{@link
|
||||
* java.lang.String#valueOf(Object)}</code> method is translated into bytes
|
||||
* according to the platform's default character encoding, and these bytes
|
||||
* are written in exactly the manner of the <code>{@link #write(int)}</code>
|
||||
* method.
|
||||
*
|
||||
* @param obj The <code>Object</code> to be printed
|
||||
*/
|
||||
@Override
|
||||
public void print(Object obj) throws IOException {
|
||||
write(String.valueOf(obj));
|
||||
}
|
||||
|
||||
/* Methods that do terminate lines */
|
||||
|
||||
/**
|
||||
* Terminate the current line by writing the line separator string. The
|
||||
* line separator string is defined by the system property
|
||||
* <code>line.separator</code>, and is not necessarily a single newline
|
||||
* character (<code>'\n'</code>).
|
||||
*
|
||||
* Need to change this from PrintWriter because the default
|
||||
* println() writes to the sink directly instead of through the
|
||||
* write method...
|
||||
*/
|
||||
@Override
|
||||
public void println() throws IOException {
|
||||
newLine();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a boolean value and then terminate the line. This method behaves
|
||||
* as though it invokes <code>{@link #print(boolean)}</code> and then
|
||||
* <code>{@link #println()}</code>.
|
||||
*/
|
||||
@Override
|
||||
public void println(boolean x) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a character and then terminate the line. This method behaves as
|
||||
* though it invokes <code>{@link #print(char)}</code> and then <code>{@link
|
||||
* #println()}</code>.
|
||||
*/
|
||||
@Override
|
||||
public void println(char x) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an integer and then terminate the line. This method behaves as
|
||||
* though it invokes <code>{@link #print(int)}</code> and then <code>{@link
|
||||
* #println()}</code>.
|
||||
*/
|
||||
@Override
|
||||
public void println(int x) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a long integer and then terminate the line. This method behaves
|
||||
* as though it invokes <code>{@link #print(long)}</code> and then
|
||||
* <code>{@link #println()}</code>.
|
||||
*/
|
||||
@Override
|
||||
public void println(long x) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a floating-point number and then terminate the line. This method
|
||||
* behaves as though it invokes <code>{@link #print(float)}</code> and then
|
||||
* <code>{@link #println()}</code>.
|
||||
*/
|
||||
@Override
|
||||
public void println(float x) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a double-precision floating-point number and then terminate the
|
||||
* line. This method behaves as though it invokes <code>{@link
|
||||
* #print(double)}</code> and then <code>{@link #println()}</code>.
|
||||
*/
|
||||
@Override
|
||||
public void println(double x) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an array of characters and then terminate the line. This method
|
||||
* behaves as though it invokes <code>{@link #print(char[])}</code> and then
|
||||
* <code>{@link #println()}</code>.
|
||||
*/
|
||||
@Override
|
||||
public void println(char x[]) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a String and then terminate the line. This method behaves as
|
||||
* though it invokes <code>{@link #print(String)}</code> and then
|
||||
* <code>{@link #println()}</code>.
|
||||
*/
|
||||
@Override
|
||||
public void println(String x) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an Object and then terminate the line. This method behaves as
|
||||
* though it invokes <code>{@link #print(Object)}</code> and then
|
||||
* <code>{@link #println()}</code>.
|
||||
*/
|
||||
@Override
|
||||
public void println(Object x) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
}
|
||||
969
java/org/apache/jasper/runtime/PageContextImpl.java
Normal file
969
java/org/apache/jasper/runtime/PageContextImpl.java
Normal file
@@ -0,0 +1,969 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
153
java/org/apache/jasper/runtime/ProtectedFunctionMapper.java
Normal file
153
java/org/apache/jasper/runtime/ProtectedFunctionMapper.java
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* 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.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
|
||||
import javax.servlet.jsp.el.FunctionMapper;
|
||||
|
||||
/**
|
||||
* Maps EL functions to their Java method counterparts. Keeps the actual Method
|
||||
* objects protected so that JSP pages can't indirectly do reflection.
|
||||
*
|
||||
* @author Mark Roth
|
||||
* @author Kin-man Chung
|
||||
*/
|
||||
@SuppressWarnings("deprecation") // Have to support old JSP EL API
|
||||
public final class ProtectedFunctionMapper extends javax.el.FunctionMapper
|
||||
implements FunctionMapper {
|
||||
|
||||
/**
|
||||
* Maps "prefix:name" to java.lang.Method objects.
|
||||
*/
|
||||
private HashMap<String,Method> fnmap = null;
|
||||
|
||||
/**
|
||||
* If there is only one function in the map, this is the Method for it.
|
||||
*/
|
||||
private Method theMethod = null;
|
||||
|
||||
/**
|
||||
* Constructor has protected access.
|
||||
*/
|
||||
private ProtectedFunctionMapper() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generated Servlet and Tag Handler implementations call this method to
|
||||
* retrieve an instance of the ProtectedFunctionMapper.
|
||||
*
|
||||
* @return A new protected function mapper.
|
||||
*/
|
||||
public static ProtectedFunctionMapper getInstance() {
|
||||
ProtectedFunctionMapper funcMapper = new ProtectedFunctionMapper();
|
||||
funcMapper.fnmap = new HashMap<>();
|
||||
return funcMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a mapping from the given EL function prefix and name to the given
|
||||
* Java method.
|
||||
*
|
||||
* @param fnQName
|
||||
* The EL function qualified name (including prefix)
|
||||
* @param c
|
||||
* The class containing the Java method
|
||||
* @param methodName
|
||||
* The name of the Java method
|
||||
* @param args
|
||||
* The arguments of the Java method
|
||||
* @throws RuntimeException
|
||||
* if no method with the given signature could be found.
|
||||
*/
|
||||
public void mapFunction(String fnQName, final Class<?> c,
|
||||
final String methodName, final Class<?>[] args) {
|
||||
// Skip if null values were passed in. They indicate a function
|
||||
// added via a lambda or ImportHandler; nether of which need to be
|
||||
// placed in the Map.
|
||||
if (fnQName == null) {
|
||||
return;
|
||||
}
|
||||
java.lang.reflect.Method method;
|
||||
try {
|
||||
method = c.getMethod(methodName, args);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException(
|
||||
"Invalid function mapping - no such method: "
|
||||
+ e.getMessage());
|
||||
}
|
||||
|
||||
this.fnmap.put(fnQName, method);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance for this class, and stores the Method for the given
|
||||
* EL function prefix and name. This method is used for the case when there
|
||||
* is only one function in the EL expression.
|
||||
*
|
||||
* @param fnQName
|
||||
* The EL function qualified name (including prefix)
|
||||
* @param c
|
||||
* The class containing the Java method
|
||||
* @param methodName
|
||||
* The name of the Java method
|
||||
* @param args
|
||||
* The arguments of the Java method
|
||||
* @throws RuntimeException
|
||||
* if no method with the given signature could be found.
|
||||
* @return the mapped function
|
||||
*/
|
||||
public static ProtectedFunctionMapper getMapForFunction(String fnQName,
|
||||
final Class<?> c, final String methodName, final Class<?>[] args) {
|
||||
java.lang.reflect.Method method = null;
|
||||
ProtectedFunctionMapper funcMapper = new ProtectedFunctionMapper();
|
||||
// Skip if null values were passed in. They indicate a function
|
||||
// added via a lambda or ImportHandler; nether of which need to be
|
||||
// placed in the Map.
|
||||
if (fnQName != null) {
|
||||
try {
|
||||
method = c.getMethod(methodName, args);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException(
|
||||
"Invalid function mapping - no such method: "
|
||||
+ e.getMessage());
|
||||
}
|
||||
}
|
||||
funcMapper.theMethod = method;
|
||||
return funcMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the specified local name and prefix into a Java.lang.Method.
|
||||
* Returns null if the prefix and local name are not found.
|
||||
*
|
||||
* @param prefix
|
||||
* the prefix of the function
|
||||
* @param localName
|
||||
* the short name of the function
|
||||
* @return the result of the method mapping. Null means no entry found.
|
||||
*/
|
||||
@Override
|
||||
public Method resolveFunction(String prefix, String localName) {
|
||||
if (this.fnmap != null) {
|
||||
return this.fnmap.get(prefix + ":" + localName);
|
||||
}
|
||||
return theMethod;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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.PrintWriter;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpServletResponseWrapper;
|
||||
import javax.servlet.jsp.JspWriter;
|
||||
|
||||
/**
|
||||
* ServletResponseWrapper used by the JSP 'include' action.
|
||||
*
|
||||
* This wrapper response object is passed to RequestDispatcher.include(), so
|
||||
* that the output of the included resource is appended to that of the
|
||||
* including page.
|
||||
*
|
||||
* @author Pierre Delisle
|
||||
*/
|
||||
|
||||
public class ServletResponseWrapperInclude extends HttpServletResponseWrapper {
|
||||
|
||||
/**
|
||||
* PrintWriter which appends to the JspWriter of the including page.
|
||||
*/
|
||||
private final PrintWriter printWriter;
|
||||
|
||||
private final JspWriter jspWriter;
|
||||
|
||||
public ServletResponseWrapperInclude(ServletResponse response,
|
||||
JspWriter jspWriter) {
|
||||
super((HttpServletResponse)response);
|
||||
this.printWriter = new PrintWriter(jspWriter);
|
||||
this.jspWriter = jspWriter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a wrapper around the JspWriter of the including page.
|
||||
*/
|
||||
@Override
|
||||
public PrintWriter getWriter() throws IOException {
|
||||
return printWriter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletOutputStream getOutputStream() throws IOException {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the output buffer of the JspWriter associated with the including
|
||||
* page.
|
||||
*/
|
||||
@Override
|
||||
public void resetBuffer() {
|
||||
try {
|
||||
jspWriter.clearBuffer();
|
||||
} catch (IOException ioe) {
|
||||
}
|
||||
}
|
||||
}
|
||||
172
java/org/apache/jasper/runtime/TagHandlerPool.java
Normal file
172
java/org/apache/jasper/runtime/TagHandlerPool.java
Normal file
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* 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 javax.servlet.ServletConfig;
|
||||
import javax.servlet.jsp.JspException;
|
||||
import javax.servlet.jsp.tagext.Tag;
|
||||
|
||||
import org.apache.jasper.Constants;
|
||||
import org.apache.tomcat.InstanceManager;
|
||||
|
||||
/**
|
||||
* Pool of tag handlers that can be reused.
|
||||
*
|
||||
* @author Jan Luehe
|
||||
*/
|
||||
public class TagHandlerPool {
|
||||
|
||||
private Tag[] handlers;
|
||||
|
||||
public static final String OPTION_TAGPOOL = "tagpoolClassName";
|
||||
public static final String OPTION_MAXSIZE = "tagpoolMaxSize";
|
||||
|
||||
// index of next available tag handler
|
||||
private int current;
|
||||
protected InstanceManager instanceManager = null;
|
||||
|
||||
public static TagHandlerPool getTagHandlerPool(ServletConfig config) {
|
||||
TagHandlerPool result = null;
|
||||
|
||||
String tpClassName = getOption(config, OPTION_TAGPOOL, null);
|
||||
if (tpClassName != null) {
|
||||
try {
|
||||
Class<?> c = Class.forName(tpClassName);
|
||||
result = (TagHandlerPool) c.getConstructor().newInstance();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
result = null;
|
||||
}
|
||||
}
|
||||
if (result == null)
|
||||
result = new TagHandlerPool();
|
||||
result.init(config);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected void init(ServletConfig config) {
|
||||
int maxSize = -1;
|
||||
String maxSizeS = getOption(config, OPTION_MAXSIZE, null);
|
||||
if (maxSizeS != null) {
|
||||
try {
|
||||
maxSize = Integer.parseInt(maxSizeS);
|
||||
} catch (Exception ex) {
|
||||
maxSize = -1;
|
||||
}
|
||||
}
|
||||
if (maxSize < 0) {
|
||||
maxSize = Constants.MAX_POOL_SIZE;
|
||||
}
|
||||
this.handlers = new Tag[maxSize];
|
||||
this.current = -1;
|
||||
instanceManager = InstanceManagerFactory.getInstanceManager(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a tag handler pool with the default capacity.
|
||||
*/
|
||||
public TagHandlerPool() {
|
||||
// Nothing - jasper generated servlets call the other constructor,
|
||||
// this should be used in future + init .
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next available tag handler from this tag handler pool,
|
||||
* instantiating one if this tag handler pool is empty.
|
||||
*
|
||||
* @param handlerClass
|
||||
* Tag handler class
|
||||
* @return Reused or newly instantiated tag handler
|
||||
* @throws JspException
|
||||
* if a tag handler cannot be instantiated
|
||||
*/
|
||||
public Tag get(Class<? extends Tag> handlerClass) throws JspException {
|
||||
Tag handler;
|
||||
synchronized (this) {
|
||||
if (current >= 0) {
|
||||
handler = handlers[current--];
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
|
||||
// Out of sync block - there is no need for other threads to
|
||||
// wait for us to construct a tag for this thread.
|
||||
try {
|
||||
if (Constants.USE_INSTANCE_MANAGER_FOR_TAGS) {
|
||||
return (Tag) instanceManager.newInstance(
|
||||
handlerClass.getName(), handlerClass.getClassLoader());
|
||||
} else {
|
||||
Tag instance = handlerClass.getConstructor().newInstance();
|
||||
instanceManager.newInstance(instance);
|
||||
return instance;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Throwable t = ExceptionUtils.unwrapInvocationTargetException(e);
|
||||
ExceptionUtils.handleThrowable(t);
|
||||
throw new JspException(e.getMessage(), t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given tag handler to this tag handler pool, unless this tag
|
||||
* handler pool has already reached its capacity, in which case the tag
|
||||
* handler's release() method is called.
|
||||
*
|
||||
* @param handler
|
||||
* Tag handler to add to this tag handler pool
|
||||
*/
|
||||
public void reuse(Tag handler) {
|
||||
synchronized (this) {
|
||||
if (current < (handlers.length - 1)) {
|
||||
handlers[++current] = handler;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// There is no need for other threads to wait for us to release
|
||||
JspRuntimeLibrary.releaseTag(handler, instanceManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the release() method of all available tag handlers in this tag
|
||||
* handler pool.
|
||||
*/
|
||||
public synchronized void release() {
|
||||
for (int i = current; i >= 0; i--) {
|
||||
JspRuntimeLibrary.releaseTag(handlers[i], instanceManager);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected static String getOption(ServletConfig config, String name,
|
||||
String defaultV) {
|
||||
if (config == null)
|
||||
return defaultV;
|
||||
|
||||
String value = config.getInitParameter(name);
|
||||
if (value != null)
|
||||
return value;
|
||||
if (config.getServletContext() == null)
|
||||
return defaultV;
|
||||
value = config.getServletContext().getInitParameter(name);
|
||||
if (value != null)
|
||||
return value;
|
||||
return defaultV;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user