1262
// in java/org/apache/jasper/tagplugins/jstl/Util.java
Override
public void write(int b) throws IOException {
bos.write(b);
}
// in java/org/apache/jasper/runtime/ServletResponseWrapperInclude.java
Override
public PrintWriter getWriter() throws IOException {
return printWriter;
}
// in java/org/apache/jasper/runtime/ServletResponseWrapperInclude.java
Override
public ServletOutputStream getOutputStream() throws IOException {
throw new IllegalStateException();
}
// in java/org/apache/jasper/runtime/JspContextWrapper.java
Override
public void initialize(Servlet servlet, ServletRequest request,
ServletResponse response, String errorPageURL,
boolean needsSession, int bufferSize, boolean autoFlush)
throws IOException, IllegalStateException, IllegalArgumentException {
}
// in java/org/apache/jasper/runtime/JspContextWrapper.java
Override
public void forward(String relativeUrlPath) throws ServletException,
IOException {
invokingJspCtxt.forward(relativeUrlPath);
}
// in java/org/apache/jasper/runtime/JspContextWrapper.java
Override
public void include(String relativeUrlPath) throws ServletException,
IOException {
invokingJspCtxt.include(relativeUrlPath);
}
// in java/org/apache/jasper/runtime/JspContextWrapper.java
Override
public void include(String relativeUrlPath, boolean flush)
throws ServletException, IOException {
invokingJspCtxt.include(relativeUrlPath, false);
}
// in java/org/apache/jasper/runtime/JspContextWrapper.java
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);
}
// in java/org/apache/jasper/runtime/JspContextWrapper.java
Override
public void handlePageException(Throwable t) throws IOException,
ServletException {
invokingJspCtxt.handlePageException(t);
}
// in java/org/apache/jasper/runtime/BodyContentImpl.java
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;
}
}
// in java/org/apache/jasper/runtime/BodyContentImpl.java
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;
}
}
// in java/org/apache/jasper/runtime/BodyContentImpl.java
Override
public void write(char[] buf) throws IOException {
if (writer != null) {
writer.write(buf);
} else {
write(buf, 0, buf.length);
}
}
// in java/org/apache/jasper/runtime/BodyContentImpl.java
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;
}
}
// in java/org/apache/jasper/runtime/BodyContentImpl.java
Override
public void write(String s) throws IOException {
if (writer != null) {
writer.write(s);
} else {
write(s, 0, s.length());
}
}
// in java/org/apache/jasper/runtime/BodyContentImpl.java
Override
public void newLine() throws IOException {
if (writer != null) {
writer.write(LINE_SEPARATOR);
} else {
write(LINE_SEPARATOR);
}
}
// in java/org/apache/jasper/runtime/BodyContentImpl.java
Override
public void print(boolean b) throws IOException {
if (writer != null) {
writer.write(b ? "true" : "false");
} else {
write(b ? "true" : "false");
}
}
// in java/org/apache/jasper/runtime/BodyContentImpl.java
Override
public void print(char c) throws IOException {
if (writer != null) {
writer.write(String.valueOf(c));
} else {
write(String.valueOf(c));
}
}
// in java/org/apache/jasper/runtime/BodyContentImpl.java
Override
public void print(int i) throws IOException {
if (writer != null) {
writer.write(String.valueOf(i));
} else {
write(String.valueOf(i));
}
}
// in java/org/apache/jasper/runtime/BodyContentImpl.java
Override
public void print(long l) throws IOException {
if (writer != null) {
writer.write(String.valueOf(l));
} else {
write(String.valueOf(l));
}
}
// in java/org/apache/jasper/runtime/BodyContentImpl.java
Override
public void print(float f) throws IOException {
if (writer != null) {
writer.write(String.valueOf(f));
} else {
write(String.valueOf(f));
}
}
// in java/org/apache/jasper/runtime/BodyContentImpl.java
Override
public void print(double d) throws IOException {
if (writer != null) {
writer.write(String.valueOf(d));
} else {
write(String.valueOf(d));
}
}
// in java/org/apache/jasper/runtime/BodyContentImpl.java
Override
public void print(char[] s) throws IOException {
if (writer != null) {
writer.write(s);
} else {
write(s);
}
}
// in java/org/apache/jasper/runtime/BodyContentImpl.java
Override
public void print(String s) throws IOException {
if (s == null) s = "null";
if (writer != null) {
writer.write(s);
} else {
write(s);
}
}
// in java/org/apache/jasper/runtime/BodyContentImpl.java
Override
public void print(Object obj) throws IOException {
if (writer != null) {
writer.write(String.valueOf(obj));
} else {
write(String.valueOf(obj));
}
}
// in java/org/apache/jasper/runtime/BodyContentImpl.java
Override
public void println() throws IOException {
newLine();
}
// in java/org/apache/jasper/runtime/BodyContentImpl.java
Override
public void println(boolean x) throws IOException {
print(x);
println();
}
// in java/org/apache/jasper/runtime/BodyContentImpl.java
Override
public void println(char x) throws IOException {
print(x);
println();
}
// in java/org/apache/jasper/runtime/BodyContentImpl.java
Override
public void println(int x) throws IOException {
print(x);
println();
}
// in java/org/apache/jasper/runtime/BodyContentImpl.java
Override
public void println(long x) throws IOException {
print(x);
println();
}
// in java/org/apache/jasper/runtime/BodyContentImpl.java
Override
public void println(float x) throws IOException {
print(x);
println();
}
// in java/org/apache/jasper/runtime/BodyContentImpl.java
Override
public void println(double x) throws IOException{
print(x);
println();
}
// in java/org/apache/jasper/runtime/BodyContentImpl.java
Override
public void println(char x[]) throws IOException {
print(x);
println();
}
// in java/org/apache/jasper/runtime/BodyContentImpl.java
Override
public void println(String x) throws IOException {
print(x);
println();
}
// in java/org/apache/jasper/runtime/BodyContentImpl.java
Override
public void println(Object x) throws IOException {
print(x);
println();
}
// in java/org/apache/jasper/runtime/BodyContentImpl.java
Override
public void clear() throws IOException {
if (writer != null) {
throw new IOException();
} else {
nextChar = 0;
if (LIMIT_BUFFER && (cb.length > Constants.DEFAULT_TAG_BUFFER_SIZE)) {
cb = new char[Constants.DEFAULT_TAG_BUFFER_SIZE];
bufferSize = cb.length;
}
}
}
// in java/org/apache/jasper/runtime/BodyContentImpl.java
Override
public void clearBuffer() throws IOException {
if (writer == null) {
this.clear();
}
}
// in java/org/apache/jasper/runtime/BodyContentImpl.java
Override
public void close() throws IOException {
if (writer != null) {
writer.close();
} else {
closed = true;
}
}
// in java/org/apache/jasper/runtime/BodyContentImpl.java
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.
}
}
// in java/org/apache/jasper/runtime/BodyContentImpl.java
private void ensureOpen() throws IOException {
if (closed) throw new IOException("Stream closed");
}
// in java/org/apache/jasper/runtime/HttpJspBase.java
Override
public final void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
_jspService(request, response);
}
// in java/org/apache/jasper/runtime/PageContextImpl.java
Override
public void initialize(Servlet servlet, ServletRequest request,
ServletResponse response, String errorPageURL,
boolean needsSession, int bufferSize, boolean autoFlush)
throws IOException {
_initialize(servlet, request, response, errorPageURL, needsSession,
bufferSize, autoFlush);
}
// in java/org/apache/jasper/runtime/PageContextImpl.java
Override
public void include(String relativeUrlPath) throws ServletException,
IOException {
JspRuntimeLibrary
.include(request, response, relativeUrlPath, out, true);
}
// in java/org/apache/jasper/runtime/PageContextImpl.java
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;
}
}
}
// in java/org/apache/jasper/runtime/PageContextImpl.java
private void doInclude(String relativeUrlPath, boolean flush)
throws ServletException, IOException {
JspRuntimeLibrary.include(request, response, relativeUrlPath, out,
flush);
}
// in java/org/apache/jasper/runtime/PageContextImpl.java
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;
}
}
}
// in java/org/apache/jasper/runtime/PageContextImpl.java
private void doForward(String relativeUrlPath) throws ServletException,
IOException {
// JSP.4.5 If the buffer was flushed, throw IllegalStateException
try {
out.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);
}
}
// in java/org/apache/jasper/runtime/PageContextImpl.java
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);
}
// in java/org/apache/jasper/runtime/PageContextImpl.java
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;
}
}
}
// in java/org/apache/jasper/runtime/PageContextImpl.java
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,
new Integer(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) {
rootCause = ((JspException) t).getCause();
} else if (t instanceof ELException) {
rootCause = ((ELException) t).getCause();
}
if (rootCause != null) {
throw new ServletException(t.getClass().getName() + ": "
+ t.getMessage(), rootCause);
}
throw new ServletException(t);
}
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
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;
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
private void initOut() throws IOException {
if (out == null) {
out = response.getWriter();
}
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
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;
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
Override
public void clearBuffer() throws IOException {
if (bufferSize == 0)
throw new IllegalStateException(
getLocalizeMessage("jsp.error.ise_on_clear"));
ensureOpen();
nextChar = 0;
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
private final void bufferOverflow() throws IOException {
throw new IOException(getLocalizeMessage("jsp.error.overflow"));
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
Override
public void flush() throws IOException {
flushBuffer();
if (out != null) {
out.flush();
}
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
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;
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
private void ensureOpen() throws IOException {
if (response == null || closed)
throw new IOException("Stream closed");
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
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;
}
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
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();
}
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
Override
public void write(char buf[]) throws IOException {
write(buf, 0, buf.length);
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
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();
}
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
Override
public void write(String s) throws IOException {
// Simple fix for Bugzilla 35410
// Calling the other write function so as to init the buffer anyways
if(s == null) {
write(s, 0, 0);
} else {
write(s, 0, s.length());
}
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
Override
public void newLine() throws IOException {
write(lineSeparator);
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
Override
public void print(boolean b) throws IOException {
write(b ? "true" : "false");
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
Override
public void print(char c) throws IOException {
write(String.valueOf(c));
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
Override
public void print(int i) throws IOException {
write(String.valueOf(i));
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
Override
public void print(long l) throws IOException {
write(String.valueOf(l));
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
Override
public void print(float f) throws IOException {
write(String.valueOf(f));
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
Override
public void print(double d) throws IOException {
write(String.valueOf(d));
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
Override
public void print(char s[]) throws IOException {
write(s);
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
Override
public void print(String s) throws IOException {
if (s == null) {
s = "null";
}
write(s);
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
Override
public void print(Object obj) throws IOException {
write(String.valueOf(obj));
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
Override
public void println() throws IOException {
newLine();
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
Override
public void println(boolean x) throws IOException {
print(x);
println();
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
Override
public void println(char x) throws IOException {
print(x);
println();
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
Override
public void println(int x) throws IOException {
print(x);
println();
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
Override
public void println(long x) throws IOException {
print(x);
println();
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
Override
public void println(float x) throws IOException {
print(x);
println();
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
Override
public void println(double x) throws IOException {
print(x);
println();
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
Override
public void println(char x[]) throws IOException {
print(x);
println();
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
Override
public void println(String x) throws IOException {
print(x);
println();
}
// in java/org/apache/jasper/runtime/JspWriterImpl.java
Override
public void println(Object x) throws IOException {
print(x);
println();
}
// in java/org/apache/jasper/runtime/JspRuntimeLibrary.java
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));
}
// in java/org/apache/jasper/compiler/JspUtil.java
public static InputStream getInputStream(String fname, JarFile jarFile,
JspCompilationContext ctxt) throws IOException {
InputStream in = null;
if (jarFile != null) {
String jarEntryName = fname.substring(1, fname.length());
ZipEntry jarEntry = jarFile.getEntry(jarEntryName);
if (jarEntry == null) {
throw new FileNotFoundException(Localizer.getMessage(
"jsp.error.file.not.found", fname));
}
in = jarFile.getInputStream(jarEntry);
} else {
in = ctxt.getResourceAsStream(fname);
}
if (in == null) {
throw new FileNotFoundException(Localizer.getMessage(
"jsp.error.file.not.found", fname));
}
return in;
}
// in java/org/apache/jasper/compiler/JspUtil.java
static InputStreamReader getReader(String fname, String encoding,
JarFile jarFile, JspCompilationContext ctxt, ErrorDispatcher err)
throws JasperException, IOException {
return getReader(fname, encoding, jarFile, ctxt, err, 0);
}
// in java/org/apache/jasper/compiler/JspUtil.java
static InputStreamReader getReader(String fname, String encoding,
JarFile jarFile, JspCompilationContext ctxt, ErrorDispatcher err,
int skip) throws JasperException, IOException {
InputStreamReader reader = null;
InputStream in = getInputStream(fname, jarFile, ctxt);
for (int i = 0; i < skip; i++) {
in.read();
}
try {
reader = new InputStreamReader(in, encoding);
} catch (UnsupportedEncodingException ex) {
err.jspError("jsp.error.unsupported.encoding", encoding);
}
return reader;
}
// in java/org/apache/jasper/compiler/SmapUtil.java
public static String[] generateSmap(
JspCompilationContext ctxt,
Node.Nodes pageNodes)
throws IOException {
// Scan the nodes for presence of Jasper generated inner classes
PreScanVisitor psVisitor = new PreScanVisitor();
try {
pageNodes.visit(psVisitor);
} catch (JasperException ex) {
}
HashMap<String, SmapStratum> map = psVisitor.getMap();
// set up our SMAP generator
SmapGenerator g = new SmapGenerator();
/** Disable reading of input SMAP because:
1. There is a bug here: getRealPath() is null if .jsp is in a jar
Bugzilla 14660.
2. Mappings from other sources into .jsp files are not supported.
TODO: fix 1. if 2. is not true.
// determine if we have an input SMAP
String smapPath = inputSmapPath(ctxt.getRealPath(ctxt.getJspFile()));
File inputSmap = new File(smapPath);
if (inputSmap.exists()) {
byte[] embeddedSmap = null;
byte[] subSmap = SDEInstaller.readWhole(inputSmap);
String subSmapString = new String(subSmap, SMAP_ENCODING);
g.addSmap(subSmapString, "JSP");
}
**/
// now, assemble info about our own stratum (JSP) using JspLineMap
SmapStratum s = new SmapStratum("JSP");
g.setOutputFileName(unqualify(ctxt.getServletJavaFileName()));
// Map out Node.Nodes
evaluateNodes(pageNodes, s, map, ctxt.getOptions().getMappedFile());
s.optimizeLineSection();
g.addStratum(s, true);
if (ctxt.getOptions().isSmapDumped()) {
File outSmap = new File(ctxt.getClassFileName() + ".smap");
PrintWriter so =
new PrintWriter(
new OutputStreamWriter(
new FileOutputStream(outSmap),
SMAP_ENCODING));
so.print(g.getString());
so.close();
}
String classFileName = ctxt.getClassFileName();
int innerClassCount = map.size();
String [] smapInfo = new String[2 + innerClassCount*2];
smapInfo[0] = classFileName;
smapInfo[1] = g.getString();
int count = 2;
Iterator<Map.Entry<String,SmapStratum>> iter = map.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<String,SmapStratum> entry = iter.next();
String innerClass = entry.getKey();
s = entry.getValue();
s.optimizeLineSection();
g = new SmapGenerator();
g.setOutputFileName(unqualify(ctxt.getServletJavaFileName()));
g.addStratum(s, true);
String innerClassFileName =
classFileName.substring(0, classFileName.indexOf(".class")) +
'$' + innerClass + ".class";
if (ctxt.getOptions().isSmapDumped()) {
File outSmap = new File(innerClassFileName + ".smap");
PrintWriter so =
new PrintWriter(
new OutputStreamWriter(
new FileOutputStream(outSmap),
SMAP_ENCODING));
so.print(g.getString());
so.close();
}
smapInfo[count] = innerClassFileName;
smapInfo[count+1] = g.getString();
count += 2;
}
return smapInfo;
}
// in java/org/apache/jasper/compiler/SmapUtil.java
public static void installSmap(String[] smap)
throws IOException {
if (smap == null) {
return;
}
for (int i = 0; i < smap.length; i += 2) {
File outServlet = new File(smap[i]);
SDEInstaller.install(outServlet,
smap[i+1].getBytes(Constants.ISO_8859_1));
}
}
// in java/org/apache/jasper/compiler/SmapUtil.java
static void install(File classFile, byte[] smap) throws IOException {
File tmpFile = new File(classFile.getPath() + "tmp");
new SDEInstaller(classFile, smap, tmpFile);
if (!classFile.delete()) {
throw new IOException("classFile.delete() failed");
}
if (!tmpFile.renameTo(classFile)) {
throw new IOException("tmpFile.renameTo(classFile) failed");
}
}
// in java/org/apache/jasper/compiler/SmapUtil.java
static byte[] readWhole(File input) throws IOException {
FileInputStream inStream = new FileInputStream(input);
int len = (int)input.length();
byte[] bytes = new byte[len];
if (inStream.read(bytes, 0, len) != len) {
throw new IOException("expected size: " + len);
}
inStream.close();
return bytes;
}
// in java/org/apache/jasper/compiler/SmapUtil.java
void addSDE() throws UnsupportedEncodingException, IOException {
copy(4 + 2 + 2); // magic min/maj version
int constantPoolCountPos = genPos;
int constantPoolCount = readU2();
if (log.isDebugEnabled())
log.debug("constant pool count: " + constantPoolCount);
writeU2(constantPoolCount);
// copy old constant pool return index of SDE symbol, if found
sdeIndex = copyConstantPool(constantPoolCount);
if (sdeIndex < 0) {
// if "SourceDebugExtension" symbol not there add it
writeUtf8ForSDE();
// increment the countantPoolCount
sdeIndex = constantPoolCount;
++constantPoolCount;
randomAccessWriteU2(constantPoolCountPos, constantPoolCount);
if (log.isDebugEnabled())
log.debug("SourceDebugExtension not found, installed at: " + sdeIndex);
} else {
if (log.isDebugEnabled())
log.debug("SourceDebugExtension found at: " + sdeIndex);
}
copy(2 + 2 + 2); // access, this, super
int interfaceCount = readU2();
writeU2(interfaceCount);
if (log.isDebugEnabled())
log.debug("interfaceCount: " + interfaceCount);
copy(interfaceCount * 2);
copyMembers(); // fields
copyMembers(); // methods
int attrCountPos = genPos;
int attrCount = readU2();
writeU2(attrCount);
if (log.isDebugEnabled())
log.debug("class attrCount: " + attrCount);
// copy the class attributes, return true if SDE attr found (not copied)
if (!copyAttrs(attrCount)) {
// we will be adding SDE and it isn't already counted
++attrCount;
randomAccessWriteU2(attrCountPos, attrCount);
if (log.isDebugEnabled())
log.debug("class attrCount incremented");
}
writeAttrForSDE(sdeIndex);
}
// in java/org/apache/jasper/compiler/SmapUtil.java
int copyConstantPool(int constantPoolCount)
throws UnsupportedEncodingException, IOException {
int sdeIndex = -1;
// copy const pool index zero not in class file
for (int i = 1; i < constantPoolCount; ++i) {
int tag = readU1();
writeU1(tag);
switch (tag) {
case 7 : // Class
case 8 : // String
if (log.isDebugEnabled())
log.debug(i + " copying 2 bytes");
copy(2);
break;
case 9 : // Field
case 10 : // Method
case 11 : // InterfaceMethod
case 3 : // Integer
case 4 : // Float
case 12 : // NameAndType
if (log.isDebugEnabled())
log.debug(i + " copying 4 bytes");
copy(4);
break;
case 5 : // Long
case 6 : // Double
if (log.isDebugEnabled())
log.debug(i + " copying 8 bytes");
copy(8);
i++;
break;
case 1 : // Utf8
int len = readU2();
writeU2(len);
byte[] utf8 = readBytes(len);
String str = new String(utf8, "UTF-8");
if (log.isDebugEnabled())
log.debug(i + " read class attr -- '" + str + "'");
if (str.equals(nameSDE)) {
sdeIndex = i;
}
writeBytes(utf8);
break;
default :
throw new IOException("unexpected tag: " + tag);
}
}
return sdeIndex;
}
// in java/org/apache/jasper/compiler/ParserController.java
public Node.Nodes parse(String inFileName)
throws FileNotFoundException, JasperException, IOException {
// If we're parsing a packaged tag file or a resource included by it
// (using an include directive), ctxt.getTagFileJar() returns the
// JAR file from which to read the tag file or included resource,
// respectively.
isTagFile = ctxt.isTagFile();
directiveOnly = false;
return doParse(inFileName, null, ctxt.getTagFileJarResource());
}
// in java/org/apache/jasper/compiler/ParserController.java
public Node.Nodes parseDirectives(String inFileName)
throws FileNotFoundException, JasperException, IOException {
// If we're parsing a packaged tag file or a resource included by it
// (using an include directive), ctxt.getTagFileJar() returns the
// JAR file from which to read the tag file or included resource,
// respectively.
isTagFile = ctxt.isTagFile();
directiveOnly = true;
return doParse(inFileName, null, ctxt.getTagFileJarResource());
}
// in java/org/apache/jasper/compiler/ParserController.java
public Node.Nodes parse(String inFileName, Node parent,
JarResource jarResource)
throws FileNotFoundException, JasperException, IOException {
// For files that are statically included, isTagfile and directiveOnly
// remain unchanged.
return doParse(inFileName, parent, jarResource);
}
// in java/org/apache/jasper/compiler/ParserController.java
public Node.Nodes parseTagFileDirectives(String inFileName,
JarResource jarResource)
throws FileNotFoundException, JasperException, IOException {
boolean isTagFileSave = isTagFile;
boolean directiveOnlySave = directiveOnly;
isTagFile = true;
directiveOnly = true;
Node.Nodes page = doParse(inFileName, null, jarResource);
directiveOnly = directiveOnlySave;
isTagFile = isTagFileSave;
return page;
}
// in java/org/apache/jasper/compiler/ParserController.java
private Node.Nodes doParse(String inFileName,
Node parent,
JarResource jarResource)
throws FileNotFoundException, JasperException, IOException {
Node.Nodes parsedPage = null;
isEncodingSpecifiedInProlog = false;
isBomPresent = false;
isDefaultPageEncoding = false;
JarFile jarFile = (jarResource == null) ? null : jarResource.getJarFile();
String absFileName = resolveFileName(inFileName);
String jspConfigPageEnc = getJspConfigPageEncoding(absFileName);
// Figure out what type of JSP document and encoding type we are
// dealing with
determineSyntaxAndEncoding(absFileName, jarFile, jspConfigPageEnc);
if (parent != null) {
// Included resource, add to dependent list
if (jarFile == null) {
compiler.getPageInfo().addDependant(absFileName,
ctxt.getLastModified(absFileName));
} else {
String entry = absFileName.substring(1);
compiler.getPageInfo().addDependant(
jarResource.getEntry(entry).toString(),
Long.valueOf(jarFile.getEntry(entry).getTime()));
}
}
if ((isXml && isEncodingSpecifiedInProlog) || isBomPresent) {
/*
* Make sure the encoding explicitly specified in the XML
* prolog (if any) matches that in the JSP config element
* (if any), treating "UTF-16", "UTF-16BE", and "UTF-16LE" as
* identical.
*/
if (jspConfigPageEnc != null && !jspConfigPageEnc.equals(sourceEnc)
&& (!jspConfigPageEnc.startsWith("UTF-16")
|| !sourceEnc.startsWith("UTF-16"))) {
err.jspError("jsp.error.prolog_config_encoding_mismatch",
sourceEnc, jspConfigPageEnc);
}
}
// Dispatch to the appropriate parser
if (isXml) {
// JSP document (XML syntax)
// InputStream for jspx page is created and properly closed in
// JspDocumentParser.
parsedPage = JspDocumentParser.parse(this, absFileName,
jarFile, parent,
isTagFile, directiveOnly,
sourceEnc,
jspConfigPageEnc,
isEncodingSpecifiedInProlog,
isBomPresent);
} else {
// Standard syntax
InputStreamReader inStreamReader = null;
try {
inStreamReader = JspUtil.getReader(absFileName, sourceEnc,
jarFile, ctxt, err, skip);
JspReader jspReader = new JspReader(ctxt, absFileName,
sourceEnc, inStreamReader,
err);
parsedPage = Parser.parse(this, jspReader, parent, isTagFile,
directiveOnly, jarResource,
sourceEnc, jspConfigPageEnc,
isDefaultPageEncoding, isBomPresent);
} finally {
if (inStreamReader != null) {
try {
inStreamReader.close();
} catch (Exception any) {
}
}
}
}
if (jarFile != null) {
try {
jarFile.close();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
}
}
baseDirStack.pop();
return parsedPage;
}
// in java/org/apache/jasper/compiler/ParserController.java
private void determineSyntaxAndEncoding(String absFileName,
JarFile jarFile,
String jspConfigPageEnc)
throws JasperException, IOException {
isXml = false;
/*
* 'true' if the syntax (XML or standard) of the file is given
* from external information: either via a JSP configuration element,
* the ".jspx" suffix, or the enclosing file (for included resources)
*/
boolean isExternal = false;
/*
* Indicates whether we need to revert from temporary usage of
* "ISO-8859-1" back to "UTF-8"
*/
boolean revert = false;
JspConfig jspConfig = ctxt.getOptions().getJspConfig();
JspConfig.JspProperty jspProperty = jspConfig.findJspProperty(
absFileName);
if (jspProperty.isXml() != null) {
// If <is-xml> is specified in a <jsp-property-group>, it is used.
isXml = JspUtil.booleanValue(jspProperty.isXml());
isExternal = true;
} else if (absFileName.endsWith(".jspx")
|| absFileName.endsWith(".tagx")) {
isXml = true;
isExternal = true;
}
if (isExternal && !isXml) {
// JSP (standard) syntax. Use encoding specified in jsp-config
// if provided.
sourceEnc = jspConfigPageEnc;
if (sourceEnc != null) {
return;
}
// We don't know the encoding, so use BOM to determine it
sourceEnc = "ISO-8859-1";
} else {
// XML syntax or unknown, (auto)detect encoding ...
Object[] ret = XMLEncodingDetector.getEncoding(absFileName,
jarFile, ctxt, err);
sourceEnc = (String) ret[0];
if (((Boolean) ret[1]).booleanValue()) {
isEncodingSpecifiedInProlog = true;
}
if (((Boolean) ret[2]).booleanValue()) {
isBomPresent = true;
}
skip = ((Integer) ret[3]).intValue();
if (!isXml && sourceEnc.equals("UTF-8")) {
/*
* We don't know if we're dealing with XML or standard syntax.
* Therefore, we need to check to see if the page contains
* a <jsp:root> element.
*
* We need to be careful, because the page may be encoded in
* ISO-8859-1 (or something entirely different), and may
* contain byte sequences that will cause a UTF-8 converter to
* throw exceptions.
*
* It is safe to use a source encoding of ISO-8859-1 in this
* case, as there are no invalid byte sequences in ISO-8859-1,
* and the byte/character sequences we're looking for (i.e.,
* <jsp:root>) are identical in either encoding (both UTF-8
* and ISO-8859-1 are extensions of ASCII).
*/
sourceEnc = "ISO-8859-1";
revert = true;
}
}
if (isXml) {
// (This implies 'isExternal' is TRUE.)
// We know we're dealing with a JSP document (via JSP config or
// ".jspx" suffix), so we're done.
return;
}
/*
* At this point, 'isExternal' or 'isXml' is FALSE.
* Search for jsp:root action, in order to determine if we're dealing
* with XML or standard syntax (unless we already know what we're
* dealing with, i.e., when 'isExternal' is TRUE and 'isXml' is FALSE).
* No check for XML prolog, since nothing prevents a page from
* outputting XML and still using JSP syntax (in this case, the
* XML prolog is treated as template text).
*/
JspReader jspReader = null;
try {
jspReader = new JspReader(ctxt, absFileName, sourceEnc, jarFile,
err);
} catch (FileNotFoundException ex) {
throw new JasperException(ex);
}
jspReader.setSingleFile(true);
Mark startMark = jspReader.mark();
if (!isExternal) {
jspReader.reset(startMark);
if (hasJspRoot(jspReader)) {
if (revert) {
sourceEnc = "UTF-8";
}
isXml = true;
return;
} else {
if (revert && isBomPresent) {
sourceEnc = "UTF-8";
}
isXml = false;
}
}
/*
* At this point, we know we're dealing with JSP syntax.
* If an XML prolog is provided, it's treated as template text.
* Determine the page encoding from the page directive, unless it's
* specified via JSP config.
*/
if (!isBomPresent) {
sourceEnc = jspConfigPageEnc;
if (sourceEnc == null) {
sourceEnc = getPageEncodingForJspSyntax(jspReader, startMark);
if (sourceEnc == null) {
// Default to "ISO-8859-1" per JSP spec
sourceEnc = "ISO-8859-1";
isDefaultPageEncoding = true;
}
}
}
}
// in java/org/apache/jasper/compiler/TldLocationsCache.java
Override
public void scan(JarURLConnection urlConn) throws IOException {
tldScanJar(urlConn);
}
// in java/org/apache/jasper/compiler/TldLocationsCache.java
Override
public void scan(File file) throws IOException {
File metaInf = new File(file, "META-INF");
if (metaInf.isDirectory()) {
tldScanDir(metaInf);
}
}
// in java/org/apache/jasper/compiler/TldLocationsCache.java
private void tldScanDir(File start) throws IOException {
File[] fileList = start.listFiles();
if (fileList != null) {
for (int i = 0; i < fileList.length; i++) {
// Scan recursively
if (fileList[i].isDirectory()) {
tldScanDir(fileList[i]);
} else if (fileList[i].getAbsolutePath().endsWith(TLD_EXT)) {
InputStream stream = null;
try {
stream = new FileInputStream(fileList[i]);
tldScanStream(
fileList[i].toURI().toString(), null, stream);
} finally {
if (stream != null) {
try {
stream.close();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
}
}
}
}
}
}
}
// in java/org/apache/jasper/compiler/TldLocationsCache.java
private void tldScanJar(JarURLConnection jarConn) throws IOException {
Jar jar = null;
InputStream is;
boolean foundTld = false;
URL resourceURL = jarConn.getJarFileURL();
String resourcePath = resourceURL.toString();
try {
jar = JarFactory.newInstance(jarConn.getURL());
jar.nextEntry();
String entryName = jar.getEntryName();
while (entryName != null) {
if (entryName.startsWith("META-INF/") &&
entryName.endsWith(".tld")) {
is = null;
try {
is = jar.getEntryInputStream();
foundTld = true;
tldScanStream(resourcePath, entryName, is);
} finally {
if (is != null) {
try {
is.close();
} catch (IOException ioe) {
// Ignore
}
}
}
}
jar.nextEntry();
entryName = jar.getEntryName();
}
} finally {
if (jar != null) {
jar.close();
}
}
if (!foundTld) {
if (log.isDebugEnabled()) {
log.debug(Localizer.getMessage("jsp.tldCache.noTldInJar",
resourcePath));
} else if (showTldScanWarning) {
// Not entirely thread-safe but a few duplicate log messages are
// not a huge issue
showTldScanWarning = false;
log.info(Localizer.getMessage("jsp.tldCache.noTldSummary"));
}
}
}
// in java/org/apache/jasper/compiler/TldLocationsCache.java
private void tldScanStream(String resourcePath, String entryName,
InputStream stream) throws IOException {
try {
// Parse the tag library descriptor at the specified resource path
String uri = null;
TreeNode tld =
new ParserUtils().parseXMLDocument(resourcePath, stream);
TreeNode uriNode = tld.findChild("uri");
if (uriNode != null) {
String body = uriNode.getBody();
if (body != null)
uri = body;
}
// Add implicit map entry only if its uri is not already
// present in the map
if (uri != null && mappings.get(uri) == null) {
TldLocation location;
if (entryName == null) {
location = new TldLocation(resourcePath);
} else {
location = new TldLocation(entryName, resourcePath);
}
mappings.put(uri, location);
}
} catch (JasperException e) {
// Hack - makes exception handling simpler
throw new IOException(e);
}
}
// in java/org/apache/jasper/compiler/JavacErrorDetail.java
private String[] readFile(InputStream s) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(s));
List<String> lines = new ArrayList<String>();
String line;
while ( (line = reader.readLine()) != null ) {
lines.add(line);
}
return lines.toArray( new String[lines.size()] );
}
// in java/org/apache/jasper/compiler/JarURLResource.java
Override
public JarFile getJarFile() throws IOException {
URL jarFileUrl = new URL("jar:" + jarUrl + "!/");
JarURLConnection conn = (JarURLConnection) jarFileUrl.openConnection();
conn.setUseCaches(false);
conn.connect();
return conn.getJarFile();
}
// in java/org/apache/jasper/compiler/ErrorDispatcher.java
public static JavacErrorDetail[] parseJavacErrors(String errMsg,
String fname,
Node.Nodes page)
throws JasperException, IOException {
return parseJavacMessage(errMsg, fname, page);
}
// in java/org/apache/jasper/compiler/ErrorDispatcher.java
private static JavacErrorDetail[] parseJavacMessage(
String errMsg, String fname, Node.Nodes page)
throws IOException, JasperException {
ArrayList<JavacErrorDetail> errors = new ArrayList<JavacErrorDetail>();
StringBuilder errMsgBuf = null;
int lineNum = -1;
JavacErrorDetail javacError = null;
BufferedReader reader = new BufferedReader(new StringReader(errMsg));
/*
* Parse compilation errors. Each compilation error consists of a file
* path and error line number, followed by a number of lines describing
* the error.
*/
String line = null;
while ((line = reader.readLine()) != null) {
/*
* Error line number is delimited by set of colons.
* Ignore colon following drive letter on Windows (fromIndex = 2).
* XXX Handle deprecation warnings that don't have line info
*/
int beginColon = line.indexOf(':', 2);
int endColon = line.indexOf(':', beginColon + 1);
if ((beginColon >= 0) && (endColon >= 0)) {
if (javacError != null) {
// add previous error to error vector
errors.add(javacError);
}
String lineNumStr = line.substring(beginColon + 1, endColon);
try {
lineNum = Integer.parseInt(lineNumStr);
} catch (NumberFormatException e) {
lineNum = -1;
}
errMsgBuf = new StringBuilder();
javacError = createJavacError(fname, page, errMsgBuf, lineNum);
}
// Ignore messages preceding first error
if (errMsgBuf != null) {
errMsgBuf.append(line);
errMsgBuf.append(Constants.NEWLINE);
}
}
// Add last error to error vector
if (javacError != null) {
errors.add(javacError);
}
reader.close();
JavacErrorDetail[] errDetails = null;
if (errors.size() > 0) {
errDetails = new JavacErrorDetail[errors.size()];
errors.toArray(errDetails);
}
return errDetails;
}
// in java/org/apache/jasper/compiler/AntCompiler.java
Override
public void write(byte[] b)
throws IOException {
findStream().write(b);
}
// in java/org/apache/jasper/servlet/JspServletWrapper.java
public void service(HttpServletRequest request,
HttpServletResponse response,
boolean precompile)
throws ServletException, IOException, FileNotFoundException {
Servlet servlet;
try {
if (ctxt.isRemoved()) {
throw new FileNotFoundException(jspUri);
}
if ((available > 0L) && (available < Long.MAX_VALUE)) {
if (available > System.currentTimeMillis()) {
response.setDateHeader("Retry-After", available);
response.sendError
(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
Localizer.getMessage("jsp.error.unavailable"));
return;
}
// Wait period has expired. Reset.
available = 0;
}
/*
* (1) Compile
*/
if (options.getDevelopment() || firstTime ) {
synchronized (this) {
firstTime = false;
// The following sets reload to true, if necessary
ctxt.compile();
}
} else {
if (compileException != null) {
// Throw cached compilation exception
throw compileException;
}
}
/*
* (2) (Re)load servlet class file
*/
servlet = getServlet();
// If a page is to be precompiled only, return.
if (precompile) {
return;
}
} catch (ServletException ex) {
if (options.getDevelopment()) {
throw handleJspException(ex);
}
throw ex;
} catch (FileNotFoundException fnfe) {
// File has been removed. Let caller handle this.
throw fnfe;
} catch (IOException ex) {
if (options.getDevelopment()) {
throw handleJspException(ex);
}
throw ex;
} catch (IllegalStateException ex) {
if (options.getDevelopment()) {
throw handleJspException(ex);
}
throw ex;
} catch (Exception ex) {
if (options.getDevelopment()) {
throw handleJspException(ex);
}
throw new JasperException(ex);
}
try {
/*
* (3) Handle limitation of number of loaded Jsps
*/
if (unloadAllowed) {
synchronized(this) {
if (unloadByCount) {
if (unloadHandle == null) {
unloadHandle = ctxt.getRuntimeContext().push(this);
} else if (lastUsageTime < ctxt.getRuntimeContext().getLastJspQueueUpdate()) {
ctxt.getRuntimeContext().makeYoungest(unloadHandle);
lastUsageTime = System.currentTimeMillis();
}
} else {
if (lastUsageTime < ctxt.getRuntimeContext().getLastJspQueueUpdate()) {
lastUsageTime = System.currentTimeMillis();
}
}
}
}
/*
* (4) Service request
*/
if (servlet instanceof SingleThreadModel) {
// sync on the wrapper so that the freshness
// of the page is determined right before servicing
synchronized (this) {
servlet.service(request, response);
}
} else {
servlet.service(request, response);
}
} catch (UnavailableException ex) {
String includeRequestUri = (String)
request.getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI);
if (includeRequestUri != null) {
// This file was included. Throw an exception as
// a response.sendError() will be ignored by the
// servlet engine.
throw ex;
}
int unavailableSeconds = ex.getUnavailableSeconds();
if (unavailableSeconds <= 0) {
unavailableSeconds = 60; // Arbitrary default
}
available = System.currentTimeMillis() +
(unavailableSeconds * 1000L);
response.sendError
(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
ex.getMessage());
} catch (ServletException ex) {
if(options.getDevelopment()) {
throw handleJspException(ex);
}
throw ex;
} catch (IOException ex) {
if(options.getDevelopment()) {
throw handleJspException(ex);
}
throw ex;
} catch (IllegalStateException ex) {
if(options.getDevelopment()) {
throw handleJspException(ex);
}
throw ex;
} catch (Exception ex) {
if(options.getDevelopment()) {
throw handleJspException(ex);
}
throw new JasperException(ex);
}
}
// in java/org/apache/jasper/servlet/JspServlet.java
Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
this.config = config;
this.context = config.getServletContext();
// Initialize the JSP Runtime Context
// Check for a custom Options implementation
String engineOptionsName =
config.getInitParameter("engineOptionsClass");
if (engineOptionsName != null) {
// Instantiate the indicated Options implementation
try {
ClassLoader loader = Thread.currentThread()
.getContextClassLoader();
Class<?> engineOptionsClass =
loader.loadClass(engineOptionsName);
Class<?>[] ctorSig =
{ ServletConfig.class, ServletContext.class };
Constructor<?> ctor =
engineOptionsClass.getConstructor(ctorSig);
Object[] args = { config, context };
options = (Options) ctor.newInstance(args);
} catch (Throwable e) {
e = ExceptionUtils.unwrapInvocationTargetException(e);
ExceptionUtils.handleThrowable(e);
// Need to localize this.
log.warn("Failed to load engineOptionsClass", e);
// Use the default Options implementation
options = new EmbeddedServletOptions(config, context);
}
} else {
// Use the default Options implementation
options = new EmbeddedServletOptions(config, context);
}
rctxt = new JspRuntimeContext(context, options);
if (config.getInitParameter("jspFile") != null) {
jspFile = config.getInitParameter("jspFile");
try {
if (null == context.getResource(jspFile)) {
throw new ServletException("missing jspFile");
}
} catch (MalformedURLException e) {
throw new ServletException("Can not locate jsp file", e);
}
try {
if (SecurityUtil.isPackageProtectionEnabled()){
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>(){
@Override
public Object run() throws IOException, ServletException {
serviceJspFile(null, null, jspFile, true);
return null;
}
});
} else {
serviceJspFile(null, null, jspFile, true);
}
} catch (IOException e) {
throw new ServletException("Could not precompile jsp: " + jspFile, e);
} catch (PrivilegedActionException e) {
Throwable t = e.getCause();
if (t instanceof ServletException) throw (ServletException)t;
throw new ServletException("Could not precompile jsp: " + jspFile, e);
}
}
// in java/org/apache/jasper/servlet/JspServlet.java
Override
public Object run() throws IOException, ServletException {
serviceJspFile(null, null, jspFile, true);
return null;
}
// in java/org/apache/jasper/servlet/JspServlet.java
Override
public void service (HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
//jspFile may be configured as an init-param for this servlet instance
String jspUri = jspFile;
if (jspUri == null) {
// JSP specified via <jsp-file> in <servlet> declaration and supplied through
//custom servlet container code
jspUri = (String) request.getAttribute(Constants.JSP_FILE);
}
if (jspUri == null) {
/*
* Check to see if the requested JSP has been the target of a
* RequestDispatcher.include()
*/
jspUri = (String) request.getAttribute(
RequestDispatcher.INCLUDE_SERVLET_PATH);
if (jspUri != null) {
/*
* Requested JSP has been target of
* RequestDispatcher.include(). Its path is assembled from the
* relevant javax.servlet.include.* request attributes
*/
String pathInfo = (String) request.getAttribute(
RequestDispatcher.INCLUDE_PATH_INFO);
if (pathInfo != null) {
jspUri += pathInfo;
}
} else {
/*
* Requested JSP has not been the target of a
* RequestDispatcher.include(). Reconstruct its path from the
* request's getServletPath() and getPathInfo()
*/
jspUri = request.getServletPath();
String pathInfo = request.getPathInfo();
if (pathInfo != null) {
jspUri += pathInfo;
}
}
}
if (log.isDebugEnabled()) {
log.debug("JspEngine --> " + jspUri);
log.debug("\t ServletPath: " + request.getServletPath());
log.debug("\t PathInfo: " + request.getPathInfo());
log.debug("\t RealPath: " + context.getRealPath(jspUri));
log.debug("\t RequestURI: " + request.getRequestURI());
log.debug("\t QueryString: " + request.getQueryString());
}
try {
boolean precompile = preCompile(request);
serviceJspFile(request, response, jspUri, precompile);
} catch (RuntimeException e) {
throw e;
} catch (ServletException e) {
throw e;
} catch (IOException e) {
throw e;
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
throw new ServletException(e);
}
}
// in java/org/apache/jasper/servlet/JspServlet.java
private void serviceJspFile(HttpServletRequest request,
HttpServletResponse response, String jspUri,
boolean precompile)
throws ServletException, IOException {
JspServletWrapper wrapper = rctxt.getWrapper(jspUri);
if (wrapper == null) {
synchronized(this) {
wrapper = rctxt.getWrapper(jspUri);
if (wrapper == null) {
// Check if the requested JSP page exists, to avoid
// creating unnecessary directories and files.
if (null == context.getResource(jspUri)) {
handleMissingResource(request, response, jspUri);
return;
}
wrapper = new JspServletWrapper(config, options, jspUri,
rctxt);
rctxt.addWrapper(jspUri,wrapper);
}
}
}
try {
wrapper.service(request, response, precompile);
} catch (FileNotFoundException fnfe) {
handleMissingResource(request, response, jspUri);
}
}
// in java/org/apache/jasper/servlet/JspServlet.java
private void handleMissingResource(HttpServletRequest request,
HttpServletResponse response, String jspUri)
throws ServletException, IOException {
String includeRequestUri =
(String)request.getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI);
if (includeRequestUri != null) {
// This file was included. Throw an exception as
// a response.sendError() will be ignored
String msg =
Localizer.getMessage("jsp.error.file.not.found",jspUri);
// Strictly, filtering this is an application
// responsibility but just in case...
throw new ServletException(SecurityUtil.filter(msg));
} else {
try {
response.sendError(HttpServletResponse.SC_NOT_FOUND,
request.getRequestURI());
} catch (IllegalStateException ise) {
log.error(Localizer.getMessage("jsp.error.file.not.found",
jspUri));
}
}
return;
}
// in java/org/apache/jasper/el/JspMethodExpression.java
Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeUTF(this.mark);
out.writeObject(this.target);
}
// in java/org/apache/jasper/el/JspMethodExpression.java
Override
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
this.mark = in.readUTF();
this.target = (MethodExpression) in.readObject();
}
// in java/org/apache/jasper/el/JspValueExpression.java
Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeUTF(this.mark);
out.writeObject(this.target);
}
// in java/org/apache/jasper/el/JspValueExpression.java
Override
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
this.mark = in.readUTF();
this.target = (ValueExpression) in.readObject();
}
// in java/org/apache/jasper/xmlparser/XMLEncodingDetector.java
public static Object[] getEncoding(String fname, JarFile jarFile,
JspCompilationContext ctxt,
ErrorDispatcher err)
throws IOException, JasperException
{
InputStream inStream = JspUtil.getInputStream(fname, jarFile, ctxt);
XMLEncodingDetector detector = new XMLEncodingDetector();
Object[] ret = detector.getEncoding(inStream, err);
inStream.close();
return ret;
}
// in java/org/apache/jasper/xmlparser/XMLEncodingDetector.java
private Object[] getEncoding(InputStream in, ErrorDispatcher err)
throws IOException, JasperException
{
this.stream = in;
this.err=err;
createInitialReader();
scanXMLDecl();
return new Object[] { this.encoding,
Boolean.valueOf(this.isEncodingSetInProlog),
Boolean.valueOf(this.isBomPresent),
Integer.valueOf(this.skip) };
}
// in java/org/apache/jasper/xmlparser/XMLEncodingDetector.java
private void createInitialReader() throws IOException, JasperException {
// wrap this stream in RewindableInputStream
stream = new RewindableInputStream(stream);
// perform auto-detect of encoding if necessary
if (encoding == null) {
// read first four bytes and determine encoding
final byte[] b4 = new byte[4];
int count = 0;
for (; count<4; count++ ) {
b4[count] = (byte)stream.read();
}
if (count == 4) {
Object [] encodingDesc = getEncodingName(b4, count);
encoding = (String)(encodingDesc[0]);
isBigEndian = (Boolean)(encodingDesc[1]);
if (encodingDesc.length > 3) {
isBomPresent = ((Boolean)(encodingDesc[2])).booleanValue();
skip = ((Integer)(encodingDesc[3])).intValue();
} else {
isBomPresent = true;
skip = ((Integer)(encodingDesc[2])).intValue();
}
stream.reset();
// Special case UTF-8 files with BOM created by Microsoft
// tools. It's more efficient to consume the BOM than make
// the reader perform extra checks. -Ac
if (count > 2 && encoding.equals("UTF-8")) {
int b0 = b4[0] & 0xFF;
int b1 = b4[1] & 0xFF;
int b2 = b4[2] & 0xFF;
if (b0 == 0xEF && b1 == 0xBB && b2 == 0xBF) {
// ignore first three bytes...
long skipped = stream.skip(3);
if (skipped != 3) {
throw new IOException(Localizer.getMessage(
"xmlParser.skipBomFail"));
}
}
}
reader = createReader(stream, encoding, isBigEndian);
} else {
reader = createReader(stream, encoding, isBigEndian);
}
}
}
// in java/org/apache/jasper/xmlparser/XMLEncodingDetector.java
private Reader createReader(InputStream inputStream, String encoding,
Boolean isBigEndian)
throws IOException, JasperException {
// normalize encoding name
if (encoding == null) {
encoding = "UTF-8";
}
// try to use an optimized reader
String ENCODING = encoding.toUpperCase(Locale.ENGLISH);
if (ENCODING.equals("UTF-8")) {
return new UTF8Reader(inputStream, fBufferSize);
}
if (ENCODING.equals("US-ASCII")) {
return new ASCIIReader(inputStream, fBufferSize);
}
if (ENCODING.equals("ISO-10646-UCS-4")) {
if (isBigEndian != null) {
boolean isBE = isBigEndian.booleanValue();
if (isBE) {
return new UCSReader(inputStream, UCSReader.UCS4BE);
} else {
return new UCSReader(inputStream, UCSReader.UCS4LE);
}
} else {
err.jspError("jsp.error.xml.encodingByteOrderUnsupported",
encoding);
}
}
if (ENCODING.equals("ISO-10646-UCS-2")) {
if (isBigEndian != null) { // sould never happen with this encoding...
boolean isBE = isBigEndian.booleanValue();
if (isBE) {
return new UCSReader(inputStream, UCSReader.UCS2BE);
} else {
return new UCSReader(inputStream, UCSReader.UCS2LE);
}
} else {
err.jspError("jsp.error.xml.encodingByteOrderUnsupported",
encoding);
}
}
// check for valid name
boolean validIANA = XMLChar.isValidIANAEncoding(encoding);
boolean validJava = XMLChar.isValidJavaEncoding(encoding);
if (!validIANA || (fAllowJavaEncodings && !validJava)) {
err.jspError("jsp.error.xml.encodingDeclInvalid", encoding);
// NOTE: AndyH suggested that, on failure, we use ISO Latin 1
// because every byte is a valid ISO Latin 1 character.
// It may not translate correctly but if we failed on
// the encoding anyway, then we're expecting the content
// of the document to be bad. This will just prevent an
// invalid UTF-8 sequence to be detected. This is only
// important when continue-after-fatal-error is turned
// on. -Ac
encoding = "ISO-8859-1";
}
// try to use a Java reader
String javaEncoding = EncodingMap.getIANA2JavaMapping(ENCODING);
if (javaEncoding == null) {
if (fAllowJavaEncodings) {
javaEncoding = encoding;
} else {
err.jspError("jsp.error.xml.encodingDeclInvalid", encoding);
// see comment above.
javaEncoding = "ISO8859_1";
}
}
return new InputStreamReader(inputStream, javaEncoding);
}
// in java/org/apache/jasper/xmlparser/XMLEncodingDetector.java
public int peekChar() throws IOException {
// load more characters, if needed
if (fCurrentEntity.position == fCurrentEntity.count) {
load(0, true);
}
// peek at character
int c = fCurrentEntity.ch[fCurrentEntity.position];
// return peeked character
if (fCurrentEntity.isExternal()) {
return c != '\r' ? c : '\n';
}
else {
return c;
}
}
// in java/org/apache/jasper/xmlparser/XMLEncodingDetector.java
public int scanChar() throws IOException {
// load more characters, if needed
if (fCurrentEntity.position == fCurrentEntity.count) {
load(0, true);
}
// scan character
int c = fCurrentEntity.ch[fCurrentEntity.position++];
boolean external = false;
if (c == '\n' ||
(c == '\r' && (external = fCurrentEntity.isExternal()))) {
if (fCurrentEntity.position == fCurrentEntity.count) {
fCurrentEntity.ch[0] = (char)c;
load(1, false);
}
if (c == '\r' && external) {
if (fCurrentEntity.ch[fCurrentEntity.position++] != '\n') {
fCurrentEntity.position--;
}
c = '\n';
}
}
// return character that was scanned
return c;
}
// in java/org/apache/jasper/xmlparser/XMLEncodingDetector.java
public String scanName() throws IOException {
// load more characters, if needed
if (fCurrentEntity.position == fCurrentEntity.count) {
load(0, true);
}
// scan name
int offset = fCurrentEntity.position;
if (XMLChar.isNameStart(fCurrentEntity.ch[offset])) {
if (++fCurrentEntity.position == fCurrentEntity.count) {
fCurrentEntity.ch[0] = fCurrentEntity.ch[offset];
offset = 0;
if (load(1, false)) {
String symbol = fSymbolTable.addSymbol(fCurrentEntity.ch,
0, 1);
return symbol;
}
}
while (XMLChar.isName(fCurrentEntity.ch[fCurrentEntity.position])) {
if (++fCurrentEntity.position == fCurrentEntity.count) {
int length = fCurrentEntity.position - offset;
if (length == fBufferSize) {
// bad luck we have to resize our buffer
char[] tmp = new char[fBufferSize * 2];
System.arraycopy(fCurrentEntity.ch, offset,
tmp, 0, length);
fCurrentEntity.ch = tmp;
fBufferSize *= 2;
} else {
System.arraycopy(fCurrentEntity.ch, offset,
fCurrentEntity.ch, 0, length);
}
offset = 0;
if (load(length, false)) {
break;
}
}
}
}
int length = fCurrentEntity.position - offset;
// return name
String symbol = null;
if (length > 0) {
symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, offset, length);
}
return symbol;
}
// in java/org/apache/jasper/xmlparser/XMLEncodingDetector.java
public int scanLiteral(int quote, XMLString content)
throws IOException {
// load more characters, if needed
if (fCurrentEntity.position == fCurrentEntity.count) {
load(0, true);
} else if (fCurrentEntity.position == fCurrentEntity.count - 1) {
fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1];
load(1, false);
fCurrentEntity.position = 0;
}
// normalize newlines
int offset = fCurrentEntity.position;
int c = fCurrentEntity.ch[offset];
int newlines = 0;
boolean external = fCurrentEntity.isExternal();
if (c == '\n' || (c == '\r' && external)) {
do {
c = fCurrentEntity.ch[fCurrentEntity.position++];
if (c == '\r' && external) {
newlines++;
if (fCurrentEntity.position == fCurrentEntity.count) {
offset = 0;
fCurrentEntity.position = newlines;
if (load(newlines, false)) {
break;
}
}
if (fCurrentEntity.ch[fCurrentEntity.position] == '\n') {
fCurrentEntity.position++;
offset++;
}
/*** NEWLINE NORMALIZATION ***/
else {
newlines++;
}
/***/
}
else if (c == '\n') {
newlines++;
if (fCurrentEntity.position == fCurrentEntity.count) {
offset = 0;
fCurrentEntity.position = newlines;
if (load(newlines, false)) {
break;
}
}
/*** NEWLINE NORMALIZATION ***
if (fCurrentEntity.ch[fCurrentEntity.position] == '\r'
&& external) {
fCurrentEntity.position++;
offset++;
}
/***/
}
else {
fCurrentEntity.position--;
break;
}
} while (fCurrentEntity.position < fCurrentEntity.count - 1);
for (int i = offset; i < fCurrentEntity.position; i++) {
fCurrentEntity.ch[i] = '\n';
}
int length = fCurrentEntity.position - offset;
if (fCurrentEntity.position == fCurrentEntity.count - 1) {
content.setValues(fCurrentEntity.ch, offset, length);
return -1;
}
}
// scan literal value
while (fCurrentEntity.position < fCurrentEntity.count) {
c = fCurrentEntity.ch[fCurrentEntity.position++];
if ((c == quote &&
(!fCurrentEntity.literal || external))
|| c == '%' || !XMLChar.isContent(c)) {
fCurrentEntity.position--;
break;
}
}
int length = fCurrentEntity.position - offset;
content.setValues(fCurrentEntity.ch, offset, length);
// return next character
if (fCurrentEntity.position != fCurrentEntity.count) {
c = fCurrentEntity.ch[fCurrentEntity.position];
// NOTE: We don't want to accidentally signal the
// end of the literal if we're expanding an
// entity appearing in the literal. -Ac
if (c == quote && fCurrentEntity.literal) {
c = -1;
}
}
else {
c = -1;
}
return c;
}
// in java/org/apache/jasper/xmlparser/XMLEncodingDetector.java
public boolean scanData(String delimiter, XMLStringBuffer buffer)
throws IOException {
boolean done = false;
int delimLen = delimiter.length();
char charAt0 = delimiter.charAt(0);
boolean external = fCurrentEntity.isExternal();
do {
// load more characters, if needed
if (fCurrentEntity.position == fCurrentEntity.count) {
load(0, true);
}
else if (fCurrentEntity.position >= fCurrentEntity.count - delimLen) {
System.arraycopy(fCurrentEntity.ch, fCurrentEntity.position,
fCurrentEntity.ch, 0, fCurrentEntity.count - fCurrentEntity.position);
load(fCurrentEntity.count - fCurrentEntity.position, false);
fCurrentEntity.position = 0;
}
if (fCurrentEntity.position >= fCurrentEntity.count - delimLen) {
// something must be wrong with the input: e.g., file ends an
// unterminated comment
int length = fCurrentEntity.count - fCurrentEntity.position;
buffer.append (fCurrentEntity.ch, fCurrentEntity.position,
length);
fCurrentEntity.position = fCurrentEntity.count;
load(0,true);
return false;
}
// normalize newlines
int offset = fCurrentEntity.position;
int c = fCurrentEntity.ch[offset];
int newlines = 0;
if (c == '\n' || (c == '\r' && external)) {
do {
c = fCurrentEntity.ch[fCurrentEntity.position++];
if (c == '\r' && external) {
newlines++;
if (fCurrentEntity.position == fCurrentEntity.count) {
offset = 0;
fCurrentEntity.position = newlines;
if (load(newlines, false)) {
break;
}
}
if (fCurrentEntity.ch[fCurrentEntity.position] == '\n') {
fCurrentEntity.position++;
offset++;
}
/*** NEWLINE NORMALIZATION ***/
else {
newlines++;
}
}
else if (c == '\n') {
newlines++;
if (fCurrentEntity.position == fCurrentEntity.count) {
offset = 0;
fCurrentEntity.position = newlines;
fCurrentEntity.count = newlines;
if (load(newlines, false)) {
break;
}
}
}
else {
fCurrentEntity.position--;
break;
}
} while (fCurrentEntity.position < fCurrentEntity.count - 1);
for (int i = offset; i < fCurrentEntity.position; i++) {
fCurrentEntity.ch[i] = '\n';
}
int length = fCurrentEntity.position - offset;
if (fCurrentEntity.position == fCurrentEntity.count - 1) {
buffer.append(fCurrentEntity.ch, offset, length);
return true;
}
}
// iterate over buffer looking for delimiter
OUTER: while (fCurrentEntity.position < fCurrentEntity.count) {
c = fCurrentEntity.ch[fCurrentEntity.position++];
if (c == charAt0) {
// looks like we just hit the delimiter
int delimOffset = fCurrentEntity.position - 1;
for (int i = 1; i < delimLen; i++) {
if (fCurrentEntity.position == fCurrentEntity.count) {
fCurrentEntity.position -= i;
break OUTER;
}
c = fCurrentEntity.ch[fCurrentEntity.position++];
if (delimiter.charAt(i) != c) {
fCurrentEntity.position--;
break;
}
}
if (fCurrentEntity.position == delimOffset + delimLen) {
done = true;
break;
}
}
else if (c == '\n' || (external && c == '\r')) {
fCurrentEntity.position--;
break;
}
else if (XMLChar.isInvalid(c)) {
fCurrentEntity.position--;
int length = fCurrentEntity.position - offset;
buffer.append(fCurrentEntity.ch, offset, length);
return true;
}
}
int length = fCurrentEntity.position - offset;
if (done) {
length -= delimLen;
}
buffer.append (fCurrentEntity.ch, offset, length);
// return true if string was skipped
} while (!done);
return !done;
}
// in java/org/apache/jasper/xmlparser/XMLEncodingDetector.java
public boolean skipChar(int c) throws IOException {
// load more characters, if needed
if (fCurrentEntity.position == fCurrentEntity.count) {
load(0, true);
}
// skip character
int cc = fCurrentEntity.ch[fCurrentEntity.position];
if (cc == c) {
fCurrentEntity.position++;
return true;
} else if (c == '\n' && cc == '\r' && fCurrentEntity.isExternal()) {
// handle newlines
if (fCurrentEntity.position == fCurrentEntity.count) {
fCurrentEntity.ch[0] = (char)cc;
load(1, false);
}
fCurrentEntity.position++;
if (fCurrentEntity.ch[fCurrentEntity.position] == '\n') {
fCurrentEntity.position++;
}
return true;
}
// character was not skipped
return false;
}
// in java/org/apache/jasper/xmlparser/XMLEncodingDetector.java
public boolean skipSpaces() throws IOException {
// load more characters, if needed
if (fCurrentEntity.position == fCurrentEntity.count) {
load(0, true);
}
// skip spaces
int c = fCurrentEntity.ch[fCurrentEntity.position];
if (XMLChar.isSpace(c)) {
boolean external = fCurrentEntity.isExternal();
do {
boolean entityChanged = false;
// handle newlines
if (c == '\n' || (external && c == '\r')) {
if (fCurrentEntity.position == fCurrentEntity.count - 1) {
fCurrentEntity.ch[0] = (char)c;
entityChanged = load(1, true);
if (!entityChanged)
// the load change the position to be 1,
// need to restore it when entity not changed
fCurrentEntity.position = 0;
}
if (c == '\r' && external) {
// REVISIT: Does this need to be updated to fix the
// #x0D ^#x0A newline normalization problem? -Ac
if (fCurrentEntity.ch[++fCurrentEntity.position] != '\n') {
fCurrentEntity.position--;
}
}
/*** NEWLINE NORMALIZATION ***
else {
if (fCurrentEntity.ch[fCurrentEntity.position + 1] == '\r'
&& external) {
fCurrentEntity.position++;
}
}
/***/
}
// load more characters, if needed
if (!entityChanged)
fCurrentEntity.position++;
if (fCurrentEntity.position == fCurrentEntity.count) {
load(0, true);
}
} while (XMLChar.isSpace(c = fCurrentEntity.ch[fCurrentEntity.position]));
return true;
}
// no spaces were found
return false;
}
// in java/org/apache/jasper/xmlparser/XMLEncodingDetector.java
public boolean skipString(String s) throws IOException {
// load more characters, if needed
if (fCurrentEntity.position == fCurrentEntity.count) {
load(0, true);
}
// skip string
final int length = s.length();
for (int i = 0; i < length; i++) {
char c = fCurrentEntity.ch[fCurrentEntity.position++];
if (c != s.charAt(i)) {
fCurrentEntity.position -= i + 1;
return false;
}
if (i < length - 1 && fCurrentEntity.position == fCurrentEntity.count) {
System.arraycopy(fCurrentEntity.ch, fCurrentEntity.count - i - 1, fCurrentEntity.ch, 0, i + 1);
// REVISIT: Can a string to be skipped cross an
// entity boundary? -Ac
if (load(i + 1, false)) {
fCurrentEntity.position -= i + 1;
return false;
}
}
}
return true;
}
// in java/org/apache/jasper/xmlparser/XMLEncodingDetector.java
final boolean load(int offset, boolean changeEntity)
throws IOException {
// read characters
int length = fCurrentEntity.mayReadChunks?
(fCurrentEntity.ch.length - offset):
(DEFAULT_XMLDECL_BUFFER_SIZE);
int count = fCurrentEntity.reader.read(fCurrentEntity.ch, offset,
length);
// reset count and position
boolean entityChanged = false;
if (count != -1) {
if (count != 0) {
fCurrentEntity.count = count + offset;
fCurrentEntity.position = offset;
}
}
// end of this entity
else {
fCurrentEntity.count = offset;
fCurrentEntity.position = offset;
entityChanged = true;
if (changeEntity) {
endEntity();
if (fCurrentEntity == null) {
throw new EOFException();
}
// handle the trailing edges
if (fCurrentEntity.position == fCurrentEntity.count) {
load(0, false);
}
}
}
return entityChanged;
}
// in java/org/apache/jasper/xmlparser/XMLEncodingDetector.java
Override
public int read() throws IOException {
int b = 0;
if (fOffset < fLength) {
return fData[fOffset++] & 0xff;
}
if (fOffset == fEndOffset) {
return -1;
}
if (fOffset == fData.length) {
byte[] newData = new byte[fOffset << 1];
System.arraycopy(fData, 0, newData, 0, fOffset);
fData = newData;
}
b = fInputStream.read();
if (b == -1) {
fEndOffset = fOffset;
return -1;
}
fData[fLength++] = (byte)b;
fOffset++;
return b & 0xff;
}
// in java/org/apache/jasper/xmlparser/XMLEncodingDetector.java
Override
public int read(byte[] b, int off, int len) throws IOException {
int bytesLeft = fLength - fOffset;
if (bytesLeft == 0) {
if (fOffset == fEndOffset) {
return -1;
}
// better get some more for the voracious reader...
if (fCurrentEntity.mayReadChunks) {
return fInputStream.read(b, off, len);
}
int returnedVal = read();
if (returnedVal == -1) {
fEndOffset = fOffset;
return -1;
}
b[off] = (byte)returnedVal;
return 1;
}
if (len < bytesLeft) {
if (len <= 0) {
return 0;
}
}
else {
len = bytesLeft;
}
if (b != null) {
System.arraycopy(fData, fOffset, b, off, len);
}
fOffset += len;
return len;
}
// in java/org/apache/jasper/xmlparser/XMLEncodingDetector.java
Override
public long skip(long n)
throws IOException
{
int bytesLeft;
if (n <= 0) {
return 0;
}
bytesLeft = fLength - fOffset;
if (bytesLeft == 0) {
if (fOffset == fEndOffset) {
return 0;
}
return fInputStream.skip(n);
}
if (n <= bytesLeft) {
fOffset += n;
return n;
}
fOffset += bytesLeft;
if (fOffset == fEndOffset) {
return bytesLeft;
}
n -= bytesLeft;
/*
* In a manner of speaking, when this class isn't permitting more
* than one byte at a time to be read, it is "blocking". The
* available() method should indicate how much can be read without
* blocking, so while we're in this mode, it should only indicate
* that bytes in its buffer are available; otherwise, the result of
* available() on the underlying InputStream is appropriate.
*/
return fInputStream.skip(n) + bytesLeft;
}
// in java/org/apache/jasper/xmlparser/XMLEncodingDetector.java
Override
public int available() throws IOException {
int bytesLeft = fLength - fOffset;
if (bytesLeft == 0) {
if (fOffset == fEndOffset) {
return -1;
}
return fCurrentEntity.mayReadChunks ? fInputStream.available()
: 0;
}
return bytesLeft;
}
// in java/org/apache/jasper/xmlparser/XMLEncodingDetector.java
Override
public void close() throws IOException {
if (fInputStream != null) {
fInputStream.close();
fInputStream = null;
}
}
// in java/org/apache/jasper/xmlparser/XMLEncodingDetector.java
private void scanXMLDecl() throws IOException, JasperException {
if (skipString("<?xml")) {
// NOTE: special case where document starts with a PI
// whose name starts with "xml" (e.g. "xmlfoo")
if (XMLChar.isName(peekChar())) {
fStringBuffer.clear();
fStringBuffer.append("xml");
while (XMLChar.isName(peekChar())) {
fStringBuffer.append((char)scanChar());
}
String target = fSymbolTable.addSymbol(fStringBuffer.ch,
fStringBuffer.offset,
fStringBuffer.length);
scanPIData(target, fString);
}
// standard XML declaration
else {
scanXMLDeclOrTextDecl(false);
}
}
}
// in java/org/apache/jasper/xmlparser/XMLEncodingDetector.java
private void scanXMLDeclOrTextDecl(boolean scanningTextDecl)
throws IOException, JasperException {
// scan decl
scanXMLDeclOrTextDecl(scanningTextDecl, fStrings);
// pseudo-attribute values
String encodingPseudoAttr = fStrings[1];
// set encoding on reader
if (encodingPseudoAttr != null) {
isEncodingSetInProlog = true;
encoding = encodingPseudoAttr;
}
}
// in java/org/apache/jasper/xmlparser/XMLEncodingDetector.java
private void scanXMLDeclOrTextDecl(boolean scanningTextDecl,
String[] pseudoAttributeValues)
throws IOException, JasperException {
// pseudo-attribute values
String version = null;
String encoding = null;
String standalone = null;
// scan pseudo-attributes
final int STATE_VERSION = 0;
final int STATE_ENCODING = 1;
final int STATE_STANDALONE = 2;
final int STATE_DONE = 3;
int state = STATE_VERSION;
boolean dataFoundForTarget = false;
boolean sawSpace = skipSpaces();
while (peekChar() != '?') {
dataFoundForTarget = true;
String name = scanPseudoAttribute(scanningTextDecl, fString);
switch (state) {
case STATE_VERSION: {
if (name == fVersionSymbol) {
if (!sawSpace) {
reportFatalError(scanningTextDecl
? "jsp.error.xml.spaceRequiredBeforeVersionInTextDecl"
: "jsp.error.xml.spaceRequiredBeforeVersionInXMLDecl",
null);
}
version = fString.toString();
state = STATE_ENCODING;
if (!version.equals("1.0")) {
// REVISIT: XML REC says we should throw an error
// in such cases.
// some may object the throwing of fatalError.
err.jspError("jsp.error.xml.versionNotSupported",
version);
}
} else if (name == fEncodingSymbol) {
if (!scanningTextDecl) {
err.jspError("jsp.error.xml.versionInfoRequired");
}
if (!sawSpace) {
reportFatalError(scanningTextDecl
? "jsp.error.xml.spaceRequiredBeforeEncodingInTextDecl"
: "jsp.error.xml.spaceRequiredBeforeEncodingInXMLDecl",
null);
}
encoding = fString.toString();
state = scanningTextDecl ? STATE_DONE : STATE_STANDALONE;
} else {
if (scanningTextDecl) {
err.jspError("jsp.error.xml.encodingDeclRequired");
}
else {
err.jspError("jsp.error.xml.versionInfoRequired");
}
}
break;
}
case STATE_ENCODING: {
if (name == fEncodingSymbol) {
if (!sawSpace) {
reportFatalError(scanningTextDecl
? "jsp.error.xml.spaceRequiredBeforeEncodingInTextDecl"
: "jsp.error.xml.spaceRequiredBeforeEncodingInXMLDecl",
null);
}
encoding = fString.toString();
state = scanningTextDecl ? STATE_DONE : STATE_STANDALONE;
// TODO: check encoding name; set encoding on
// entity scanner
} else if (!scanningTextDecl && name == fStandaloneSymbol) {
if (!sawSpace) {
err.jspError("jsp.error.xml.spaceRequiredBeforeStandalone");
}
standalone = fString.toString();
state = STATE_DONE;
if (!standalone.equals("yes") && !standalone.equals("no")) {
err.jspError("jsp.error.xml.sdDeclInvalid");
}
} else {
err.jspError("jsp.error.xml.encodingDeclRequired");
}
break;
}
case STATE_STANDALONE: {
if (name == fStandaloneSymbol) {
if (!sawSpace) {
err.jspError("jsp.error.xml.spaceRequiredBeforeStandalone");
}
standalone = fString.toString();
state = STATE_DONE;
if (!standalone.equals("yes") && !standalone.equals("no")) {
err.jspError("jsp.error.xml.sdDeclInvalid");
}
} else {
err.jspError("jsp.error.xml.encodingDeclRequired");
}
break;
}
default: {
err.jspError("jsp.error.xml.noMorePseudoAttributes");
}
}
sawSpace = skipSpaces();
}
// REVISIT: should we remove this error reporting?
if (scanningTextDecl && state != STATE_DONE) {
err.jspError("jsp.error.xml.morePseudoAttributes");
}
// If there is no data in the xml or text decl then we fail to report
// error for version or encoding info above.
if (scanningTextDecl) {
if (!dataFoundForTarget && encoding == null) {
err.jspError("jsp.error.xml.encodingDeclRequired");
}
} else {
if (!dataFoundForTarget && version == null) {
err.jspError("jsp.error.xml.versionInfoRequired");
}
}
// end
if (!skipChar('?')) {
err.jspError("jsp.error.xml.xmlDeclUnterminated");
}
if (!skipChar('>')) {
err.jspError("jsp.error.xml.xmlDeclUnterminated");
}
// fill in return array
pseudoAttributeValues[0] = version;
pseudoAttributeValues[1] = encoding;
pseudoAttributeValues[2] = standalone;
}
// in java/org/apache/jasper/xmlparser/XMLEncodingDetector.java
public String scanPseudoAttribute(boolean scanningTextDecl,
XMLString value)
throws IOException, JasperException {
String name = scanName();
if (name == null) {
err.jspError("jsp.error.xml.pseudoAttrNameExpected");
}
skipSpaces();
if (!skipChar('=')) {
reportFatalError(scanningTextDecl ?
"jsp.error.xml.eqRequiredInTextDecl"
: "jsp.error.xml.eqRequiredInXMLDecl",
name);
}
skipSpaces();
int quote = peekChar();
if (quote != '\'' && quote != '"') {
reportFatalError(scanningTextDecl ?
"jsp.error.xml.quoteRequiredInTextDecl"
: "jsp.error.xml.quoteRequiredInXMLDecl" ,
name);
}
scanChar();
int c = scanLiteral(quote, value);
if (c != quote) {
fStringBuffer2.clear();
do {
fStringBuffer2.append(value);
if (c != -1) {
if (c == '&' || c == '%' || c == '<' || c == ']') {
fStringBuffer2.append((char)scanChar());
}
else if (XMLChar.isHighSurrogate(c)) {
scanSurrogates(fStringBuffer2);
}
else if (XMLChar.isInvalid(c)) {
String key = scanningTextDecl
? "jsp.error.xml.invalidCharInTextDecl"
: "jsp.error.xml.invalidCharInXMLDecl";
reportFatalError(key, Integer.toString(c, 16));
scanChar();
}
}
c = scanLiteral(quote, value);
} while (c != quote);
fStringBuffer2.append(value);
value.setValues(fStringBuffer2);
}
if (!skipChar(quote)) {
reportFatalError(scanningTextDecl ?
"jsp.error.xml.closeQuoteMissingInTextDecl"
: "jsp.error.xml.closeQuoteMissingInXMLDecl",
name);
}
// return
return name;
}
// in java/org/apache/jasper/xmlparser/XMLEncodingDetector.java
private void scanPIData(String target, XMLString data)
throws IOException, JasperException {
// check target
if (target.length() == 3) {
char c0 = Character.toLowerCase(target.charAt(0));
char c1 = Character.toLowerCase(target.charAt(1));
char c2 = Character.toLowerCase(target.charAt(2));
if (c0 == 'x' && c1 == 'm' && c2 == 'l') {
err.jspError("jsp.error.xml.reservedPITarget");
}
}
// spaces
if (!skipSpaces()) {
if (skipString("?>")) {
// we found the end, there is no data
data.clear();
return;
}
else {
// if there is data there should be some space
err.jspError("jsp.error.xml.spaceRequiredInPI");
}
}
fStringBuffer.clear();
// data
if (scanData("?>", fStringBuffer)) {
do {
int c = peekChar();
if (c != -1) {
if (XMLChar.isHighSurrogate(c)) {
scanSurrogates(fStringBuffer);
} else if (XMLChar.isInvalid(c)) {
err.jspError("jsp.error.xml.invalidCharInPI",
Integer.toHexString(c));
scanChar();
}
}
} while (scanData("?>", fStringBuffer));
}
data.setValues(fStringBuffer);
}
// in java/org/apache/jasper/xmlparser/XMLEncodingDetector.java
private boolean scanSurrogates(XMLStringBuffer buf)
throws IOException, JasperException {
int high = scanChar();
int low = peekChar();
if (!XMLChar.isLowSurrogate(low)) {
err.jspError("jsp.error.xml.invalidCharInContent",
Integer.toString(high, 16));
return false;
}
scanChar();
// convert surrogates to supplemental character
int c = XMLChar.supplemental((char)high, (char)low);
// supplemental character must be a valid XML character
if (!XMLChar.isValid(c)) {
err.jspError("jsp.error.xml.invalidCharInContent",
Integer.toString(c, 16));
return false;
}
// fill in the buffer
buf.append((char)high);
buf.append((char)low);
return true;
}
// in java/org/apache/jasper/xmlparser/UTF8Reader.java
Override
public int read() throws IOException {
// decode character
int c = fSurrogate;
if (fSurrogate == -1) {
// NOTE: We use the index into the buffer if there are remaining
// bytes from the last block read. -Ac
int index = 0;
// get first byte
int b0 = index == fOffset
? fInputStream.read() : fBuffer[index++] & 0x00FF;
if (b0 == -1) {
return -1;
}
// UTF-8: [0xxx xxxx]
// Unicode: [0000 0000] [0xxx xxxx]
if (b0 < 0x80) {
c = (char)b0;
}
// UTF-8: [110y yyyy] [10xx xxxx]
// Unicode: [0000 0yyy] [yyxx xxxx]
else if ((b0 & 0xE0) == 0xC0) {
int b1 = index == fOffset
? fInputStream.read() : fBuffer[index++] & 0x00FF;
if (b1 == -1) {
expectedByte(2, 2);
}
if ((b1 & 0xC0) != 0x80) {
invalidByte(2, 2);
}
c = ((b0 << 6) & 0x07C0) | (b1 & 0x003F);
}
// UTF-8: [1110 zzzz] [10yy yyyy] [10xx xxxx]
// Unicode: [zzzz yyyy] [yyxx xxxx]
else if ((b0 & 0xF0) == 0xE0) {
int b1 = index == fOffset
? fInputStream.read() : fBuffer[index++] & 0x00FF;
if (b1 == -1) {
expectedByte(2, 3);
}
if ((b1 & 0xC0) != 0x80) {
invalidByte(2, 3);
}
int b2 = index == fOffset
? fInputStream.read() : fBuffer[index++] & 0x00FF;
if (b2 == -1) {
expectedByte(3, 3);
}
if ((b2 & 0xC0) != 0x80) {
invalidByte(3, 3);
}
c = ((b0 << 12) & 0xF000) | ((b1 << 6) & 0x0FC0) |
(b2 & 0x003F);
}
// UTF-8: [1111 0uuu] [10uu zzzz] [10yy yyyy] [10xx xxxx]*
// Unicode: [1101 10ww] [wwzz zzyy] (high surrogate)
// [1101 11yy] [yyxx xxxx] (low surrogate)
// * uuuuu = wwww + 1
else if ((b0 & 0xF8) == 0xF0) {
int b1 = index == fOffset
? fInputStream.read() : fBuffer[index++] & 0x00FF;
if (b1 == -1) {
expectedByte(2, 4);
}
if ((b1 & 0xC0) != 0x80) {
invalidByte(2, 3);
}
int b2 = index == fOffset
? fInputStream.read() : fBuffer[index++] & 0x00FF;
if (b2 == -1) {
expectedByte(3, 4);
}
if ((b2 & 0xC0) != 0x80) {
invalidByte(3, 3);
}
int b3 = index == fOffset
? fInputStream.read() : fBuffer[index++] & 0x00FF;
if (b3 == -1) {
expectedByte(4, 4);
}
if ((b3 & 0xC0) != 0x80) {
invalidByte(4, 4);
}
int uuuuu = ((b0 << 2) & 0x001C) | ((b1 >> 4) & 0x0003);
if (uuuuu > 0x10) {
invalidSurrogate(uuuuu);
}
int wwww = uuuuu - 1;
int hs = 0xD800 |
((wwww << 6) & 0x03C0) | ((b1 << 2) & 0x003C) |
((b2 >> 4) & 0x0003);
int ls = 0xDC00 | ((b2 << 6) & 0x03C0) | (b3 & 0x003F);
c = hs;
fSurrogate = ls;
}
// error
else {
invalidByte(1, 1);
}
}
// use surrogate
else {
fSurrogate = -1;
}
// return character
if (DEBUG_READ) {
if (log.isDebugEnabled())
log.debug("read(): 0x"+Integer.toHexString(c));
}
return c;
}
// in java/org/apache/jasper/xmlparser/UTF8Reader.java
Override
public int read(char ch[], int offset, int length) throws IOException {
// handle surrogate
int out = offset;
if (fSurrogate != -1) {
ch[offset + 1] = (char)fSurrogate;
fSurrogate = -1;
length--;
out++;
}
// read bytes
int count = 0;
if (fOffset == 0) {
// adjust length to read
if (length > fBuffer.length) {
length = fBuffer.length;
}
// perform read operation
count = fInputStream.read(fBuffer, 0, length);
if (count == -1) {
return -1;
}
count += out - offset;
}
// skip read; last character was in error
// NOTE: Having an offset value other than zero means that there was
// an error in the last character read. In this case, we have
// skipped the read so we don't consume any bytes past the
// error. By signaling the error on the next block read we
// allow the method to return the most valid characters that
// it can on the previous block read. -Ac
else {
count = fOffset;
fOffset = 0;
}
// convert bytes to characters
final int total = count;
for (int in = 0; in < total; in++) {
int b0 = fBuffer[in] & 0x00FF;
// UTF-8: [0xxx xxxx]
// Unicode: [0000 0000] [0xxx xxxx]
if (b0 < 0x80) {
ch[out++] = (char)b0;
continue;
}
// UTF-8: [110y yyyy] [10xx xxxx]
// Unicode: [0000 0yyy] [yyxx xxxx]
if ((b0 & 0xE0) == 0xC0) {
int b1 = -1;
if (++in < total) {
b1 = fBuffer[in] & 0x00FF;
}
else {
b1 = fInputStream.read();
if (b1 == -1) {
if (out > offset) {
fBuffer[0] = (byte)b0;
fOffset = 1;
return out - offset;
}
expectedByte(2, 2);
}
count++;
}
if ((b1 & 0xC0) != 0x80) {
if (out > offset) {
fBuffer[0] = (byte)b0;
fBuffer[1] = (byte)b1;
fOffset = 2;
return out - offset;
}
invalidByte(2, 2);
}
int c = ((b0 << 6) & 0x07C0) | (b1 & 0x003F);
ch[out++] = (char)c;
count -= 1;
continue;
}
// UTF-8: [1110 zzzz] [10yy yyyy] [10xx xxxx]
// Unicode: [zzzz yyyy] [yyxx xxxx]
if ((b0 & 0xF0) == 0xE0) {
int b1 = -1;
if (++in < total) {
b1 = fBuffer[in] & 0x00FF;
}
else {
b1 = fInputStream.read();
if (b1 == -1) {
if (out > offset) {
fBuffer[0] = (byte)b0;
fOffset = 1;
return out - offset;
}
expectedByte(2, 3);
}
count++;
}
if ((b1 & 0xC0) != 0x80) {
if (out > offset) {
fBuffer[0] = (byte)b0;
fBuffer[1] = (byte)b1;
fOffset = 2;
return out - offset;
}
invalidByte(2, 3);
}
int b2 = -1;
if (++in < total) {
b2 = fBuffer[in] & 0x00FF;
}
else {
b2 = fInputStream.read();
if (b2 == -1) {
if (out > offset) {
fBuffer[0] = (byte)b0;
fBuffer[1] = (byte)b1;
fOffset = 2;
return out - offset;
}
expectedByte(3, 3);
}
count++;
}
if ((b2 & 0xC0) != 0x80) {
if (out > offset) {
fBuffer[0] = (byte)b0;
fBuffer[1] = (byte)b1;
fBuffer[2] = (byte)b2;
fOffset = 3;
return out - offset;
}
invalidByte(3, 3);
}
int c = ((b0 << 12) & 0xF000) | ((b1 << 6) & 0x0FC0) |
(b2 & 0x003F);
ch[out++] = (char)c;
count -= 2;
continue;
}
// UTF-8: [1111 0uuu] [10uu zzzz] [10yy yyyy] [10xx xxxx]*
// Unicode: [1101 10ww] [wwzz zzyy] (high surrogate)
// [1101 11yy] [yyxx xxxx] (low surrogate)
// * uuuuu = wwww + 1
if ((b0 & 0xF8) == 0xF0) {
int b1 = -1;
if (++in < total) {
b1 = fBuffer[in] & 0x00FF;
}
else {
b1 = fInputStream.read();
if (b1 == -1) {
if (out > offset) {
fBuffer[0] = (byte)b0;
fOffset = 1;
return out - offset;
}
expectedByte(2, 4);
}
count++;
}
if ((b1 & 0xC0) != 0x80) {
if (out > offset) {
fBuffer[0] = (byte)b0;
fBuffer[1] = (byte)b1;
fOffset = 2;
return out - offset;
}
invalidByte(2, 4);
}
int b2 = -1;
if (++in < total) {
b2 = fBuffer[in] & 0x00FF;
}
else {
b2 = fInputStream.read();
if (b2 == -1) {
if (out > offset) {
fBuffer[0] = (byte)b0;
fBuffer[1] = (byte)b1;
fOffset = 2;
return out - offset;
}
expectedByte(3, 4);
}
count++;
}
if ((b2 & 0xC0) != 0x80) {
if (out > offset) {
fBuffer[0] = (byte)b0;
fBuffer[1] = (byte)b1;
fBuffer[2] = (byte)b2;
fOffset = 3;
return out - offset;
}
invalidByte(3, 4);
}
int b3 = -1;
if (++in < total) {
b3 = fBuffer[in] & 0x00FF;
}
else {
b3 = fInputStream.read();
if (b3 == -1) {
if (out > offset) {
fBuffer[0] = (byte)b0;
fBuffer[1] = (byte)b1;
fBuffer[2] = (byte)b2;
fOffset = 3;
return out - offset;
}
expectedByte(4, 4);
}
count++;
}
if ((b3 & 0xC0) != 0x80) {
if (out > offset) {
fBuffer[0] = (byte)b0;
fBuffer[1] = (byte)b1;
fBuffer[2] = (byte)b2;
fBuffer[3] = (byte)b3;
fOffset = 4;
return out - offset;
}
invalidByte(4, 4);
}
// decode bytes into surrogate characters
int uuuuu = ((b0 << 2) & 0x001C) | ((b1 >> 4) & 0x0003);
if (uuuuu > 0x10) {
invalidSurrogate(uuuuu);
}
int wwww = uuuuu - 1;
int zzzz = b1 & 0x000F;
int yyyyyy = b2 & 0x003F;
int xxxxxx = b3 & 0x003F;
int hs = 0xD800 | ((wwww << 6) & 0x03C0) | (zzzz << 2) | (yyyyyy >> 4);
int ls = 0xDC00 | ((yyyyyy << 6) & 0x03C0) | xxxxxx;
// set characters
ch[out++] = (char)hs;
ch[out++] = (char)ls;
count -= 2;
continue;
}
// error
if (out > offset) {
fBuffer[0] = (byte)b0;
fOffset = 1;
return out - offset;
}
invalidByte(1, 1);
}
// return number of characters converted
if (DEBUG_READ) {
if (log.isDebugEnabled())
log.debug("read(char[],"+offset+','+length+"): count="+count);
}
return count;
}
// in java/org/apache/jasper/xmlparser/UTF8Reader.java
Override
public long skip(long n) throws IOException {
long remaining = n;
final char[] ch = new char[fBuffer.length];
do {
int length = ch.length < remaining ? ch.length : (int)remaining;
int count = read(ch, 0, length);
if (count > 0) {
remaining -= count;
}
else {
break;
}
} while (remaining > 0);
long skipped = n - remaining;
return skipped;
}
// in java/org/apache/jasper/xmlparser/UTF8Reader.java
Override
public boolean ready() throws IOException {
return false;
}
// in java/org/apache/jasper/xmlparser/UTF8Reader.java
Override
public void mark(int readAheadLimit) throws IOException {
throw new IOException(
Localizer.getMessage("jsp.error.xml.operationNotSupported",
"mark()", "UTF-8"));
}
// in java/org/apache/jasper/xmlparser/UTF8Reader.java
Override
public void reset() throws IOException {
fOffset = 0;
fSurrogate = -1;
}
// in java/org/apache/jasper/xmlparser/UTF8Reader.java
Override
public void close() throws IOException {
fInputStream.close();
}
// in java/org/apache/jasper/xmlparser/UCSReader.java
Override
public int read() throws IOException {
int b0 = fInputStream.read() & 0xff;
if (b0 == 0xff)
return -1;
int b1 = fInputStream.read() & 0xff;
if (b1 == 0xff)
return -1;
if(fEncoding >=4) {
int b2 = fInputStream.read() & 0xff;
if (b2 == 0xff)
return -1;
int b3 = fInputStream.read() & 0xff;
if (b3 == 0xff)
return -1;
if (log.isDebugEnabled())
log.debug("b0 is " + (b0 & 0xff) + " b1 " + (b1 & 0xff) + " b2 " + (b2 & 0xff) + " b3 " + (b3 & 0xff));
if (fEncoding == UCS4BE)
return (b0<<24)+(b1<<16)+(b2<<8)+b3;
else
return (b3<<24)+(b2<<16)+(b1<<8)+b0;
} else { // UCS-2
if (fEncoding == UCS2BE)
return (b0<<8)+b1;
else
return (b1<<8)+b0;
}
}
// in java/org/apache/jasper/xmlparser/UCSReader.java
Override
public int read(char ch[], int offset, int length) throws IOException {
int byteLength = length << ((fEncoding >= 4)?2:1);
if (byteLength > fBuffer.length) {
byteLength = fBuffer.length;
}
int count = fInputStream.read(fBuffer, 0, byteLength);
if(count == -1) return -1;
// try and make count be a multiple of the number of bytes we're looking for
if(fEncoding >= 4) { // BigEndian
// this looks ugly, but it avoids an if at any rate...
int numToRead = (4 - (count & 3) & 3);
for(int i=0; i<numToRead; i++) {
int charRead = fInputStream.read();
if(charRead == -1) { // end of input; something likely went wrong!A Pad buffer with nulls.
for (int j = i;j<numToRead; j++)
fBuffer[count+j] = 0;
break;
} else {
fBuffer[count+i] = (byte)charRead;
}
}
count += numToRead;
} else {
int numToRead = count & 1;
if(numToRead != 0) {
count++;
int charRead = fInputStream.read();
if(charRead == -1) { // end of input; something likely went wrong!A Pad buffer with nulls.
fBuffer[count] = 0;
} else {
fBuffer[count] = (byte)charRead;
}
}
}
// now count is a multiple of the right number of bytes
int numChars = count >> ((fEncoding >= 4)?2:1);
int curPos = 0;
for (int i = 0; i < numChars; i++) {
int b0 = fBuffer[curPos++] & 0xff;
int b1 = fBuffer[curPos++] & 0xff;
if(fEncoding >=4) {
int b2 = fBuffer[curPos++] & 0xff;
int b3 = fBuffer[curPos++] & 0xff;
if (fEncoding == UCS4BE)
ch[offset+i] = (char)((b0<<24)+(b1<<16)+(b2<<8)+b3);
else
ch[offset+i] = (char)((b3<<24)+(b2<<16)+(b1<<8)+b0);
} else { // UCS-2
if (fEncoding == UCS2BE)
ch[offset+i] = (char)((b0<<8)+b1);
else
ch[offset+i] = (char)((b1<<8)+b0);
}
}
return numChars;
}
// in java/org/apache/jasper/xmlparser/UCSReader.java
Override
public long skip(long n) throws IOException {
// charWidth will represent the number of bits to move
// n leftward to get num of bytes to skip, and then move the result rightward
// to get num of chars effectively skipped.
// The trick with &'ing, as with elsewhere in this dcode, is
// intended to avoid an expensive use of / that might not be optimized
// away.
int charWidth = (fEncoding >=4)?2:1;
long bytesSkipped = fInputStream.skip(n<<charWidth);
if((bytesSkipped & (charWidth | 1)) == 0) return bytesSkipped >> charWidth;
return (bytesSkipped >> charWidth) + 1;
}
// in java/org/apache/jasper/xmlparser/UCSReader.java
Override
public boolean ready() throws IOException {
return false;
}
// in java/org/apache/jasper/xmlparser/UCSReader.java
Override
public void mark(int readAheadLimit) throws IOException {
fInputStream.mark(readAheadLimit);
}
// in java/org/apache/jasper/xmlparser/UCSReader.java
Override
public void reset() throws IOException {
fInputStream.reset();
}
// in java/org/apache/jasper/xmlparser/UCSReader.java
Override
public void close() throws IOException {
fInputStream.close();
}
// in java/org/apache/jasper/xmlparser/ASCIIReader.java
Override
public int read() throws IOException {
int b0 = fInputStream.read();
if (b0 > 0x80) {
throw new IOException(Localizer.getMessage("jsp.error.xml.invalidASCII",
Integer.toString(b0)));
}
return b0;
}
// in java/org/apache/jasper/xmlparser/ASCIIReader.java
Override
public int read(char ch[], int offset, int length) throws IOException {
if (length > fBuffer.length) {
length = fBuffer.length;
}
int count = fInputStream.read(fBuffer, 0, length);
for (int i = 0; i < count; i++) {
int b0 = (0xff & fBuffer[i]); // Convert to unsigned
if (b0 > 0x80) {
throw new IOException(Localizer.getMessage("jsp.error.xml.invalidASCII",
Integer.toString(b0)));
}
ch[offset + i] = (char)b0;
}
return count;
}
// in java/org/apache/jasper/xmlparser/ASCIIReader.java
Override
public long skip(long n) throws IOException {
return fInputStream.skip(n);
}
// in java/org/apache/jasper/xmlparser/ASCIIReader.java
Override
public boolean ready() throws IOException {
return false;
}
// in java/org/apache/jasper/xmlparser/ASCIIReader.java
Override
public void mark(int readAheadLimit) throws IOException {
fInputStream.mark(readAheadLimit);
}
// in java/org/apache/jasper/xmlparser/ASCIIReader.java
Override
public void reset() throws IOException {
fInputStream.reset();
}
// in java/org/apache/jasper/xmlparser/ASCIIReader.java
Override
public void close() throws IOException {
fInputStream.close();
}
// in java/org/apache/jasper/JspC.java
public void generateWebMapping( String file, JspCompilationContext clctxt )
throws IOException
{
if (log.isDebugEnabled()) {
log.debug("Generating web mapping for file " + file
+ " using compilation context " + clctxt);
}
String className = clctxt.getServletClassName();
String packageName = clctxt.getServletPackageName();
String thisServletName;
if ("".equals(packageName)) {
thisServletName = className;
} else {
thisServletName = packageName + '.' + className;
}
if (servletout != null) {
servletout.write("\n <servlet>\n <servlet-name>");
servletout.write(thisServletName);
servletout.write("</servlet-name>\n <servlet-class>");
servletout.write(thisServletName);
servletout.write("</servlet-class>\n </servlet>\n");
}
if (mappingout != null) {
mappingout.write("\n <servlet-mapping>\n <servlet-name>");
mappingout.write(thisServletName);
mappingout.write("</servlet-name>\n <url-pattern>");
mappingout.write(file.replace('\\', '/'));
mappingout.write("</url-pattern>\n </servlet-mapping>\n");
}
}
// in java/org/apache/jasper/JspC.java
protected void mergeIntoWebXml() throws IOException {
File webappBase = new File(uriRoot);
File webXml = new File(webappBase, "WEB-INF/web.xml");
File webXml2 = new File(webappBase, "WEB-INF/web2.xml");
String insertStartMarker =
Localizer.getMessage("jspc.webinc.insertStart");
String insertEndMarker =
Localizer.getMessage("jspc.webinc.insertEnd");
BufferedReader reader = new BufferedReader(openWebxmlReader(webXml));
BufferedReader fragmentReader = new BufferedReader(
openWebxmlReader(new File(webxmlFile)));
PrintWriter writer = new PrintWriter(openWebxmlWriter(webXml2));
// Insert the <servlet> and <servlet-mapping> declarations
boolean inserted = false;
int current = reader.read();
while (current > -1) {
if (current == '<') {
String element = getElement(reader);
if (!inserted && insertBefore.contains(element)) {
// Insert generated content here
writer.println(insertStartMarker);
while (true) {
String line = fragmentReader.readLine();
if (line == null) {
writer.println();
break;
}
writer.println(line);
}
writer.println(insertEndMarker);
writer.println();
writer.write(element);
inserted = true;
} else if (element.equals(insertStartMarker)) {
// Skip the previous auto-generated content
while (true) {
current = reader.read();
if (current < 0) {
throw new EOFException();
}
if (current == '<') {
element = getElement(reader);
if (element.equals(insertEndMarker)) {
break;
}
}
}
current = reader.read();
while (current == '\n' || current == '\r') {
current = reader.read();
}
continue;
} else {
writer.write(element);
}
} else {
writer.write(current);
}
current = reader.read();
}
writer.close();
reader.close();
fragmentReader.close();
FileInputStream fis = new FileInputStream(webXml2);
FileOutputStream fos = new FileOutputStream(webXml);
byte buf[] = new byte[512];
while (true) {
int n = fis.read(buf);
if (n < 0) {
break;
}
fos.write(buf, 0, n);
}
fis.close();
fos.close();
if(!webXml2.delete() && log.isDebugEnabled())
log.debug(Localizer.getMessage("jspc.delete.fail",
webXml2.toString()));
if (!(new File(webxmlFile)).delete() && log.isDebugEnabled())
log.debug(Localizer.getMessage("jspc.delete.fail", webxmlFile));
}
// in java/org/apache/jasper/JspC.java
private String getElement(Reader reader) throws IOException {
StringBuilder result = new StringBuilder();
result.append('<');
boolean done = false;
while (!done) {
int current = reader.read();
while (current != '>') {
if (current < 0) {
throw new EOFException();
}
result.append((char) current);
current = reader.read();
}
result.append((char) current);
int len = result.length();
if (len > 4 && result.substring(0, 4).equals("<!--")) {
// This is a comment - make sure we are at the end
if (len >= 7 && result.substring(len - 3, len).equals("-->")) {
done = true;
}
} else {
done = true;
}
}
return result.toString();
}
// in java/org/apache/jasper/JspC.java
protected void initClassLoader(JspCompilationContext clctxt)
throws IOException {
classPath = getClassPath();
ClassLoader jspcLoader = getClass().getClassLoader();
if (jspcLoader instanceof AntClassLoader) {
classPath += File.pathSeparator
+ ((AntClassLoader) jspcLoader).getClasspath();
}
// Turn the classPath into URLs
ArrayList<URL> urls = new ArrayList<URL>();
StringTokenizer tokenizer = new StringTokenizer(classPath,
File.pathSeparator);
while (tokenizer.hasMoreTokens()) {
String path = tokenizer.nextToken();
try {
File libFile = new File(path);
urls.add(libFile.toURI().toURL());
} catch (IOException ioe) {
// Failing a toCanonicalPath on a file that
// exists() should be a JVM regression test,
// therefore we have permission to freak uot
throw new RuntimeException(ioe.toString());
}
}
File webappBase = new File(uriRoot);
if (webappBase.exists()) {
File classes = new File(webappBase, "/WEB-INF/classes");
try {
if (classes.exists()) {
classPath = classPath + File.pathSeparator
+ classes.getCanonicalPath();
urls.add(classes.getCanonicalFile().toURI().toURL());
}
} catch (IOException ioe) {
// failing a toCanonicalPath on a file that
// exists() should be a JVM regression test,
// therefore we have permission to freak out
throw new RuntimeException(ioe.toString());
}
File lib = new File(webappBase, "/WEB-INF/lib");
if (lib.exists() && lib.isDirectory()) {
String[] libs = lib.list();
for (int i = 0; i < libs.length; i++) {
if( libs[i].length() <5 ) continue;
String ext=libs[i].substring( libs[i].length() - 4 );
if (! ".jar".equalsIgnoreCase(ext)) {
if (".tld".equalsIgnoreCase(ext)) {
log.warn("TLD files should not be placed in "
+ "/WEB-INF/lib");
}
continue;
}
try {
File libFile = new File(lib, libs[i]);
classPath = classPath + File.pathSeparator
+ libFile.getAbsolutePath();
urls.add(libFile.getAbsoluteFile().toURI().toURL());
} catch (IOException ioe) {
// failing a toCanonicalPath on a file that
// exists() should be a JVM regression test,
// therefore we have permission to freak out
throw new RuntimeException(ioe.toString());
}
}
}
}
// What is this ??
urls.add(new File(
clctxt.getRealPath("/")).getCanonicalFile().toURI().toURL());
URL urlsA[]=new URL[urls.size()];
urls.toArray(urlsA);
loader = new URLClassLoader(urlsA, this.getClass().getClassLoader());
}
// in java/org/apache/jasper/JspC.java
private Reader openWebxmlReader(File file) throws IOException {
FileInputStream fis = new FileInputStream(file);
try {
return webxmlEncoding != null ? new InputStreamReader(fis,
webxmlEncoding) : new InputStreamReader(fis);
} catch (IOException ex) {
fis.close();
throw ex;
}
}
// in java/org/apache/jasper/JspC.java
private Writer openWebxmlWriter(File file) throws IOException {
FileOutputStream fos = new FileOutputStream(file);
try {
return webxmlEncoding != null ? new OutputStreamWriter(fos,
webxmlEncoding) : new OutputStreamWriter(fos);
} catch (IOException ex) {
fos.close();
throw ex;
}
}
// in java/org/apache/naming/resources/WARDirContext.java
Override
public InputStream streamContent()
throws IOException {
try {
if (binaryContent == null) {
InputStream is = base.getInputStream(entry);
inputStream = is;
return is;
}
} catch (ZipException e) {
throw new IOException(e.getMessage(), e);
}
return super.streamContent();
}
// in java/org/apache/naming/resources/DirContextURLConnection.java
Override
public void connect()
throws IOException {
if (!connected) {
try {
date = System.currentTimeMillis();
String path = getURL().getFile();
if (context instanceof ProxyDirContext) {
ProxyDirContext proxyDirContext =
(ProxyDirContext) context;
String hostName = proxyDirContext.getHostName();
String contextPath = proxyDirContext.getContextPath();
if (hostName != null) {
if (!path.startsWith("/" + hostName + "/"))
return;
path = path.substring(hostName.length()+ 1);
}
if (contextPath != null) {
if (!path.startsWith(contextPath + "/")) {
return;
}
path = path.substring(contextPath.length());
}
}
path = URLDecoder.decode(path, "UTF-8");
object = context.lookup(path);
attributes = context.getAttributes(path);
if (object instanceof Resource)
resource = (Resource) object;
if (object instanceof DirContext)
collection = (DirContext) object;
} catch (NamingException e) {
// Object not found
}
connected = true;
}
}
// in java/org/apache/naming/resources/DirContextURLConnection.java
Override
public Object getContent()
throws IOException {
if (!connected)
connect();
if (resource != null)
return getInputStream();
if (collection != null)
return collection;
if (object != null)
return object;
throw new FileNotFoundException(
getURL() == null ? "null" : getURL().toString());
}
// in java/org/apache/naming/resources/DirContextURLConnection.java
Override
public InputStream getInputStream()
throws IOException {
if (!connected)
connect();
if (resource == null) {
throw new FileNotFoundException(
getURL() == null ? "null" : getURL().toString());
}
// Reopen resource
try {
resource = (Resource) context.lookup(
URLDecoder.decode(getURL().getFile(), "UTF-8"));
} catch (NamingException e) {
// Ignore
}
return (resource.streamContent());
}
// in java/org/apache/naming/resources/DirContextURLConnection.java
public Enumeration<String> list()
throws IOException {
if (!connected) {
connect();
}
if ((resource == null) && (collection == null)) {
throw new FileNotFoundException(
getURL() == null ? "null" : getURL().toString());
}
Vector<String> result = new Vector<String>();
if (collection != null) {
try {
String file = getURL().getFile();
// This will be of the form /<hostname>/<contextpath>/file name
// if <contextpath> is not empty otherwise this will be of the
// form /<hostname>/file name
// Strip off the hostname and the contextpath (note that context
// path may contain '/'
int start;
if (context instanceof ProxyDirContext) {
String cp = ((ProxyDirContext)context).getContextPath();
String h = ((ProxyDirContext)context).getHostName();
if ("".equals(cp)) {
start = h.length() + 2;
} else {
start = h.length() + cp.length() + 2;
}
} else {
start = file.indexOf('/', file.indexOf('/', 1) + 1);
}
NamingEnumeration<NameClassPair> enumeration =
context.list(file.substring(start));
while (enumeration.hasMoreElements()) {
NameClassPair ncp = enumeration.nextElement();
result.addElement(
URLEncoder.encode(ncp.getName(), "UTF-8"));
}
} catch (NamingException e) {
// Unexpected exception
throw new FileNotFoundException(
getURL() == null ? "null" : getURL().toString());
}
}
return result.elements();
}
// in java/org/apache/naming/resources/FileDirContext.java
Override
public InputStream streamContent()
throws IOException {
if (binaryContent == null) {
FileInputStream fis = new FileInputStream(file);
inputStream = fis;
return fis;
}
return super.streamContent();
}
// in java/org/apache/naming/resources/Resource.java
public InputStream streamContent() throws IOException {
if (binaryContent != null) {
return new ByteArrayInputStream(binaryContent);
}
return inputStream;
}
// in java/org/apache/naming/resources/DirContextURLStreamHandler.java
Override
protected URLConnection openConnection(URL u)
throws IOException {
DirContext currentContext = this.context;
if (currentContext == null)
currentContext = get();
return new DirContextURLConnection(currentContext, u);
}
// in java/org/apache/juli/ClassLoaderLogManager.java
Override
public void readConfiguration()
throws IOException, SecurityException {
checkAccess();
readConfiguration(Thread.currentThread().getContextClassLoader());
}
// in java/org/apache/juli/ClassLoaderLogManager.java
Override
public void readConfiguration(InputStream is)
throws IOException, SecurityException {
checkAccess();
reset();
readConfiguration(is, Thread.currentThread().getContextClassLoader());
}
// in java/org/apache/juli/ClassLoaderLogManager.java
protected void readConfiguration(ClassLoader classLoader)
throws IOException {
InputStream is = null;
// Special case for URL classloaders which are used in containers:
// only look in the local repositories to avoid redefining loggers 20 times
try {
if ((classLoader instanceof URLClassLoader)
&& (((URLClassLoader) classLoader).findResource("logging.properties") != null)) {
is = classLoader.getResourceAsStream("logging.properties");
}
} catch (AccessControlException ace) {
// No permission to configure logging in context
// Log and carry on
ClassLoaderLogInfo info = classLoaderLoggers.get(ClassLoader.getSystemClassLoader());
if (info != null) {
Logger log = info.loggers.get("");
if (log != null) {
Permission perm = ace.getPermission();
if (perm instanceof FilePermission && perm.getActions().equals("read")) {
log.warning("Reading " + perm.getName() + " is not permitted. See \"per context logging\" in the default catalina.policy file.");
}
else {
log.warning("Reading logging.properties is not permitted in some context. See \"per context logging\" in the default catalina.policy file.");
log.warning("Original error was: " + ace.getMessage());
}
}
}
}
if ((is == null) && (classLoader == ClassLoader.getSystemClassLoader())) {
String configFileStr = System.getProperty("java.util.logging.config.file");
if (configFileStr != null) {
try {
is = new FileInputStream(replace(configFileStr));
} catch (IOException e) {
// Ignore
}
}
// Try the default JVM configuration
if (is == null) {
File defaultFile = new File(new File(System.getProperty("java.home"), "lib"),
"logging.properties");
try {
is = new FileInputStream(defaultFile);
} catch (IOException e) {
// Critical problem, do something ...
}
}
}
Logger localRootLogger = new RootLogger();
if (is == null) {
// Retrieve the root logger of the parent classloader instead
ClassLoader current = classLoader.getParent();
ClassLoaderLogInfo info = null;
while (current != null && info == null) {
info = getClassLoaderInfo(current);
current = current.getParent();
}
if (info != null) {
localRootLogger.setParent(info.rootNode.logger);
}
}
ClassLoaderLogInfo info =
new ClassLoaderLogInfo(new LogNode(null, localRootLogger));
classLoaderLoggers.put(classLoader, info);
if (is != null) {
readConfiguration(is, classLoader);
}
addLogger(localRootLogger);
}
// in java/org/apache/juli/ClassLoaderLogManager.java
protected void readConfiguration(InputStream is, ClassLoader classLoader)
throws IOException {
ClassLoaderLogInfo info = classLoaderLoggers.get(classLoader);
try {
info.props.load(is);
} catch (IOException e) {
// Report error
System.err.println("Configuration error");
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException ioe) {
// Ignore
}
}
// Create handlers for the root logger of this classloader
String rootHandlers = info.props.getProperty(".handlers");
String handlers = info.props.getProperty("handlers");
Logger localRootLogger = info.rootNode.logger;
if (handlers != null) {
StringTokenizer tok = new StringTokenizer(handlers, ",");
while (tok.hasMoreTokens()) {
String handlerName = (tok.nextToken().trim());
String handlerClassName = handlerName;
String prefix = "";
if (handlerClassName.length() <= 0) {
continue;
}
// Parse and remove a prefix (prefix start with a digit, such as
// "10WebappFooHanlder.")
if (Character.isDigit(handlerClassName.charAt(0))) {
int pos = handlerClassName.indexOf('.');
if (pos >= 0) {
prefix = handlerClassName.substring(0, pos + 1);
handlerClassName = handlerClassName.substring(pos + 1);
}
}
try {
this.prefix.set(prefix);
Handler handler =
(Handler) classLoader.loadClass(handlerClassName).newInstance();
// The specification strongly implies all configuration should be done
// during the creation of the handler object.
// This includes setting level, filter, formatter and encoding.
this.prefix.set(null);
info.handlers.put(handlerName, handler);
if (rootHandlers == null) {
localRootLogger.addHandler(handler);
}
} catch (Exception e) {
// Report error
System.err.println("Handler error");
e.printStackTrace();
}
}
}
}
// in java/org/apache/coyote/Request.java
public int doRead(ByteChunk chunk)
throws IOException {
int n = inputBuffer.doRead(chunk, this);
if (n > 0) {
bytesRead+=n;
}
return n;
}
// in java/org/apache/coyote/Response.java
public void doWrite(ByteChunk chunk/*byte buffer[], int pos, int count*/)
throws IOException
{
outputBuffer.doWrite(chunk, this);
contentWritten+=chunk.getLength();
}
// in java/org/apache/coyote/ajp/AjpAprProcessor.java
Override
public SocketState process(SocketWrapper<Long> socket)
throws IOException {
RequestInfo rp = request.getRequestProcessor();
rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);
// Setting up the socket
this.socket = socket;
long socketRef = socket.getSocket().longValue();
Socket.setrbb(socketRef, inputBuffer);
Socket.setsbb(socketRef, outputBuffer);
boolean cping = false;
// Error flag
error = false;
boolean keptAlive = false;
while (!error && !endpoint.isPaused()) {
// Parsing the request header
try {
// Get first message of the request
if (!readMessage(requestHeaderMessage, true, keptAlive)) {
// This means that no data is available right now
// (long keepalive), so that the processor should be recycled
// and the method should return true
break;
}
// Check message type, process right away and break if
// not regular request processing
int type = requestHeaderMessage.getByte();
if (type == Constants.JK_AJP13_CPING_REQUEST) {
if (endpoint.isPaused()) {
recycle(true);
break;
}
cping = true;
if (Socket.send(socketRef, pongMessageArray, 0,
pongMessageArray.length) < 0) {
error = true;
}
continue;
} else if(type != Constants.JK_AJP13_FORWARD_REQUEST) {
// Unexpected packet type. Unread body packets should have
// been swallowed in finish().
if (log.isDebugEnabled()) {
log.debug("Unexpected message: " + type);
}
error = true;
break;
}
keptAlive = true;
request.setStartTime(System.currentTimeMillis());
} catch (IOException e) {
error = true;
break;
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.debug(sm.getString("ajpprocessor.header.error"), t);
// 400 - Bad Request
response.setStatus(400);
adapter.log(request, response, 0);
error = true;
}
if (!error) {
// Setting up filters, and parse some request headers
rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
try {
prepareRequest();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.debug(sm.getString("ajpprocessor.request.prepare"), t);
// 400 - Internal Server Error
response.setStatus(400);
adapter.log(request, response, 0);
error = true;
}
}
if (!error && !cping && endpoint.isPaused()) {
// 503 - Service unavailable
response.setStatus(503);
adapter.log(request, response, 0);
error = true;
}
cping = false;
// Process the request in the adapter
if (!error) {
try {
rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
adapter.service(request, response);
} catch (InterruptedIOException e) {
error = true;
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error(sm.getString("ajpprocessor.request.process"), t);
// 500 - Internal Server Error
response.setStatus(500);
adapter.log(request, response, 0);
error = true;
}
}
if (isAsync() && !error) {
break;
}
// Finish the response if not done yet
if (!finished) {
try {
finish();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
error = true;
}
}
// If there was an error, make sure the request is counted as
// and error, and update the statistics counter
if (error) {
response.setStatus(500);
}
request.updateCounters();
rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
recycle(false);
}
rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
if (!error && !endpoint.isPaused()) {
if (isAsync()) {
return SocketState.LONG;
} else {
return SocketState.OPEN;
}
} else {
return SocketState.CLOSED;
}
}
// in java/org/apache/coyote/ajp/AjpAprProcessor.java
Override
protected void output(byte[] src, int offset, int length)
throws IOException {
outputBuffer.put(src, offset, length);
long socketRef = socket.getSocket().longValue();
if (outputBuffer.position() > 0) {
if ((socketRef != 0) && Socket.sendbb(socketRef, 0, outputBuffer.position()) < 0) {
throw new IOException(sm.getString("ajpprocessor.failedsend"));
}
outputBuffer.clear();
}
}
// in java/org/apache/coyote/ajp/AjpAprProcessor.java
protected boolean read(int n)
throws IOException {
if (inputBuffer.capacity() - inputBuffer.limit() <=
n - inputBuffer.remaining()) {
inputBuffer.compact();
inputBuffer.limit(inputBuffer.position());
inputBuffer.position(0);
}
int nRead;
while (inputBuffer.remaining() < n) {
nRead = Socket.recvbb
(socket.getSocket().longValue(), inputBuffer.limit(),
inputBuffer.capacity() - inputBuffer.limit());
if (nRead > 0) {
inputBuffer.limit(inputBuffer.limit() + nRead);
} else {
throw new IOException(sm.getString("ajpprotocol.failedread"));
}
}
return true;
}
// in java/org/apache/coyote/ajp/AjpAprProcessor.java
protected boolean readt(int n, boolean useAvailableData)
throws IOException {
if (useAvailableData && inputBuffer.remaining() == 0) {
return false;
}
if (inputBuffer.capacity() - inputBuffer.limit() <=
n - inputBuffer.remaining()) {
inputBuffer.compact();
inputBuffer.limit(inputBuffer.position());
inputBuffer.position(0);
}
int nRead;
while (inputBuffer.remaining() < n) {
nRead = Socket.recvbb
(socket.getSocket().longValue(), inputBuffer.limit(),
inputBuffer.capacity() - inputBuffer.limit());
if (nRead > 0) {
inputBuffer.limit(inputBuffer.limit() + nRead);
} else {
if ((-nRead) == Status.ETIMEDOUT || (-nRead) == Status.TIMEUP) {
return false;
} else {
throw new IOException(sm.getString("ajpprotocol.failedread"));
}
}
}
return true;
}
// in java/org/apache/coyote/ajp/AjpAprProcessor.java
Override
public boolean receive() throws IOException {
first = false;
bodyMessage.reset();
if (!readMessage(bodyMessage, false, false)) {
// Invalid message
return false;
}
// No data received.
if (bodyMessage.getLen() == 0) {
// just the header
// Don't mark 'end of stream' for the first chunk.
return false;
}
int blen = bodyMessage.peekInt();
if (blen == 0) {
return false;
}
bodyMessage.getBodyBytes(bodyBytes);
empty = false;
return true;
}
// in java/org/apache/coyote/ajp/AjpAprProcessor.java
protected boolean readMessage(AjpMessage message, boolean first,
boolean useAvailableData)
throws IOException {
int headerLength = message.getHeaderLength();
if (first) {
if (!readt(headerLength, useAvailableData)) {
return false;
}
} else {
read(headerLength);
}
inputBuffer.get(message.getBuffer(), 0, headerLength);
int messageLength = message.processHeader(true);
if (messageLength < 0) {
// Invalid AJP header signature
// TODO: Throw some exception and close the connection to frontend.
return false;
}
else if (messageLength == 0) {
// Zero length message.
return true;
}
else {
if (messageLength > message.getBuffer().length) {
// Message too long for the buffer
// Need to trigger a 400 response
throw new IllegalArgumentException(sm.getString(
"ajpprocessor.header.tooLong",
Integer.valueOf(messageLength),
Integer.valueOf(message.getBuffer().length)));
}
read(messageLength);
inputBuffer.get(message.getBuffer(), headerLength, messageLength);
return true;
}
}
// in java/org/apache/coyote/ajp/AjpNioProcessor.java
Override
public SocketState process(SocketWrapper<NioChannel> socket)
throws IOException {
RequestInfo rp = request.getRequestProcessor();
rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);
// Setting up the socket
this.socket = socket.getSocket();
long soTimeout = endpoint.getSoTimeout();
boolean cping = false;
// Error flag
error = false;
while (!error && !endpoint.isPaused()) {
// Parsing the request header
try {
// Get first message of the request
int bytesRead = readMessage(requestHeaderMessage, false);
if (bytesRead == 0) {
break;
}
// Set back timeout if keep alive timeout is enabled
if (keepAliveTimeout > 0) {
socket.setTimeout(soTimeout);
}
// Check message type, process right away and break if
// not regular request processing
int type = requestHeaderMessage.getByte();
if (type == Constants.JK_AJP13_CPING_REQUEST) {
if (endpoint.isPaused()) {
recycle(true);
break;
}
cping = true;
try {
output(pongMessageArray, 0, pongMessageArray.length);
} catch (IOException e) {
error = true;
}
recycle(false);
continue;
} else if(type != Constants.JK_AJP13_FORWARD_REQUEST) {
// Unexpected packet type. Unread body packets should have
// been swallowed in finish().
if (log.isDebugEnabled()) {
log.debug("Unexpected message: " + type);
}
error = true;
recycle(true);
break;
}
request.setStartTime(System.currentTimeMillis());
} catch (IOException e) {
error = true;
break;
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.debug(sm.getString("ajpprocessor.header.error"), t);
// 400 - Bad Request
response.setStatus(400);
adapter.log(request, response, 0);
error = true;
}
if (!error) {
// Setting up filters, and parse some request headers
rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
try {
prepareRequest();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.debug(sm.getString("ajpprocessor.request.prepare"), t);
// 400 - Internal Server Error
response.setStatus(400);
adapter.log(request, response, 0);
error = true;
}
}
if (!error && !cping && endpoint.isPaused()) {
// 503 - Service unavailable
response.setStatus(503);
adapter.log(request, response, 0);
error = true;
}
cping = false;
// Process the request in the adapter
if (!error) {
try {
rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
adapter.service(request, response);
} catch (InterruptedIOException e) {
error = true;
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error(sm.getString("ajpprocessor.request.process"), t);
// 500 - Internal Server Error
response.setStatus(500);
adapter.log(request, response, 0);
error = true;
}
}
if (isAsync() && !error) {
break;
}
// Finish the response if not done yet
if (!finished) {
try {
finish();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
error = true;
}
}
// If there was an error, make sure the request is counted as
// and error, and update the statistics counter
if (error) {
response.setStatus(500);
}
request.updateCounters();
rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
// Set keep alive timeout if enabled
if (keepAliveTimeout > 0) {
socket.setTimeout(keepAliveTimeout);
}
recycle(false);
}
rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
if (!error && !endpoint.isPaused()) {
if (isAsync()) {
return SocketState.LONG;
} else {
return SocketState.OPEN;
}
} else {
return SocketState.CLOSED;
}
}
// in java/org/apache/coyote/ajp/AjpNioProcessor.java
Override
protected void output(byte[] src, int offset, int length)
throws IOException {
ByteBuffer writeBuffer = socket.getBufHandler() .getWriteBuffer();
writeBuffer.put(src, offset, length);
writeBuffer.flip();
NioEndpoint.KeyAttachment att = (NioEndpoint.KeyAttachment)socket.getAttachment(false);
if ( att == null ) throw new IOException("Key must be cancelled");
long writeTimeout = att.getTimeout();
Selector selector = null;
try {
selector = pool.get();
} catch ( IOException x ) {
//ignore
}
try {
pool.write(writeBuffer, socket, selector, writeTimeout, true);
}finally {
if ( selector != null ) pool.put(selector);
}
writeBuffer.clear();
}
// in java/org/apache/coyote/ajp/AjpNioProcessor.java
protected int read(byte[] buf, int pos, int n, boolean blockFirstRead)
throws IOException {
int read = 0;
int res = 0;
boolean block = blockFirstRead;
while (read < n) {
res = readSocket(buf, read + pos, n, block);
if (res > 0) {
read += res;
} else if (res == 0 && !block) {
break;
} else {
throw new IOException(sm.getString("ajpprotocol.failedread"));
}
block = true;
}
return read;
}
// in java/org/apache/coyote/ajp/AjpNioProcessor.java
private int readSocket(byte[] buf, int pos, int n, boolean block)
throws IOException {
int nRead = 0;
socket.getBufHandler().getReadBuffer().clear();
socket.getBufHandler().getReadBuffer().limit(n);
if ( block ) {
Selector selector = null;
try {
selector = pool.get();
} catch ( IOException x ) {
// Ignore
}
try {
NioEndpoint.KeyAttachment att = (NioEndpoint.KeyAttachment)socket.getAttachment(false);
if ( att == null ) throw new IOException("Key must be cancelled.");
nRead = pool.read(socket.getBufHandler().getReadBuffer(),socket,selector,att.getTimeout());
} catch ( EOFException eof ) {
nRead = -1;
} finally {
if ( selector != null ) pool.put(selector);
}
} else {
nRead = socket.read(socket.getBufHandler().getReadBuffer());
}
if (nRead > 0) {
socket.getBufHandler().getReadBuffer().flip();
socket.getBufHandler().getReadBuffer().limit(nRead);
socket.getBufHandler().getReadBuffer().get(buf, pos, nRead);
return nRead;
} else if (nRead == -1) {
//return false;
throw new EOFException(sm.getString("iib.eof.error"));
} else {
return 0;
}
}
// in java/org/apache/coyote/ajp/AjpNioProcessor.java
Override
public boolean receive() throws IOException {
first = false;
bodyMessage.reset();
readMessage(bodyMessage, true);
// No data received.
if (bodyMessage.getLen() == 0) {
// just the header
// Don't mark 'end of stream' for the first chunk.
return false;
}
int blen = bodyMessage.peekInt();
if (blen == 0) {
return false;
}
bodyMessage.getBodyBytes(bodyBytes);
empty = false;
return true;
}
// in java/org/apache/coyote/ajp/AjpNioProcessor.java
protected int readMessage(AjpMessage message, boolean blockFirstRead)
throws IOException {
byte[] buf = message.getBuffer();
int headerLength = message.getHeaderLength();
int bytesRead = read(buf, 0, headerLength, blockFirstRead);
if (bytesRead == 0) {
return 0;
}
int messageLength = message.processHeader(true);
if (messageLength < 0) {
// Invalid AJP header signature
throw new IOException(sm.getString("ajpmessage.invalidLength",
Integer.valueOf(messageLength)));
}
else if (messageLength == 0) {
// Zero length message.
return bytesRead;
}
else {
if (messageLength > buf.length) {
// Message too long for the buffer
// Need to trigger a 400 response
throw new IllegalArgumentException(sm.getString(
"ajpprocessor.header.tooLong",
Integer.valueOf(messageLength),
Integer.valueOf(buf.length)));
}
bytesRead += read(buf, headerLength, messageLength, true);
return bytesRead;
}
}
// in java/org/apache/coyote/ajp/AbstractAjpProcessor.java
Override
public SocketState event(SocketStatus status) throws IOException {
// Should never reach this code but in case we do...
throw new IOException(
sm.getString("ajpprocessor.comet.notsupported"));
}
// in java/org/apache/coyote/ajp/AbstractAjpProcessor.java
Override
public SocketState upgradeDispatch() throws IOException {
// Should never reach this code but in case we do...
throw new IOException(
sm.getString("ajpprocessor.httpupgrade.notsupported"));
}
// in java/org/apache/coyote/ajp/AbstractAjpProcessor.java
protected boolean refillReadBuffer() throws IOException {
// If the server returns an empty packet, assume that that end of
// the stream has been reached (yuck -- fix protocol??).
// FORM support
if (replay) {
endOfStream = true; // we've read everything there is
}
if (endOfStream) {
return false;
}
// Request more data immediately
output(getBodyMessageArray, 0, getBodyMessageArray.length);
boolean moreData = receive();
if( !moreData ) {
endOfStream = true;
}
return moreData;
}
// in java/org/apache/coyote/ajp/AbstractAjpProcessor.java
protected void prepareResponse() throws IOException {
response.setCommitted(true);
responseMessage.reset();
responseMessage.appendByte(Constants.JK_AJP13_SEND_HEADERS);
// HTTP header contents
responseMessage.appendInt(response.getStatus());
String message = null;
if (org.apache.coyote.Constants.USE_CUSTOM_STATUS_MSG_IN_HEADER &&
HttpMessages.isSafeInHttpHeader(response.getMessage())) {
message = response.getMessage();
}
if (message == null){
message = HttpMessages.getMessage(response.getStatus());
}
if (message == null) {
// mod_jk + httpd 2.x fails with a null status message - bug 45026
message = Integer.toString(response.getStatus());
}
tmpMB.setString(message);
responseMessage.appendBytes(tmpMB);
// Special headers
MimeHeaders headers = response.getMimeHeaders();
String contentType = response.getContentType();
if (contentType != null) {
headers.setValue("Content-Type").setString(contentType);
}
String contentLanguage = response.getContentLanguage();
if (contentLanguage != null) {
headers.setValue("Content-Language").setString(contentLanguage);
}
long contentLength = response.getContentLengthLong();
if (contentLength >= 0) {
headers.setValue("Content-Length").setLong(contentLength);
}
// Other headers
int numHeaders = headers.size();
responseMessage.appendInt(numHeaders);
for (int i = 0; i < numHeaders; i++) {
MessageBytes hN = headers.getName(i);
int hC = Constants.getResponseAjpIndex(hN.toString());
if (hC > 0) {
responseMessage.appendInt(hC);
}
else {
responseMessage.appendBytes(hN);
}
MessageBytes hV=headers.getValue(i);
responseMessage.appendBytes(hV);
}
// Write to buffer
responseMessage.end();
output(responseMessage.getBuffer(), 0,
responseMessage.getLen());
}
// in java/org/apache/coyote/ajp/AbstractAjpProcessor.java
protected void flush(boolean explicit) throws IOException {
if (explicit && !finished) {
// Send the flush message
output(flushMessageArray, 0, flushMessageArray.length);
}
}
// in java/org/apache/coyote/ajp/AbstractAjpProcessor.java
protected void finish() throws IOException {
if (!response.isCommitted()) {
// Validate and write response headers
try {
prepareResponse();
} catch (IOException e) {
// Set error flag
error = true;
}
}
if (finished)
return;
finished = true;
// Swallow the unread body packet if present
if (first && request.getContentLengthLong() > 0) {
receive();
}
// Add the end message
if (error) {
output(endAndCloseMessageArray, 0, endAndCloseMessageArray.length);
} else {
output(endMessageArray, 0, endMessageArray.length);
}
}
// in java/org/apache/coyote/ajp/AbstractAjpProcessor.java
Override
public int doRead(ByteChunk chunk, Request req)
throws IOException {
if (endOfStream) {
return -1;
}
if (first && req.getContentLengthLong() > 0) {
// Handle special first-body-chunk
if (!receive()) {
return 0;
}
} else if (empty) {
if (!refillReadBuffer()) {
return -1;
}
}
ByteChunk bc = bodyBytes.getByteChunk();
chunk.setBytes(bc.getBuffer(), bc.getStart(), bc.getLength());
empty = true;
return chunk.getLength();
}
// in java/org/apache/coyote/ajp/AbstractAjpProcessor.java
Override
public int doWrite(ByteChunk chunk, Response res)
throws IOException {
if (!response.isCommitted()) {
// Validate and write response headers
try {
prepareResponse();
} catch (IOException e) {
// Set error flag
error = true;
}
}
int len = chunk.getLength();
// 4 - hardcoded, byte[] marshaling overhead
// Adjust allowed size if packetSize != default (Constants.MAX_PACKET_SIZE)
int chunkSize = Constants.MAX_SEND_SIZE + packetSize - Constants.MAX_PACKET_SIZE;
int off = 0;
while (len > 0) {
int thisTime = len;
if (thisTime > chunkSize) {
thisTime = chunkSize;
}
len -= thisTime;
responseMessage.reset();
responseMessage.appendByte(Constants.JK_AJP13_SEND_BODY_CHUNK);
responseMessage.appendBytes(chunk.getBytes(), chunk.getOffset() + off, thisTime);
responseMessage.end();
output(responseMessage.getBuffer(), 0, responseMessage.getLen());
off += thisTime;
}
bytesWritten += chunk.getLength();
return chunk.getLength();
}
// in java/org/apache/coyote/ajp/AjpProcessor.java
Override
public SocketState process(SocketWrapper<Socket> socket)
throws IOException {
RequestInfo rp = request.getRequestProcessor();
rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);
// Setting up the socket
this.socket = socket;
input = socket.getSocket().getInputStream();
output = socket.getSocket().getOutputStream();
int soTimeout = -1;
if (keepAliveTimeout > 0) {
soTimeout = socket.getSocket().getSoTimeout();
}
boolean cping = false;
// Error flag
error = false;
while (!error && !endpoint.isPaused()) {
// Parsing the request header
try {
// Set keep alive timeout if enabled
if (keepAliveTimeout > 0) {
socket.getSocket().setSoTimeout(keepAliveTimeout);
}
// Get first message of the request
if (!readMessage(requestHeaderMessage)) {
// This means a connection timeout
break;
}
// Set back timeout if keep alive timeout is enabled
if (keepAliveTimeout > 0) {
socket.getSocket().setSoTimeout(soTimeout);
}
// Check message type, process right away and break if
// not regular request processing
int type = requestHeaderMessage.getByte();
if (type == Constants.JK_AJP13_CPING_REQUEST) {
if (endpoint.isPaused()) {
recycle(true);
break;
}
cping = true;
try {
output.write(pongMessageArray);
} catch (IOException e) {
error = true;
}
continue;
} else if(type != Constants.JK_AJP13_FORWARD_REQUEST) {
// Unexpected packet type. Unread body packets should have
// been swallowed in finish().
if (log.isDebugEnabled()) {
log.debug("Unexpected message: " + type);
}
error = true;
break;
}
request.setStartTime(System.currentTimeMillis());
} catch (IOException e) {
error = true;
break;
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.debug(sm.getString("ajpprocessor.header.error"), t);
// 400 - Bad Request
response.setStatus(400);
adapter.log(request, response, 0);
error = true;
}
if (!error) {
// Setting up filters, and parse some request headers
rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
try {
prepareRequest();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.debug(sm.getString("ajpprocessor.request.prepare"), t);
// 400 - Internal Server Error
response.setStatus(400);
adapter.log(request, response, 0);
error = true;
}
}
if (!error && !cping && endpoint.isPaused()) {
// 503 - Service unavailable
response.setStatus(503);
adapter.log(request, response, 0);
error = true;
}
cping = false;
// Process the request in the adapter
if (!error) {
try {
rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
adapter.service(request, response);
} catch (InterruptedIOException e) {
error = true;
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error(sm.getString("ajpprocessor.request.process"), t);
// 500 - Internal Server Error
response.setStatus(500);
adapter.log(request, response, 0);
error = true;
}
}
if (isAsync() && !error) {
break;
}
// Finish the response if not done yet
if (!finished) {
try {
finish();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
error = true;
}
}
// If there was an error, make sure the request is counted as
// and error, and update the statistics counter
if (error) {
response.setStatus(500);
}
request.updateCounters();
rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
recycle(false);
}
rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
if (isAsync() && !error && !endpoint.isPaused()) {
return SocketState.LONG;
} else {
input = null;
output = null;
return SocketState.CLOSED;
}
}
// in java/org/apache/coyote/ajp/AjpProcessor.java
Override
protected void output(byte[] src, int offset, int length)
throws IOException {
output.write(src, offset, length);
}
// in java/org/apache/coyote/ajp/AjpProcessor.java
protected boolean read(byte[] buf, int pos, int n)
throws IOException {
int read = 0;
int res = 0;
while (read < n) {
res = input.read(buf, read + pos, n - read);
if (res > 0) {
read += res;
} else {
throw new IOException(sm.getString("ajpprotocol.failedread"));
}
}
return true;
}
// in java/org/apache/coyote/ajp/AjpProcessor.java
Override
public boolean receive() throws IOException {
first = false;
bodyMessage.reset();
if (!readMessage(bodyMessage)) {
// Invalid message
return false;
}
// No data received.
if (bodyMessage.getLen() == 0) {
// just the header
// Don't mark 'end of stream' for the first chunk.
return false;
}
int blen = bodyMessage.peekInt();
if (blen == 0) {
return false;
}
bodyMessage.getBodyBytes(bodyBytes);
empty = false;
return true;
}
// in java/org/apache/coyote/ajp/AjpProcessor.java
protected boolean readMessage(AjpMessage message)
throws IOException {
byte[] buf = message.getBuffer();
int headerLength = message.getHeaderLength();
read(buf, 0, headerLength);
int messageLength = message.processHeader(true);
if (messageLength < 0) {
// Invalid AJP header signature
// TODO: Throw some exception and close the connection to frontend.
return false;
}
else if (messageLength == 0) {
// Zero length message.
return true;
}
else {
if (messageLength > buf.length) {
// Message too long for the buffer
// Need to trigger a 400 response
throw new IllegalArgumentException(sm.getString(
"ajpprocessor.header.tooLong",
Integer.valueOf(messageLength),
Integer.valueOf(buf.length)));
}
read(buf, headerLength, messageLength);
return true;
}
}
// in java/org/apache/coyote/http11/Http11AprProcessor.java
Override
public SocketState event(SocketStatus status)
throws IOException {
RequestInfo rp = request.getRequestProcessor();
try {
rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
error = !adapter.event(request, response, status);
} catch (InterruptedIOException e) {
error = true;
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error(sm.getString("http11processor.request.process"), t);
// 500 - Internal Server Error
response.setStatus(500);
adapter.log(request, response, 0);
error = true;
}
rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
if (error) {
return SocketState.CLOSED;
} else if (!comet) {
inputBuffer.nextRequest();
outputBuffer.nextRequest();
return SocketState.OPEN;
} else {
return SocketState.LONG;
}
}
// in java/org/apache/coyote/http11/Http11AprProcessor.java
Override
protected void setRequestLineReadTimeout() throws IOException {
// Timeouts while in the poller are handled entirely by the poller
// Only need to be concerned with socket timeouts
// APR uses simulated blocking so if some request line data is present
// then it must all be presented (with the normal socket timeout).
// When entering the processing loop for the first time there will
// always be some data to read so the keep-alive timeout is not required
// For the second and subsequent executions of the processing loop, if
// there is no request line data present then no further data will be
// read from the socket. If there is request line data present then it
// must all be presented (with the normal socket timeout)
// When the socket is created it is given the correct timeout.
// sendfile may change the timeout but will restore it
// This processor may change the timeout for uploads but will restore it
// NO-OP
}
// in java/org/apache/coyote/http11/Http11NioProcessor.java
Override
public SocketState event(SocketStatus status)
throws IOException {
long soTimeout = endpoint.getSoTimeout();
RequestInfo rp = request.getRequestProcessor();
final NioEndpoint.KeyAttachment attach = (NioEndpoint.KeyAttachment)socket.getSocket().getAttachment(false);
try {
rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
error = !adapter.event(request, response, status);
if ( !error ) {
if (attach != null) {
attach.setComet(comet);
if (comet) {
Integer comettimeout = (Integer) request.getAttribute(
org.apache.coyote.Constants.COMET_TIMEOUT_ATTR);
if (comettimeout != null) {
attach.setTimeout(comettimeout.longValue());
}
} else {
//reset the timeout
if (keepAlive) {
attach.setTimeout(keepAliveTimeout);
} else {
attach.setTimeout(soTimeout);
}
}
}
}
} catch (InterruptedIOException e) {
error = true;
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error(sm.getString("http11processor.request.process"), t);
// 500 - Internal Server Error
response.setStatus(500);
adapter.log(request, response, 0);
error = true;
}
rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
if (error) {
return SocketState.CLOSED;
} else if (!comet) {
if (keepAlive) {
inputBuffer.nextRequest();
outputBuffer.nextRequest();
return SocketState.OPEN;
} else {
return SocketState.CLOSED;
}
} else {
return SocketState.LONG;
}
}
// in java/org/apache/coyote/http11/Http11NioProcessor.java
Override
protected void setRequestLineReadTimeout() throws IOException {
// socket.setTimeout()
// - timeout used by poller
// socket.getSocket().getIOChannel().socket().setSoTimeout()
// - timeout used for blocking reads
// When entering the processing loop there will always be data to read
// so no point changing timeouts at this point
// For the second and subsequent executions of the processing loop, a
// non-blocking read is used so again no need to set the timeouts
// Because NIO supports non-blocking reading of the request line and
// headers the timeouts need to be set when returning the socket to
// the poller rather than here.
// NO-OP
}
// in java/org/apache/coyote/http11/Http11NioProcessor.java
Override
protected void setSocketTimeout(int timeout) throws IOException {
socket.getSocket().getIOChannel().socket().setSoTimeout(timeout);
}
// in java/org/apache/coyote/http11/InternalOutputBuffer.java
Override
public void init(SocketWrapper<Socket> socketWrapper,
AbstractEndpoint endpoint) throws IOException {
outputStream = socketWrapper.getSocket().getOutputStream();
}
// in java/org/apache/coyote/http11/InternalOutputBuffer.java
Override
public void flush()
throws IOException {
super.flush();
// Flush the current buffer
if (useSocketBuffer) {
socketBuffer.flushBuffer();
}
}
// in java/org/apache/coyote/http11/InternalOutputBuffer.java
Override
public void endRequest()
throws IOException {
super.endRequest();
if (useSocketBuffer) {
socketBuffer.flushBuffer();
}
}
// in java/org/apache/coyote/http11/InternalOutputBuffer.java
Override
public void sendAck()
throws IOException {
if (!committed)
outputStream.write(Constants.ACK_BYTES);
}
// in java/org/apache/coyote/http11/InternalOutputBuffer.java
Override
protected void commit()
throws IOException {
// The response is now committed
committed = true;
response.setCommitted(true);
if (pos > 0) {
// Sending the response header buffer
if (useSocketBuffer) {
socketBuffer.append(buf, 0, pos);
} else {
outputStream.write(buf, 0, pos);
}
}
}
// in java/org/apache/coyote/http11/InternalOutputBuffer.java
Override
public void realWriteBytes(byte cbuf[], int off, int len)
throws IOException {
if (len > 0) {
outputStream.write(cbuf, off, len);
}
}
// in java/org/apache/coyote/http11/InternalOutputBuffer.java
Override
public int doWrite(ByteChunk chunk, Response res)
throws IOException {
int length = chunk.getLength();
if (useSocketBuffer) {
socketBuffer.append(chunk.getBuffer(), chunk.getStart(),
length);
} else {
outputStream.write(chunk.getBuffer(), chunk.getStart(),
length);
}
byteCount += chunk.getLength();
return chunk.getLength();
}
// in java/org/apache/coyote/http11/InternalNioInputBuffer.java
Override
public boolean parseRequestLine(boolean useAvailableDataOnly)
throws IOException {
//check state
if ( !parsingRequestLine ) return true;
//
// Skipping blank lines
//
if ( parsingRequestLinePhase == 0 ) {
byte chr = 0;
do {
// Read new bytes if needed
if (pos >= lastValid) {
if (useAvailableDataOnly) {
return false;
}
// Ignore bytes that were read
pos = lastValid = 0;
// Do a simple read with a short timeout
if ( readSocket(true, false)==0 ) return false;
}
chr = buf[pos++];
} while ((chr == Constants.CR) || (chr == Constants.LF));
pos--;
if (pos >= skipBlankLinesSize) {
// Move data, to have enough space for further reading
// of headers and body
System.arraycopy(buf, pos, buf, 0, lastValid - pos);
lastValid -= pos;
pos = 0;
}
skipBlankLinesBytes = pos;
parsingRequestLineStart = pos;
parsingRequestLinePhase = 2;
if (log.isDebugEnabled()) {
log.debug("Received ["
+ new String(buf, pos, lastValid - pos, DEFAULT_CHARSET)
+ "]");
}
}
if ( parsingRequestLinePhase == 2 ) {
//
// Reading the method name
// Method name is always US-ASCII
//
boolean space = false;
while (!space) {
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill(true, false)) //request line parsing
return false;
}
// Spec says no CR or LF in method name
if (buf[pos] == Constants.CR || buf[pos] == Constants.LF) {
throw new IllegalArgumentException(
sm.getString("iib.invalidmethod"));
}
if (buf[pos] == Constants.SP || buf[pos] == Constants.HT) {
space = true;
request.method().setBytes(buf, parsingRequestLineStart, pos - parsingRequestLineStart);
}
pos++;
}
parsingRequestLinePhase = 3;
}
if ( parsingRequestLinePhase == 3 ) {
// Spec says single SP but also be tolerant of multiple and/or HT
boolean space = true;
while (space) {
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill(true, false)) //request line parsing
return false;
}
if (buf[pos] == Constants.SP || buf[pos] == Constants.HT) {
pos++;
} else {
space = false;
}
}
parsingRequestLineStart = pos;
parsingRequestLinePhase = 4;
}
if (parsingRequestLinePhase == 4) {
// Mark the current buffer position
int end = 0;
//
// Reading the URI
//
boolean space = false;
while (!space) {
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill(true,false)) //request line parsing
return false;
}
if (buf[pos] == Constants.SP || buf[pos] == Constants.HT) {
space = true;
end = pos;
} else if ((buf[pos] == Constants.CR)
|| (buf[pos] == Constants.LF)) {
// HTTP/0.9 style request
parsingRequestLineEol = true;
space = true;
end = pos;
} else if ((buf[pos] == Constants.QUESTION)
&& (parsingRequestLineQPos == -1)) {
parsingRequestLineQPos = pos;
}
pos++;
}
request.unparsedURI().setBytes(buf, parsingRequestLineStart, end - parsingRequestLineStart);
if (parsingRequestLineQPos >= 0) {
request.queryString().setBytes(buf, parsingRequestLineQPos + 1,
end - parsingRequestLineQPos - 1);
request.requestURI().setBytes(buf, parsingRequestLineStart, parsingRequestLineQPos - parsingRequestLineStart);
} else {
request.requestURI().setBytes(buf, parsingRequestLineStart, end - parsingRequestLineStart);
}
parsingRequestLinePhase = 5;
}
if ( parsingRequestLinePhase == 5 ) {
// Spec says single SP but also be tolerant of multiple and/or HT
boolean space = true;
while (space) {
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill(true, false)) //request line parsing
return false;
}
if (buf[pos] == Constants.SP || buf[pos] == Constants.HT) {
pos++;
} else {
space = false;
}
}
parsingRequestLineStart = pos;
parsingRequestLinePhase = 6;
}
if (parsingRequestLinePhase == 6) {
// Mark the current buffer position
end = 0;
//
// Reading the protocol
// Protocol is always US-ASCII
//
while (!parsingRequestLineEol) {
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill(true, false)) //request line parsing
return false;
}
if (buf[pos] == Constants.CR) {
end = pos;
} else if (buf[pos] == Constants.LF) {
if (end == 0)
end = pos;
parsingRequestLineEol = true;
}
pos++;
}
if ( (end - parsingRequestLineStart) > 0) {
request.protocol().setBytes(buf, parsingRequestLineStart, end - parsingRequestLineStart);
} else {
request.protocol().setString("");
}
parsingRequestLine = false;
parsingRequestLinePhase = 0;
parsingRequestLineEol = false;
parsingRequestLineStart = 0;
return true;
}
throw new IllegalStateException("Invalid request line parse phase:"+parsingRequestLinePhase);
}
// in java/org/apache/coyote/http11/InternalNioInputBuffer.java
private int readSocket(boolean timeout, boolean block) throws IOException {
int nRead = 0;
socket.getBufHandler().getReadBuffer().clear();
if ( block ) {
Selector selector = null;
try {
selector = pool.get();
} catch ( IOException x ) {
// Ignore
}
try {
NioEndpoint.KeyAttachment att = (NioEndpoint.KeyAttachment)socket.getAttachment(false);
if ( att == null ) throw new IOException("Key must be cancelled.");
nRead = pool.read(socket.getBufHandler().getReadBuffer(),socket,selector,att.getTimeout());
} catch ( EOFException eof ) {
nRead = -1;
} finally {
if ( selector != null ) pool.put(selector);
}
} else {
nRead = socket.read(socket.getBufHandler().getReadBuffer());
}
if (nRead > 0) {
socket.getBufHandler().getReadBuffer().flip();
socket.getBufHandler().getReadBuffer().limit(nRead);
expand(nRead + pos);
socket.getBufHandler().getReadBuffer().get(buf, pos, nRead);
lastValid = pos + nRead;
return nRead;
} else if (nRead == -1) {
//return false;
throw new EOFException(sm.getString("iib.eof.error"));
} else {
return 0;
}
}
// in java/org/apache/coyote/http11/InternalNioInputBuffer.java
Override
public boolean parseHeaders()
throws IOException {
if (!parsingHeader) {
throw new IllegalStateException(
sm.getString("iib.parseheaders.ise.error"));
}
HeaderParseStatus status = HeaderParseStatus.HAVE_MORE_HEADERS;
do {
status = parseHeader();
} while ( status == HeaderParseStatus.HAVE_MORE_HEADERS );
if (status == HeaderParseStatus.DONE) {
parsingHeader = false;
end = pos;
// Checking that
// (1) Headers plus request line size does not exceed its limit
// (2) There are enough bytes to avoid expanding the buffer when
// reading body
// Technically, (2) is technical limitation, (1) is logical
// limitation to enforce the meaning of headerBufferSize
// From the way how buf is allocated and how blank lines are being
// read, it should be enough to check (1) only.
if (end - skipBlankLinesBytes > headerBufferSize
|| buf.length - end < socketReadBufferSize) {
throw new IllegalArgumentException(
sm.getString("iib.requestheadertoolarge.error"));
}
return true;
} else {
return false;
}
}
// in java/org/apache/coyote/http11/InternalNioInputBuffer.java
private HeaderParseStatus parseHeader()
throws IOException {
//
// Check for blank line
//
byte chr = 0;
while (headerParsePos == HeaderParsePosition.HEADER_START) {
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill(true,false)) {//parse header
headerParsePos = HeaderParsePosition.HEADER_START;
return HeaderParseStatus.NEED_MORE_DATA;
}
}
chr = buf[pos];
if (chr == Constants.CR) {
// Skip
} else if (chr == Constants.LF) {
pos++;
return HeaderParseStatus.DONE;
} else {
break;
}
pos++;
}
if ( headerParsePos == HeaderParsePosition.HEADER_START ) {
// Mark the current buffer position
headerData.start = pos;
headerParsePos = HeaderParsePosition.HEADER_NAME;
}
//
// Reading the header name
// Header name is always US-ASCII
//
while (headerParsePos == HeaderParsePosition.HEADER_NAME) {
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill(true,false)) { //parse header
return HeaderParseStatus.NEED_MORE_DATA;
}
}
chr = buf[pos];
if (chr == Constants.COLON) {
headerParsePos = HeaderParsePosition.HEADER_VALUE_START;
headerData.headerValue = headers.addValue(buf, headerData.start, pos - headerData.start);
pos++;
// Mark the current buffer position
headerData.start = pos;
headerData.realPos = pos;
headerData.lastSignificantChar = pos;
break;
} else if (!HTTP_TOKEN_CHAR[chr]) {
// If a non-token header is detected, skip the line and
// ignore the header
headerData.lastSignificantChar = pos;
return skipLine();
}
// chr is next byte of header name. Convert to lowercase.
if ((chr >= Constants.A) && (chr <= Constants.Z)) {
buf[pos] = (byte) (chr - Constants.LC_OFFSET);
}
pos++;
}
// Skip the line and ignore the header
if (headerParsePos == HeaderParsePosition.HEADER_SKIPLINE) {
return skipLine();
}
//
// Reading the header value (which can be spanned over multiple lines)
//
while (headerParsePos == HeaderParsePosition.HEADER_VALUE_START ||
headerParsePos == HeaderParsePosition.HEADER_VALUE ||
headerParsePos == HeaderParsePosition.HEADER_MULTI_LINE) {
if ( headerParsePos == HeaderParsePosition.HEADER_VALUE_START ) {
// Skipping spaces
while (true) {
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill(true,false)) {//parse header
//HEADER_VALUE_START
return HeaderParseStatus.NEED_MORE_DATA;
}
}
chr = buf[pos];
if (chr == Constants.SP || chr == Constants.HT) {
pos++;
} else {
headerParsePos = HeaderParsePosition.HEADER_VALUE;
break;
}
}
}
if ( headerParsePos == HeaderParsePosition.HEADER_VALUE ) {
// Reading bytes until the end of the line
boolean eol = false;
while (!eol) {
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill(true,false)) {//parse header
//HEADER_VALUE
return HeaderParseStatus.NEED_MORE_DATA;
}
}
chr = buf[pos];
if (chr == Constants.CR) {
// Skip
} else if (chr == Constants.LF) {
eol = true;
} else if (chr == Constants.SP || chr == Constants.HT) {
buf[headerData.realPos] = chr;
headerData.realPos++;
} else {
buf[headerData.realPos] = chr;
headerData.realPos++;
headerData.lastSignificantChar = headerData.realPos;
}
pos++;
}
// Ignore whitespaces at the end of the line
headerData.realPos = headerData.lastSignificantChar;
// Checking the first character of the new line. If the character
// is a LWS, then it's a multiline header
headerParsePos = HeaderParsePosition.HEADER_MULTI_LINE;
}
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill(true,false)) {//parse header
//HEADER_MULTI_LINE
return HeaderParseStatus.NEED_MORE_DATA;
}
}
chr = buf[pos];
if ( headerParsePos == HeaderParsePosition.HEADER_MULTI_LINE ) {
if ( (chr != Constants.SP) && (chr != Constants.HT)) {
headerParsePos = HeaderParsePosition.HEADER_START;
break;
} else {
// Copying one extra space in the buffer (since there must
// be at least one space inserted between the lines)
buf[headerData.realPos] = chr;
headerData.realPos++;
headerParsePos = HeaderParsePosition.HEADER_VALUE_START;
}
}
}
// Set the header value
headerData.headerValue.setBytes(buf, headerData.start,
headerData.lastSignificantChar - headerData.start);
headerData.recycle();
return HeaderParseStatus.HAVE_MORE_HEADERS;
}
// in java/org/apache/coyote/http11/InternalNioInputBuffer.java
private HeaderParseStatus skipLine() throws IOException {
headerParsePos = HeaderParsePosition.HEADER_SKIPLINE;
boolean eol = false;
// Reading bytes until the end of the line
while (!eol) {
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill(true,false)) {
return HeaderParseStatus.NEED_MORE_DATA;
}
}
if (buf[pos] == Constants.CR) {
// Skip
} else if (buf[pos] == Constants.LF) {
eol = true;
} else {
headerData.lastSignificantChar = pos;
}
pos++;
}
if (log.isDebugEnabled()) {
log.debug(sm.getString("iib.invalidheader", new String(buf,
headerData.start,
headerData.lastSignificantChar - headerData.start + 1,
DEFAULT_CHARSET)));
}
headerParsePos = HeaderParsePosition.HEADER_START;
return HeaderParseStatus.HAVE_MORE_HEADERS;
}
// in java/org/apache/coyote/http11/InternalNioInputBuffer.java
Override
protected void init(SocketWrapper<NioChannel> socketWrapper,
AbstractEndpoint endpoint) throws IOException {
socket = socketWrapper.getSocket();
socketReadBufferSize =
socket.getBufHandler().getReadBuffer().capacity();
int bufLength = skipBlankLinesSize + headerBufferSize
+ socketReadBufferSize;
if (buf == null || buf.length < bufLength) {
buf = new byte[bufLength];
}
pool = ((NioEndpoint)endpoint).getSelectorPool();
}
// in java/org/apache/coyote/http11/InternalNioInputBuffer.java
Override
protected boolean fill(boolean block) throws IOException, EOFException {
return fill(true,block);
}
// in java/org/apache/coyote/http11/InternalNioInputBuffer.java
protected boolean fill(boolean timeout, boolean block) throws IOException, EOFException {
boolean read = false;
if (parsingHeader) {
if (lastValid == buf.length) {
throw new IllegalArgumentException
(sm.getString("iib.requestheadertoolarge.error"));
}
// Do a simple read with a short timeout
read = readSocket(timeout,block)>0;
} else {
lastValid = pos = end;
// Do a simple read with a short timeout
read = readSocket(timeout, block)>0;
}
return read;
}
// in java/org/apache/coyote/http11/InternalNioInputBuffer.java
Override
public int doRead(ByteChunk chunk, Request req )
throws IOException {
if (pos >= lastValid) {
if (!fill(true,true)) //read body, must be blocking, as the thread is inside the app
return -1;
}
int length = lastValid - pos;
chunk.setBytes(buf, pos, length);
pos = lastValid;
return (length);
}
// in java/org/apache/coyote/http11/upgrade/UpgradeProcessor.java
Override
public final SocketState upgradeDispatch() throws IOException {
return upgradeInbound.onData();
}
// in java/org/apache/coyote/http11/upgrade/UpgradeProcessor.java
Override
public final SocketState process(SocketWrapper<S> socketWrapper)
throws IOException {
return null;
}
// in java/org/apache/coyote/http11/upgrade/UpgradeProcessor.java
Override
public final SocketState event(SocketStatus status) throws IOException {
return null;
}
// in java/org/apache/coyote/http11/upgrade/UpgradeNioProcessor.java
Override
public void flush() throws IOException {
NioEndpoint.KeyAttachment att =
(NioEndpoint.KeyAttachment) nioChannel.getAttachment(false);
if (att == null) {
throw new IOException("Key must be cancelled");
}
long writeTimeout = att.getTimeout();
Selector selector = null;
try {
selector = pool.get();
} catch ( IOException x ) {
//ignore
}
try {
do {
if (nioChannel.flush(true, selector, writeTimeout)) {
break;
}
} while (true);
} finally {
if (selector != null) {
pool.put(selector);
}
}
}
// in java/org/apache/coyote/http11/upgrade/UpgradeNioProcessor.java
Override
public void write(int b) throws IOException {
writeToSocket(new byte[] {(byte) b}, 0, 1);
}
// in java/org/apache/coyote/http11/upgrade/UpgradeNioProcessor.java
Override
public void write(byte[]b, int off, int len) throws IOException {
int written = 0;
while (len - written > maxWrite) {
written += writeToSocket(b, off + written, maxWrite);
}
writeToSocket(b, off + written, len - written);
}
// in java/org/apache/coyote/http11/upgrade/UpgradeNioProcessor.java
Override
public int read() throws IOException {
byte[] bytes = new byte[1];
int result = readSocket(true, bytes, 0, 1);
if (result == -1) {
return -1;
} else {
return bytes[0] & 0xFF;
}
}
// in java/org/apache/coyote/http11/upgrade/UpgradeNioProcessor.java
Override
public int read(boolean block, byte[] bytes, int off, int len)
throws IOException {
if (len > maxRead) {
return readSocket(block, bytes, off, maxRead);
} else {
return readSocket(block, bytes, off, len);
}
}
// in java/org/apache/coyote/http11/upgrade/UpgradeNioProcessor.java
private int readSocket(boolean block, byte[] bytes, int offset, int len)
throws IOException {
int nRead = 0;
nioChannel.getBufHandler().getReadBuffer().clear();
nioChannel.getBufHandler().getReadBuffer().limit(len);
if (block) {
Selector selector = null;
try {
selector = pool.get();
} catch ( IOException x ) {
// Ignore
}
try {
NioEndpoint.KeyAttachment att =
(NioEndpoint.KeyAttachment) nioChannel.getAttachment(false);
if (att == null) {
throw new IOException("Key must be cancelled.");
}
nRead = pool.read(nioChannel.getBufHandler().getReadBuffer(),
nioChannel, selector, att.getTimeout());
} catch (EOFException eof) {
nRead = -1;
} finally {
if (selector != null) {
pool.put(selector);
}
}
} else {
nRead = nioChannel.read(nioChannel.getBufHandler().getReadBuffer());
}
if (nRead > 0) {
nioChannel.getBufHandler().getReadBuffer().flip();
nioChannel.getBufHandler().getReadBuffer().limit(nRead);
nioChannel.getBufHandler().getReadBuffer().get(bytes, offset, nRead);
return nRead;
} else if (nRead == -1) {
//return false;
throw new EOFException(sm.getString("nio.eof.error"));
} else {
return 0;
}
}
// in java/org/apache/coyote/http11/upgrade/UpgradeNioProcessor.java
private synchronized int writeToSocket(byte[] bytes, int off, int len)
throws IOException {
nioChannel.getBufHandler().getWriteBuffer().clear();
nioChannel.getBufHandler().getWriteBuffer().put(bytes, off, len);
nioChannel.getBufHandler().getWriteBuffer().flip();
int written = 0;
NioEndpoint.KeyAttachment att =
(NioEndpoint.KeyAttachment) nioChannel.getAttachment(false);
if (att == null) {
throw new IOException("Key must be cancelled");
}
long writeTimeout = att.getTimeout();
Selector selector = null;
try {
selector = pool.get();
} catch ( IOException x ) {
//ignore
}
try {
written = pool.write(nioChannel.getBufHandler().getWriteBuffer(),
nioChannel, selector, writeTimeout, true);
} finally {
if (selector != null) {
pool.put(selector);
}
}
return written;
}
// in java/org/apache/coyote/http11/upgrade/UpgradeBioProcessor.java
Override
public void flush() throws IOException {
outputStream.flush();
}
// in java/org/apache/coyote/http11/upgrade/UpgradeBioProcessor.java
Override
public void write(int b) throws IOException {
outputStream.write(b);
}
// in java/org/apache/coyote/http11/upgrade/UpgradeBioProcessor.java
Override
public void write(byte[]b, int off, int len) throws IOException {
outputStream.write(b, off, len);
}
// in java/org/apache/coyote/http11/upgrade/UpgradeBioProcessor.java
Override
public int read() throws IOException {
return inputStream.read();
}
// in java/org/apache/coyote/http11/upgrade/UpgradeBioProcessor.java
Override
public int read(boolean block, byte[] bytes, int off, int len)
throws IOException {
// The BIO endpoint always uses blocking IO so the block parameter is
// ignored and a blocking read is performed.
return inputStream.read(bytes, off, len);
}
// in java/org/apache/coyote/http11/upgrade/UpgradeAprProcessor.java
Override
public void flush() throws IOException {
// NOOP
}
// in java/org/apache/coyote/http11/upgrade/UpgradeAprProcessor.java
Override
public void write(int b) throws IOException {
Socket.send(socket, new byte[] {(byte) b}, 0, 1);
}
// in java/org/apache/coyote/http11/upgrade/UpgradeAprProcessor.java
Override
public void write(byte[]b, int off, int len) throws IOException {
Socket.send(socket, b, off, len);
}
// in java/org/apache/coyote/http11/upgrade/UpgradeAprProcessor.java
Override
public int read() throws IOException {
byte[] bytes = new byte[1];
int result = Socket.recv(socket, bytes, 0, 1);
if (result == -1) {
return -1;
} else {
return bytes[0] & 0xFF;
}
}
// in java/org/apache/coyote/http11/upgrade/UpgradeAprProcessor.java
Override
public int read(boolean block, byte[] bytes, int off, int len)
throws IOException {
if (!block) {
Socket.optSet(socket, Socket.APR_SO_NONBLOCK, -1);
}
try {
int result = Socket.recv(socket, bytes, off, len);
if (result > 0) {
return result;
} else if (-result == Status.EAGAIN) {
return 0;
} else {
throw new IOException(sm.getString("apr.error",
Integer.valueOf(-result)));
}
} finally {
if (!block) {
Socket.optSet(socket, Socket.APR_SO_NONBLOCK, 0);
}
}
}
// in java/org/apache/coyote/http11/upgrade/UpgradeOutbound.java
Override
public void flush() throws IOException {
processor.flush();
}
// in java/org/apache/coyote/http11/upgrade/UpgradeOutbound.java
Override
public void write(int b) throws IOException {
processor.write(b);
}
// in java/org/apache/coyote/http11/upgrade/UpgradeOutbound.java
Override
public void write(byte[] b, int off, int len) throws IOException {
processor.write(b, off, len);
}
// in java/org/apache/coyote/http11/Http11NioProtocol.java
Override
protected Processor<NioChannel> createUpgradeProcessor(
SocketWrapper<NioChannel> socket, UpgradeInbound inbound)
throws IOException {
return new UpgradeNioProcessor(socket, inbound,
((Http11NioProtocol) getProtocol()).getEndpoint().getSelectorPool());
}
// in java/org/apache/coyote/http11/filters/SavedRequestInputFilter.java
Override
public int doRead(ByteChunk chunk, org.apache.coyote.Request request)
throws IOException {
int writeLength = 0;
if (chunk.getLimit() > 0 && chunk.getLimit() < input.getLength()) {
writeLength = chunk.getLimit();
} else {
writeLength = input.getLength();
}
if(input.getOffset()>= input.getEnd())
return -1;
input.substract(chunk.getBuffer(), 0, writeLength);
chunk.setOffset(0);
chunk.setEnd(writeLength);
return writeLength;
}
// in java/org/apache/coyote/http11/filters/SavedRequestInputFilter.java
Override
public long end() throws IOException {
return 0;
}
// in java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
Override
public int doRead(ByteChunk chunk, Request req)
throws IOException {
if (endChunk)
return -1;
if(needCRLFParse) {
needCRLFParse = false;
parseCRLF();
}
if (remaining <= 0) {
if (!parseChunkHeader()) {
throw new IOException("Invalid chunk header");
}
if (endChunk) {
parseEndChunk();
return -1;
}
}
int result = 0;
if (pos >= lastValid) {
readBytes();
}
if (remaining > (lastValid - pos)) {
result = lastValid - pos;
remaining = remaining - result;
chunk.setBytes(buf, pos, result);
pos = lastValid;
} else {
result = remaining;
chunk.setBytes(buf, pos, remaining);
pos = pos + remaining;
remaining = 0;
//we need a CRLF
if ((pos+1) >= lastValid) {
//if we call parseCRLF we overrun the buffer here
//so we defer it to the next call BZ 11117
needCRLFParse = true;
} else {
parseCRLF(); //parse the CRLF immediately
}
}
return result;
}
// in java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
Override
public long end()
throws IOException {
// Consume extra bytes : parse the stream until the end chunk is found
while (doRead(readChunk, null) >= 0) {
// NOOP: Just consume the input
}
// Return the number of extra bytes which were consumed
return (lastValid - pos);
}
// in java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
protected int readBytes()
throws IOException {
int nRead = buffer.doRead(readChunk, null);
pos = readChunk.getStart();
lastValid = pos + nRead;
buf = readChunk.getBytes();
return nRead;
}
// in java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
protected boolean parseChunkHeader()
throws IOException {
int result = 0;
boolean eol = false;
boolean readDigit = false;
boolean trailer = false;
while (!eol) {
if (pos >= lastValid) {
if (readBytes() <= 0)
return false;
}
if (buf[pos] == Constants.CR) {
// FIXME: Improve parsing to check for CRLF
} else if (buf[pos] == Constants.LF) {
eol = true;
} else if (buf[pos] == Constants.SEMI_COLON) {
trailer = true;
} else if (!trailer) {
//don't read data after the trailer
if (HexUtils.getDec(buf[pos]) != -1) {
readDigit = true;
result *= 16;
result += HexUtils.getDec(buf[pos]);
} else {
//we shouldn't allow invalid, non hex characters
//in the chunked header
return false;
}
}
pos++;
}
if (!readDigit)
return false;
if (result == 0)
endChunk = true;
remaining = result;
if (remaining < 0)
return false;
return true;
}
// in java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
protected boolean parseCRLF()
throws IOException {
boolean eol = false;
boolean crfound = false;
while (!eol) {
if (pos >= lastValid) {
if (readBytes() <= 0)
throw new IOException("Invalid CRLF");
}
if (buf[pos] == Constants.CR) {
if (crfound) throw new IOException("Invalid CRLF, two CR characters encountered.");
crfound = true;
} else if (buf[pos] == Constants.LF) {
if (!crfound) throw new IOException("Invalid CRLF, no CR character encountered.");
eol = true;
} else {
throw new IOException("Invalid CRLF");
}
pos++;
}
return true;
}
// in java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
protected void parseEndChunk() throws IOException {
// Handle option trailer headers
while (parseHeader()) {
// Loop until we run out of headers
}
}
// in java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
private boolean parseHeader() throws IOException {
MimeHeaders headers = request.getMimeHeaders();
byte chr = 0;
while (true) {
// Read new bytes if needed
if (pos >= lastValid) {
if (readBytes() <0)
throw new EOFException("Unexpected end of stream whilst reading trailer headers for chunked request");
}
chr = buf[pos];
if ((chr == Constants.CR) || (chr == Constants.LF)) {
if (chr == Constants.LF) {
pos++;
return false;
}
} else {
break;
}
pos++;
}
// Mark the current buffer position
int start = trailingHeaders.getEnd();
//
// Reading the header name
// Header name is always US-ASCII
//
boolean colon = false;
while (!colon) {
// Read new bytes if needed
if (pos >= lastValid) {
if (readBytes() <0)
throw new EOFException("Unexpected end of stream whilst reading trailer headers for chunked request");
}
chr = buf[pos];
if ((chr >= Constants.A) && (chr <= Constants.Z)) {
chr = (byte) (chr - Constants.LC_OFFSET);
}
if (chr == Constants.COLON) {
colon = true;
} else {
trailingHeaders.append(chr);
}
pos++;
}
MessageBytes headerValue = headers.addValue(trailingHeaders.getBytes(),
start, trailingHeaders.getEnd() - start);
// Mark the current buffer position
start = trailingHeaders.getEnd();
//
// Reading the header value (which can be spanned over multiple lines)
//
boolean eol = false;
boolean validLine = true;
int lastSignificantChar = 0;
while (validLine) {
boolean space = true;
// Skipping spaces
while (space) {
// Read new bytes if needed
if (pos >= lastValid) {
if (readBytes() <0)
throw new EOFException("Unexpected end of stream whilst reading trailer headers for chunked request");
}
chr = buf[pos];
if ((chr == Constants.SP) || (chr == Constants.HT)) {
pos++;
} else {
space = false;
}
}
// Reading bytes until the end of the line
while (!eol) {
// Read new bytes if needed
if (pos >= lastValid) {
if (readBytes() <0)
throw new EOFException("Unexpected end of stream whilst reading trailer headers for chunked request");
}
chr = buf[pos];
if (chr == Constants.CR) {
// Skip
} else if (chr == Constants.LF) {
eol = true;
} else if (chr == Constants.SP) {
trailingHeaders.append(chr);
} else {
trailingHeaders.append(chr);
lastSignificantChar = trailingHeaders.getEnd();
}
pos++;
}
// Checking the first character of the new line. If the character
// is a LWS, then it's a multiline header
// Read new bytes if needed
if (pos >= lastValid) {
if (readBytes() <0)
throw new EOFException("Unexpected end of stream whilst reading trailer headers for chunked request");
}
chr = buf[pos];
if ((chr != Constants.SP) && (chr != Constants.HT)) {
validLine = false;
} else {
eol = false;
// Copying one extra space in the buffer (since there must
// be at least one space inserted between the lines)
trailingHeaders.append(chr);
}
}
// Set the header value
headerValue.setBytes(trailingHeaders.getBytes(), start,
lastSignificantChar - start);
return true;
}
// in java/org/apache/coyote/http11/filters/IdentityInputFilter.java
Override
public int doRead(ByteChunk chunk, Request req)
throws IOException {
int result = -1;
if (contentLength >= 0) {
if (remaining > 0) {
int nRead = buffer.doRead(chunk, req);
if (nRead > remaining) {
// The chunk is longer than the number of bytes remaining
// in the body; changing the chunk length to the number
// of bytes remaining
chunk.setBytes(chunk.getBytes(), chunk.getStart(),
(int) remaining);
result = (int) remaining;
} else {
result = nRead;
}
remaining = remaining - nRead;
} else {
// No more bytes left to be read : return -1 and clear the
// buffer
chunk.recycle();
result = -1;
}
}
return result;
}
// in java/org/apache/coyote/http11/filters/IdentityInputFilter.java
Override
public long end()
throws IOException {
// Consume extra bytes.
while (remaining > 0) {
int nread = buffer.doRead(endChunk, null);
if (nread > 0 ) {
remaining = remaining - nread;
} else { // errors are handled higher up.
remaining = 0;
}
}
// If too many bytes were read, return the amount.
return -remaining;
}
// in java/org/apache/coyote/http11/filters/ChunkedOutputFilter.java
Override
public int doWrite(ByteChunk chunk, Response res)
throws IOException {
int result = chunk.getLength();
if (result <= 0) {
return 0;
}
// Calculate chunk header
int pos = 7;
int current = result;
while (current > 0) {
int digit = current % 16;
current = current / 16;
chunkLength[pos--] = HexUtils.getHex(digit);
}
chunkHeader.setBytes(chunkLength, pos + 1, 9 - pos);
buffer.doWrite(chunkHeader, res);
buffer.doWrite(chunk, res);
chunkHeader.setBytes(chunkLength, 8, 2);
buffer.doWrite(chunkHeader, res);
return result;
}
// in java/org/apache/coyote/http11/filters/ChunkedOutputFilter.java
Override
public long end()
throws IOException {
// Write end chunk
buffer.doWrite(END_CHUNK, null);
return 0;
}
// in java/org/apache/coyote/http11/filters/VoidOutputFilter.java
Override
public int doWrite(ByteChunk chunk, Response res)
throws IOException {
return chunk.getLength();
}
// in java/org/apache/coyote/http11/filters/VoidOutputFilter.java
Override
public long end()
throws IOException {
return 0;
}
// in java/org/apache/coyote/http11/filters/GzipOutputFilter.java
Override
public int doWrite(ByteChunk chunk, Response res)
throws IOException {
if (compressionStream == null) {
compressionStream = new FlushableGZIPOutputStream(fakeOutputStream);
}
compressionStream.write(chunk.getBytes(), chunk.getStart(),
chunk.getLength());
return chunk.getLength();
}
// in java/org/apache/coyote/http11/filters/GzipOutputFilter.java
Override
public long end()
throws IOException {
if (compressionStream == null) {
compressionStream = new FlushableGZIPOutputStream(fakeOutputStream);
}
compressionStream.finish();
compressionStream.close();
return ((OutputFilter) buffer).end();
}
// in java/org/apache/coyote/http11/filters/GzipOutputFilter.java
Override
public void write(int b)
throws IOException {
// Shouldn't get used for good performance, but is needed for
// compatibility with Sun JDK 1.4.0
singleByteBuffer[0] = (byte) (b & 0xff);
outputChunk.setBytes(singleByteBuffer, 0, 1);
buffer.doWrite(outputChunk, null);
}
// in java/org/apache/coyote/http11/filters/GzipOutputFilter.java
Override
public void write(byte[] b, int off, int len)
throws IOException {
outputChunk.setBytes(b, off, len);
buffer.doWrite(outputChunk, null);
}
// in java/org/apache/coyote/http11/filters/GzipOutputFilter.java
Override
public void flush() throws IOException {/*NOOP*/}
// in java/org/apache/coyote/http11/filters/GzipOutputFilter.java
Override
public void close() throws IOException {/*NOOP*/}
// in java/org/apache/coyote/http11/filters/BufferedInputFilter.java
Override
public int doRead(ByteChunk chunk, Request request) throws IOException {
if (hasRead || buffered.getLength() <= 0) {
return -1;
}
chunk.setBytes(buffered.getBytes(), buffered.getStart(),
buffered.getLength());
hasRead = true;
return chunk.getLength();
}
// in java/org/apache/coyote/http11/filters/BufferedInputFilter.java
Override
public long end() throws IOException {
return 0;
}
// in java/org/apache/coyote/http11/filters/FlushableGZIPOutputStream.java
Override
public void write(byte[] bytes) throws IOException {
write(bytes, 0, bytes.length);
}
// in java/org/apache/coyote/http11/filters/FlushableGZIPOutputStream.java
Override
public synchronized void write(byte[] bytes, int offset, int length)
throws IOException {
if (length > 0) {
flushLastByte();
if (length > 1) {
super.write(bytes, offset, length - 1);
}
rememberLastByte(bytes[offset + length - 1]);
}
}
// in java/org/apache/coyote/http11/filters/FlushableGZIPOutputStream.java
Override
public synchronized void write(int i) throws IOException {
flushLastByte();
rememberLastByte((byte) i);
}
// in java/org/apache/coyote/http11/filters/FlushableGZIPOutputStream.java
Override
public synchronized void finish() throws IOException {
try {
flushLastByte();
} catch (IOException ignore) {
// If our write failed, then trailer write in finish() will fail
// with IOException as well, but it will leave Deflater in more
// consistent state.
}
super.finish();
}
// in java/org/apache/coyote/http11/filters/FlushableGZIPOutputStream.java
Override
public synchronized void close() throws IOException {
try {
flushLastByte();
} catch (IOException ignored) {
// Ignore. As OutputStream#close() says, the contract of close()
// is to close the stream. It does not matter much if the
// stream is not writable any more.
}
super.close();
}
// in java/org/apache/coyote/http11/filters/FlushableGZIPOutputStream.java
private void flushLastByte() throws IOException {
if (hasLastByte) {
// Clear the flag first, because write() may fail
hasLastByte = false;
super.write(lastByte, 0, 1);
}
}
// in java/org/apache/coyote/http11/filters/FlushableGZIPOutputStream.java
Override
public synchronized void flush() throws IOException {
if (hasLastByte) {
// - do not allow the gzip header to be flushed on its own
// - do not do anything if there is no data to send
// trick the deflater to flush
/**
* Now this is tricky: We force the Deflater to flush its data by
* switching compression level. As yet, a perplexingly simple workaround
* for
* http://developer.java.sun.com/developer/bugParade/bugs/4255743.html
*/
if (!def.finished()) {
def.setLevel(Deflater.NO_COMPRESSION);
flushLastByte();
def.setLevel(Deflater.DEFAULT_COMPRESSION);
}
}
out.flush();
}
// in java/org/apache/coyote/http11/filters/FlushableGZIPOutputStream.java
Override
protected void deflate() throws IOException {
int len;
do {
len = def.deflate(buf, 0, buf.length);
if (len > 0) {
out.write(buf, 0, len);
}
} while (len != 0);
}
// in java/org/apache/coyote/http11/filters/IdentityOutputFilter.java
Override
public int doWrite(ByteChunk chunk, Response res)
throws IOException {
int result = -1;
if (contentLength >= 0) {
if (remaining > 0) {
result = chunk.getLength();
if (result > remaining) {
// The chunk is longer than the number of bytes remaining
// in the body; changing the chunk length to the number
// of bytes remaining
chunk.setBytes(chunk.getBytes(), chunk.getStart(),
(int) remaining);
result = (int) remaining;
remaining = 0;
} else {
remaining = remaining - result;
}
buffer.doWrite(chunk, res);
} else {
// No more bytes left to be written : return -1 and clear the
// buffer
chunk.recycle();
result = -1;
}
} else {
// If no content length was set, just write the bytes
buffer.doWrite(chunk, res);
result = chunk.getLength();
}
return result;
}
// in java/org/apache/coyote/http11/filters/IdentityOutputFilter.java
Override
public long end()
throws IOException {
if (remaining > 0)
return remaining;
return 0;
}
// in java/org/apache/coyote/http11/filters/VoidInputFilter.java
Override
public int doRead(ByteChunk chunk, Request req)
throws IOException {
return -1;
}
// in java/org/apache/coyote/http11/filters/VoidInputFilter.java
Override
public long end()
throws IOException {
return 0;
}
// in java/org/apache/coyote/http11/AbstractHttp11Processor.java
Override
public SocketState process(SocketWrapper<S> socketWrapper)
throws IOException {
RequestInfo rp = request.getRequestProcessor();
rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);
// Setting up the I/O
setSocketWrapper(socketWrapper);
getInputBuffer().init(socketWrapper, endpoint);
getOutputBuffer().init(socketWrapper, endpoint);
// Flags
error = false;
keepAlive = true;
comet = false;
openSocket = false;
sendfileInProgress = false;
readComplete = true;
if (endpoint.getUsePolling()) {
keptAlive = false;
} else {
keptAlive = socketWrapper.isKeptAlive();
}
if (disableKeepAlive()) {
socketWrapper.setKeepAliveLeft(0);
}
while (!error && keepAlive && !comet && !isAsync() &&
upgradeInbound == null && !endpoint.isPaused()) {
// Parsing the request header
try {
setRequestLineReadTimeout();
if (!getInputBuffer().parseRequestLine(keptAlive)) {
if (handleIncompleteRequestLineRead()) {
break;
}
}
if (endpoint.isPaused()) {
// 503 - Service unavailable
response.setStatus(503);
error = true;
} else {
request.setStartTime(System.currentTimeMillis());
keptAlive = true;
// Currently only NIO will ever return false here
if (!getInputBuffer().parseHeaders()) {
// We've read part of the request, don't recycle it
// instead associate it with the socket
openSocket = true;
readComplete = false;
break;
}
if (!disableUploadTimeout) {
setSocketTimeout(connectionUploadTimeout);
}
}
} catch (IOException e) {
if (getLog().isDebugEnabled()) {
getLog().debug(
sm.getString("http11processor.header.parse"), e);
}
error = true;
break;
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
if (getLog().isDebugEnabled()) {
getLog().debug(
sm.getString("http11processor.header.parse"), t);
}
// 400 - Bad Request
response.setStatus(400);
adapter.log(request, response, 0);
error = true;
}
if (!error) {
// Setting up filters, and parse some request headers
rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
try {
prepareRequest();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
if (getLog().isDebugEnabled()) {
getLog().debug(sm.getString(
"http11processor.request.prepare"), t);
}
// 400 - Internal Server Error
response.setStatus(400);
adapter.log(request, response, 0);
error = true;
}
}
if (maxKeepAliveRequests == 1) {
keepAlive = false;
} else if (maxKeepAliveRequests > 0 &&
socketWrapper.decrementKeepAlive() <= 0) {
keepAlive = false;
}
// Process the request in the adapter
if (!error) {
try {
rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
adapter.service(request, response);
// Handle when the response was committed before a serious
// error occurred. Throwing a ServletException should both
// set the status to 500 and set the errorException.
// If we fail here, then the response is likely already
// committed, so we can't try and set headers.
if(keepAlive && !error) { // Avoid checking twice.
error = response.getErrorException() != null ||
(!isAsync() &&
statusDropsConnection(response.getStatus()));
}
setCometTimeouts(socketWrapper);
} catch (InterruptedIOException e) {
error = true;
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
getLog().error(sm.getString(
"http11processor.request.process"), t);
// 500 - Internal Server Error
response.setStatus(500);
adapter.log(request, response, 0);
error = true;
}
}
// Finish the handling of the request
rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT);
if (!isAsync() && !comet) {
if (error) {
// If we know we are closing the connection, don't drain
// input. This way uploading a 100GB file doesn't tie up the
// thread if the servlet has rejected it.
getInputBuffer().setSwallowInput(false);
}
endRequest();
}
rp.setStage(org.apache.coyote.Constants.STAGE_ENDOUTPUT);
// If there was an error, make sure the request is counted as
// and error, and update the statistics counter
if (error) {
response.setStatus(500);
}
request.updateCounters();
if (!isAsync() && !comet || error) {
getInputBuffer().nextRequest();
getOutputBuffer().nextRequest();
}
if (!disableUploadTimeout) {
setSocketTimeout(endpoint.getSoTimeout());
}
rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
if (breakKeepAliveLoop(socketWrapper)) {
break;
}
}
rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
if (error || endpoint.isPaused()) {
return SocketState.CLOSED;
} else if (isAsync() || comet) {
return SocketState.LONG;
} else if (isUpgrade()) {
return SocketState.UPGRADING;
} else {
if (sendfileInProgress) {
return SocketState.SENDFILE;
} else {
if (openSocket) {
if (readComplete) {
return SocketState.OPEN;
} else {
return SocketState.LONG;
}
} else {
return SocketState.CLOSED;
}
}
}
}
// in java/org/apache/coyote/http11/AbstractHttp11Processor.java
Override
public SocketState upgradeDispatch() throws IOException {
// Should never reach this code but in case we do...
// TODO
throw new IOException(
sm.getString("TODO"));
}
// in java/org/apache/coyote/http11/Http11Protocol.java
Override
protected Processor<Socket> createUpgradeProcessor(
SocketWrapper<Socket> socket, UpgradeInbound inbound)
throws IOException {
return new UpgradeBioProcessor(socket, inbound);
}
// in java/org/apache/coyote/http11/InternalInputBuffer.java
Override
public boolean parseRequestLine(boolean useAvailableDataOnly)
throws IOException {
int start = 0;
//
// Skipping blank lines
//
byte chr = 0;
do {
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill())
throw new EOFException(sm.getString("iib.eof.error"));
}
chr = buf[pos++];
} while ((chr == Constants.CR) || (chr == Constants.LF));
pos--;
// Mark the current buffer position
start = pos;
//
// Reading the method name
// Method name is always US-ASCII
//
boolean space = false;
while (!space) {
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill())
throw new EOFException(sm.getString("iib.eof.error"));
}
// Spec says no CR or LF in method name
if (buf[pos] == Constants.CR || buf[pos] == Constants.LF) {
throw new IllegalArgumentException(
sm.getString("iib.invalidmethod"));
}
// Spec says single SP but it also says be tolerant of HT
if (buf[pos] == Constants.SP || buf[pos] == Constants.HT) {
space = true;
request.method().setBytes(buf, start, pos - start);
}
pos++;
}
// Spec says single SP but also says be tolerant of multiple and/or HT
while (space) {
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill())
throw new EOFException(sm.getString("iib.eof.error"));
}
if (buf[pos] == Constants.SP || buf[pos] == Constants.HT) {
pos++;
} else {
space = false;
}
}
// Mark the current buffer position
start = pos;
int end = 0;
int questionPos = -1;
//
// Reading the URI
//
boolean eol = false;
while (!space) {
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill())
throw new EOFException(sm.getString("iib.eof.error"));
}
// Spec says single SP but it also says be tolerant of HT
if (buf[pos] == Constants.SP || buf[pos] == Constants.HT) {
space = true;
end = pos;
} else if ((buf[pos] == Constants.CR)
|| (buf[pos] == Constants.LF)) {
// HTTP/0.9 style request
eol = true;
space = true;
end = pos;
} else if ((buf[pos] == Constants.QUESTION)
&& (questionPos == -1)) {
questionPos = pos;
}
pos++;
}
request.unparsedURI().setBytes(buf, start, end - start);
if (questionPos >= 0) {
request.queryString().setBytes(buf, questionPos + 1,
end - questionPos - 1);
request.requestURI().setBytes(buf, start, questionPos - start);
} else {
request.requestURI().setBytes(buf, start, end - start);
}
// Spec says single SP but also says be tolerant of multiple and/or HT
while (space) {
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill())
throw new EOFException(sm.getString("iib.eof.error"));
}
if (buf[pos] == Constants.SP || buf[pos] == Constants.HT) {
pos++;
} else {
space = false;
}
}
// Mark the current buffer position
start = pos;
end = 0;
//
// Reading the protocol
// Protocol is always US-ASCII
//
while (!eol) {
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill())
throw new EOFException(sm.getString("iib.eof.error"));
}
if (buf[pos] == Constants.CR) {
end = pos;
} else if (buf[pos] == Constants.LF) {
if (end == 0)
end = pos;
eol = true;
}
pos++;
}
if ((end - start) > 0) {
request.protocol().setBytes(buf, start, end - start);
} else {
request.protocol().setString("");
}
return true;
}
// in java/org/apache/coyote/http11/InternalInputBuffer.java
Override
public boolean parseHeaders()
throws IOException {
if (!parsingHeader) {
throw new IllegalStateException(
sm.getString("iib.parseheaders.ise.error"));
}
while (parseHeader()) {
// Loop until we run out of headers
}
parsingHeader = false;
end = pos;
return true;
}
// in java/org/apache/coyote/http11/InternalInputBuffer.java
Override
protected void init(SocketWrapper<Socket> socketWrapper,
AbstractEndpoint endpoint) throws IOException {
inputStream = socketWrapper.getSocket().getInputStream();
}
// in java/org/apache/coyote/http11/InternalInputBuffer.java
private void skipLine(int start) throws IOException {
boolean eol = false;
int lastRealByte = start;
if (pos - 1 > start) {
lastRealByte = pos - 1;
}
while (!eol) {
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill())
throw new EOFException(sm.getString("iib.eof.error"));
}
if (buf[pos] == Constants.CR) {
// Skip
} else if (buf[pos] == Constants.LF) {
eol = true;
} else {
lastRealByte = pos;
}
pos++;
}
if (log.isDebugEnabled()) {
log.debug(sm.getString("iib.invalidheader", new String(buf, start,
lastRealByte - start + 1, Charset.forName("ISO-8859-1"))));
}
}
// in java/org/apache/coyote/http11/InternalInputBuffer.java
protected boolean fill() throws IOException {
return fill(true);
}
// in java/org/apache/coyote/http11/InternalInputBuffer.java
Override
protected boolean fill(boolean block) throws IOException {
int nRead = 0;
if (parsingHeader) {
if (lastValid == buf.length) {
throw new IllegalArgumentException
(sm.getString("iib.requestheadertoolarge.error"));
}
nRead = inputStream.read(buf, pos, buf.length - lastValid);
if (nRead > 0) {
lastValid = pos + nRead;
}
} else {
if (buf.length - end < 4500) {
// In this case, the request header was really large, so we allocate a
// brand new one; the old one will get GCed when subsequent requests
// clear all references
buf = new byte[buf.length];
end = 0;
}
pos = end;
lastValid = pos;
nRead = inputStream.read(buf, pos, buf.length - lastValid);
if (nRead > 0) {
lastValid = pos + nRead;
}
}
return (nRead > 0);
}
// in java/org/apache/coyote/http11/InternalInputBuffer.java
Override
public int doRead(ByteChunk chunk, Request req )
throws IOException {
if (pos >= lastValid) {
if (!fill())
return -1;
}
int length = lastValid - pos;
chunk.setBytes(buf, pos, length);
pos = lastValid;
return (length);
}
// in java/org/apache/coyote/http11/Http11Processor.java
Override
protected void setRequestLineReadTimeout() throws IOException {
/*
* When there is no data in the buffer and this is not the first
* request on this connection and timeouts are being used the
* first read for this request may need a different timeout to
* take account of time spent waiting for a processing thread.
*
* This is a little hacky but better than exposing the socket
* and the timeout info to the InputBuffer
*/
if (inputBuffer.lastValid == 0 && socket.getLastAccess() > -1) {
int firstReadTimeout;
if (keepAliveTimeout == -1) {
firstReadTimeout = 0;
} else {
long queueTime =
System.currentTimeMillis() - socket.getLastAccess();
if (queueTime >= keepAliveTimeout) {
// Queued for longer than timeout but there might be
// data so use shortest possible timeout
firstReadTimeout = 1;
} else {
// Cast is safe since queueTime must be less than
// keepAliveTimeout which is an int
firstReadTimeout = keepAliveTimeout - (int) queueTime;
}
}
socket.getSocket().setSoTimeout(firstReadTimeout);
if (!inputBuffer.fill()) {
throw new EOFException(sm.getString("iib.eof.error"));
}
// Once the first byte has been read, the standard timeout should be
// used so restore it here.
socket.getSocket().setSoTimeout(endpoint.getSoTimeout());
}
}
// in java/org/apache/coyote/http11/Http11Processor.java
Override
protected void setSocketTimeout(int timeout) throws IOException {
socket.getSocket().setSoTimeout(timeout);
}
// in java/org/apache/coyote/http11/Http11Processor.java
Override
public SocketState event(SocketStatus status) throws IOException {
// Should never reach this code but in case we do...
throw new IOException(
sm.getString("http11processor.comet.notsupported"));
}
// in java/org/apache/coyote/http11/InternalAprOutputBuffer.java
Override
public void init(SocketWrapper<Long> socketWrapper,
AbstractEndpoint endpoint) throws IOException {
socket = socketWrapper.getSocket().longValue();
Socket.setsbb(this.socket, bbuf);
}
// in java/org/apache/coyote/http11/InternalAprOutputBuffer.java
Override
public void flush()
throws IOException {
super.flush();
// Flush the current buffer
flushBuffer();
}
// in java/org/apache/coyote/http11/InternalAprOutputBuffer.java
Override
public void endRequest()
throws IOException {
if (!committed) {
// Send the connector a request for commit. The connector should
// then validate the headers, send them (using sendHeader) and
// set the filters accordingly.
response.action(ActionCode.COMMIT, null);
}
if (finished)
return;
if (lastActiveFilter != -1)
activeFilters[lastActiveFilter].end();
flushBuffer();
finished = true;
}
// in java/org/apache/coyote/http11/InternalAprOutputBuffer.java
Override
public void sendAck()
throws IOException {
if (!committed) {
if (Socket.send(socket, Constants.ACK_BYTES, 0, Constants.ACK_BYTES.length) < 0)
throw new IOException(sm.getString("iib.failedwrite"));
}
}
// in java/org/apache/coyote/http11/InternalAprOutputBuffer.java
Override
protected void commit() throws IOException {
// The response is now committed
committed = true;
response.setCommitted(true);
if (pos > 0) {
// Sending the response header buffer
bbuf.put(buf, 0, pos);
}
}
// in java/org/apache/coyote/http11/InternalAprOutputBuffer.java
private void flushBuffer()
throws IOException {
if (bbuf.position() > 0) {
if (Socket.sendbb(socket, 0, bbuf.position()) < 0) {
throw new IOException();
}
bbuf.clear();
}
}
// in java/org/apache/coyote/http11/InternalAprOutputBuffer.java
Override
public int doWrite(ByteChunk chunk, Response res)
throws IOException {
int len = chunk.getLength();
int start = chunk.getStart();
byte[] b = chunk.getBuffer();
while (len > 0) {
int thisTime = len;
if (bbuf.position() == bbuf.capacity()) {
flushBuffer();
}
if (thisTime > bbuf.capacity() - bbuf.position()) {
thisTime = bbuf.capacity() - bbuf.position();
}
bbuf.put(b, start, thisTime);
len = len - thisTime;
start = start + thisTime;
}
byteCount += chunk.getLength();
return chunk.getLength();
}
// in java/org/apache/coyote/http11/InternalAprInputBuffer.java
Override
public boolean parseRequestLine(boolean useAvailableData)
throws IOException {
int start = 0;
//
// Skipping blank lines
//
byte chr = 0;
do {
// Read new bytes if needed
if (pos >= lastValid) {
if (useAvailableData) {
return false;
}
if (!fill())
throw new EOFException(sm.getString("iib.eof.error"));
}
chr = buf[pos++];
} while ((chr == Constants.CR) || (chr == Constants.LF));
pos--;
// Mark the current buffer position
start = pos;
if (pos >= lastValid) {
if (useAvailableData) {
return false;
}
if (!fill())
throw new EOFException(sm.getString("iib.eof.error"));
}
//
// Reading the method name
// Method name is always US-ASCII
//
boolean space = false;
while (!space) {
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill())
throw new EOFException(sm.getString("iib.eof.error"));
}
// Spec says no CR or LF in method name
if (buf[pos] == Constants.CR || buf[pos] == Constants.LF) {
throw new IllegalArgumentException(
sm.getString("iib.invalidmethod"));
}
// Spec says single SP but it also says be tolerant of HT
if (buf[pos] == Constants.SP || buf[pos] == Constants.HT) {
space = true;
request.method().setBytes(buf, start, pos - start);
}
pos++;
}
// Spec says single SP but also says be tolerant of multiple and/or HT
while (space) {
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill())
throw new EOFException(sm.getString("iib.eof.error"));
}
if (buf[pos] == Constants.SP || buf[pos] == Constants.HT) {
pos++;
} else {
space = false;
}
}
// Mark the current buffer position
start = pos;
int end = 0;
int questionPos = -1;
//
// Reading the URI
//
boolean eol = false;
while (!space) {
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill())
throw new EOFException(sm.getString("iib.eof.error"));
}
// Spec says single SP but it also says be tolerant of HT
if (buf[pos] == Constants.SP || buf[pos] == Constants.HT) {
space = true;
end = pos;
} else if ((buf[pos] == Constants.CR)
|| (buf[pos] == Constants.LF)) {
// HTTP/0.9 style request
eol = true;
space = true;
end = pos;
} else if ((buf[pos] == Constants.QUESTION)
&& (questionPos == -1)) {
questionPos = pos;
}
pos++;
}
request.unparsedURI().setBytes(buf, start, end - start);
if (questionPos >= 0) {
request.queryString().setBytes(buf, questionPos + 1,
end - questionPos - 1);
request.requestURI().setBytes(buf, start, questionPos - start);
} else {
request.requestURI().setBytes(buf, start, end - start);
}
// Spec says single SP but also says be tolerant of multiple and/or HT
while (space) {
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill())
throw new EOFException(sm.getString("iib.eof.error"));
}
if (buf[pos] == Constants.SP || buf[pos] == Constants.HT) {
pos++;
} else {
space = false;
}
}
// Mark the current buffer position
start = pos;
end = 0;
//
// Reading the protocol
// Protocol is always US-ASCII
//
while (!eol) {
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill())
throw new EOFException(sm.getString("iib.eof.error"));
}
if (buf[pos] == Constants.CR) {
end = pos;
} else if (buf[pos] == Constants.LF) {
if (end == 0)
end = pos;
eol = true;
}
pos++;
}
if ((end - start) > 0) {
request.protocol().setBytes(buf, start, end - start);
} else {
request.protocol().setString("");
}
return true;
}
// in java/org/apache/coyote/http11/InternalAprInputBuffer.java
Override
public boolean parseHeaders()
throws IOException {
if (!parsingHeader) {
throw new IllegalStateException(
sm.getString("iib.parseheaders.ise.error"));
}
while (parseHeader()) {
// Loop until there are no more headers
}
parsingHeader = false;
end = pos;
return true;
}
// in java/org/apache/coyote/http11/InternalAprInputBuffer.java
private void skipLine(int start) throws IOException {
boolean eol = false;
int lastRealByte = start;
if (pos - 1 > start) {
lastRealByte = pos - 1;
}
while (!eol) {
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill())
throw new EOFException(sm.getString("iib.eof.error"));
}
if (buf[pos] == Constants.CR) {
// Skip
} else if (buf[pos] == Constants.LF) {
eol = true;
} else {
lastRealByte = pos;
}
pos++;
}
if (log.isDebugEnabled()) {
log.debug(sm.getString("iib.invalidheader", new String(buf, start,
lastRealByte - start + 1, Charset.forName("ISO-8859-1"))));
}
}
// in java/org/apache/coyote/http11/InternalAprInputBuffer.java
Override
public int doRead(ByteChunk chunk, Request req)
throws IOException {
if (lastActiveFilter == -1)
return inputStreamInputBuffer.doRead(chunk, req);
else
return activeFilters[lastActiveFilter].doRead(chunk,req);
}
// in java/org/apache/coyote/http11/InternalAprInputBuffer.java
Override
protected void init(SocketWrapper<Long> socketWrapper,
AbstractEndpoint endpoint) throws IOException {
socket = socketWrapper.getSocket().longValue();
Socket.setrbb(this.socket, bbuf);
}
// in java/org/apache/coyote/http11/InternalAprInputBuffer.java
Override
protected boolean fill(boolean block) throws IOException {
// Ignore the block parameter and just call fill
return fill();
}
// in java/org/apache/coyote/http11/InternalAprInputBuffer.java
protected boolean fill()
throws IOException {
int nRead = 0;
if (parsingHeader) {
if (lastValid == buf.length) {
throw new IllegalArgumentException
(sm.getString("iib.requestheadertoolarge.error"));
}
bbuf.clear();
nRead = Socket.recvbb(socket, 0, buf.length - lastValid);
if (nRead > 0) {
bbuf.limit(nRead);
bbuf.get(buf, pos, nRead);
lastValid = pos + nRead;
} else {
if ((-nRead) == Status.EAGAIN) {
return false;
} else {
throw new IOException(sm.getString("iib.failedread"));
}
}
} else {
if (buf.length - end < 4500) {
// In this case, the request header was really large, so we allocate a
// brand new one; the old one will get GCed when subsequent requests
// clear all references
buf = new byte[buf.length];
end = 0;
}
pos = end;
lastValid = pos;
bbuf.clear();
nRead = Socket.recvbb(socket, 0, buf.length - lastValid);
if (nRead > 0) {
bbuf.limit(nRead);
bbuf.get(buf, pos, nRead);
lastValid = pos + nRead;
} else {
if ((-nRead) == Status.ETIMEDOUT || (-nRead) == Status.TIMEUP) {
throw new SocketTimeoutException(sm.getString("iib.failedread"));
} else if (nRead == 0) {
// APR_STATUS_IS_EOF, since native 1.1.22
return false;
} else {
throw new IOException(sm.getString("iib.failedread"));
}
}
}
return (nRead > 0);
}
// in java/org/apache/coyote/http11/InternalAprInputBuffer.java
Override
public int doRead(ByteChunk chunk, Request req )
throws IOException {
if (pos >= lastValid) {
if (!fill())
return -1;
}
int length = lastValid - pos;
chunk.setBytes(buf, pos, length);
pos = lastValid;
return (length);
}
// in java/org/apache/coyote/http11/AbstractInputBuffer.java
public void endRequest()
throws IOException {
if (swallowInput && (lastActiveFilter != -1)) {
int extraBytes = (int) activeFilters[lastActiveFilter].end();
pos = pos - extraBytes;
}
}
// in java/org/apache/coyote/http11/AbstractInputBuffer.java
Override
public int doRead(ByteChunk chunk, Request req)
throws IOException {
if (lastActiveFilter == -1)
return inputStreamInputBuffer.doRead(chunk, req);
else
return activeFilters[lastActiveFilter].doRead(chunk,req);
}
// in java/org/apache/coyote/http11/InternalNioOutputBuffer.java
Override
public void flush() throws IOException {
super.flush();
// Flush the current buffer
flushBuffer();
}
// in java/org/apache/coyote/http11/InternalNioOutputBuffer.java
Override
public void endRequest() throws IOException {
super.endRequest();
flushBuffer();
}
// in java/org/apache/coyote/http11/InternalNioOutputBuffer.java
Override
public void sendAck() throws IOException {
if (!committed) {
//Socket.send(socket, Constants.ACK_BYTES, 0, Constants.ACK_BYTES.length) < 0
socket.getBufHandler() .getWriteBuffer().put(Constants.ACK_BYTES,0,Constants.ACK_BYTES.length);
writeToSocket(socket.getBufHandler() .getWriteBuffer(),true,true);
}
}
// in java/org/apache/coyote/http11/InternalNioOutputBuffer.java
private synchronized int writeToSocket(ByteBuffer bytebuffer, boolean block, boolean flip) throws IOException {
if ( flip ) bytebuffer.flip();
int written = 0;
NioEndpoint.KeyAttachment att = (NioEndpoint.KeyAttachment)socket.getAttachment(false);
if ( att == null ) throw new IOException("Key must be cancelled");
long writeTimeout = att.getTimeout();
Selector selector = null;
try {
selector = pool.get();
} catch ( IOException x ) {
//ignore
}
try {
written = pool.write(bytebuffer, socket, selector, writeTimeout, block);
//make sure we are flushed
do {
if (socket.flush(true,selector,writeTimeout)) break;
}while ( true );
}finally {
if ( selector != null ) pool.put(selector);
}
if ( block ) bytebuffer.clear(); //only clear
return written;
}
// in java/org/apache/coyote/http11/InternalNioOutputBuffer.java
Override
public void init(SocketWrapper<NioChannel> socketWrapper,
AbstractEndpoint endpoint) throws IOException {
socket = socketWrapper.getSocket();
pool = ((NioEndpoint)endpoint).getSelectorPool();
}
// in java/org/apache/coyote/http11/InternalNioOutputBuffer.java
Override
protected void commit()
throws IOException {
// The response is now committed
committed = true;
response.setCommitted(true);
if (pos > 0) {
// Sending the response header buffer
addToBB(buf, 0, pos);
}
}
// in java/org/apache/coyote/http11/InternalNioOutputBuffer.java
private synchronized void addToBB(byte[] buf, int offset, int length) throws IOException {
while (length > 0) {
int thisTime = length;
if (socket.getBufHandler().getWriteBuffer().position() ==
socket.getBufHandler().getWriteBuffer().capacity()
|| socket.getBufHandler().getWriteBuffer().remaining()==0) {
flushBuffer();
}
if (thisTime > socket.getBufHandler().getWriteBuffer().remaining()) {
thisTime = socket.getBufHandler().getWriteBuffer().remaining();
}
socket.getBufHandler().getWriteBuffer().put(buf, offset, thisTime);
length = length - thisTime;
offset = offset + thisTime;
}
NioEndpoint.KeyAttachment ka = (NioEndpoint.KeyAttachment)socket.getAttachment(false);
if ( ka!= null ) ka.access();//prevent timeouts for just doing client writes
}
// in java/org/apache/coyote/http11/InternalNioOutputBuffer.java
private void flushBuffer() throws IOException {
//prevent timeout for async,
SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector());
if (key != null) {
NioEndpoint.KeyAttachment attach = (NioEndpoint.KeyAttachment) key.attachment();
attach.access();
}
//write to the socket, if there is anything to write
if (socket.getBufHandler().getWriteBuffer().position() > 0) {
socket.getBufHandler().getWriteBuffer().flip();
writeToSocket(socket.getBufHandler().getWriteBuffer(),true, false);
}
}
// in java/org/apache/coyote/http11/InternalNioOutputBuffer.java
Override
public int doWrite(ByteChunk chunk, Response res)
throws IOException {
int len = chunk.getLength();
int start = chunk.getStart();
byte[] b = chunk.getBuffer();
addToBB(b, start, len);
byteCount += chunk.getLength();
return chunk.getLength();
}
// in java/org/apache/coyote/http11/AbstractOutputBuffer.java
Override
public int doWrite(ByteChunk chunk, Response res)
throws IOException {
if (!committed) {
// Send the connector a request for commit. The connector should
// then validate the headers, send them (using sendHeaders) and
// set the filters accordingly.
response.action(ActionCode.COMMIT, null);
}
if (lastActiveFilter == -1)
return outputStreamOutputBuffer.doWrite(chunk, res);
else
return activeFilters[lastActiveFilter].doWrite(chunk, res);
}
// in java/org/apache/coyote/http11/AbstractOutputBuffer.java
public void flush()
throws IOException {
if (!committed) {
// Send the connector a request for commit. The connector should
// then validate the headers, send them (using sendHeader) and
// set the filters accordingly.
response.action(ActionCode.COMMIT, null);
}
// go through the filters and if there is gzip filter
// invoke it to flush
for (int i = 0; i <= lastActiveFilter; i++) {
if (activeFilters[i] instanceof GzipOutputFilter) {
if (log.isDebugEnabled()) {
log.debug("Flushing the gzip filter at position " + i +
" of the filter chain...");
}
((GzipOutputFilter) activeFilters[i]).flush();
break;
}
}
}
// in java/org/apache/coyote/http11/AbstractOutputBuffer.java
public void endRequest()
throws IOException {
if (!committed) {
// Send the connector a request for commit. The connector should
// then validate the headers, send them (using sendHeader) and
// set the filters accordingly.
response.action(ActionCode.COMMIT, null);
}
if (finished)
return;
if (lastActiveFilter != -1)
activeFilters[lastActiveFilter].end();
finished = true;
}
// in java/org/apache/coyote/http11/Http11AprProtocol.java
Override
protected Processor<Long> createUpgradeProcessor(
SocketWrapper<Long> socket, UpgradeInbound inbound)
throws IOException {
return new UpgradeAprProcessor(socket, inbound);
}
// in java/org/apache/coyote/spdy/SpdyAprNpnHandler.java
Override
public void init(final AbstractEndpoint ep, long sslContext,
final Adapter adapter) {
spdyContext = new SpdyContext();
if (sslContext == 0) {
// Apr endpoint without SSL - proxy mode.
spdyContext.setTlsComprression(false, false);
return;
}
if (0 != SSLExt.setNPN(sslContext, SpdyContext.SPDY_NPN_OUT)) {
log.warn("SPDY/NPN not supported");
}
spdyContext.setNetSupport(new NetSupportOpenSSL());
spdyContext.setExecutor(ep.getExecutor());
spdyContext.setHandler(new SpdyHandler() {
@Override
public void onStream(SpdyConnection con, SpdyStream ch)
throws IOException {
SpdyProcessor sp = new SpdyProcessor(con, ep);
sp.setAdapter(adapter);
sp.onSynStream(ch);
}
});
}
// in java/org/apache/coyote/spdy/SpdyAprNpnHandler.java
Override
public void onStream(SpdyConnection con, SpdyStream ch)
throws IOException {
SpdyProcessor sp = new SpdyProcessor(con, ep);
sp.setAdapter(adapter);
sp.onSynStream(ch);
}
// in java/org/apache/coyote/spdy/SpdyProcessor.java
Override
public int doRead(ByteChunk bchunk, Request request) throws IOException {
if (inFrame == null) {
// blocking
inFrame = spdyStream.getDataFrame(endpoint.getSoTimeout());
}
if (inFrame == null) {
return -1; // timeout
}
if (inFrame.remaining() == 0 && inFrame.isHalfClose()) {
return -1;
}
int rd = Math.min(inFrame.remaining(), bchunk.getBytes().length);
System.arraycopy(inFrame.data, inFrame.off, bchunk.getBytes(),
bchunk.getStart(), rd);
inFrame.advance(rd);
if (inFrame.remaining() == 0) {
spdy.getSpdyContext().releaseFrame(inFrame);
if (!inFrame.isHalfClose()) {
inFrame = null;
}
}
bchunk.setEnd(bchunk.getEnd() + rd);
return rd;
}
// in java/org/apache/coyote/spdy/SpdyProcessor.java
Override
public int doWrite(org.apache.tomcat.util.buf.ByteChunk chunk,
Response response) throws IOException {
if (!response.isCommitted()) {
// Send the connector a request for commit. The connector should
// then validate the headers, send them (using sendHeader) and
// set the filters accordingly.
response.action(ActionCode.COMMIT, null);
}
spdyStream.sendDataFrame(chunk.getBuffer(), chunk.getStart(),
chunk.getLength(), false);
byteCount += chunk.getLength();
return chunk.getLength();
}
// in java/org/apache/coyote/spdy/SpdyProcessor.java
protected void sendSynReply() throws IOException {
response.setCommitted(true);
// Special headers
MimeHeaders headers = response.getMimeHeaders();
String contentType = response.getContentType();
if (contentType != null) {
headers.setValue("Content-Type").setString(contentType);
}
String contentLanguage = response.getContentLanguage();
if (contentLanguage != null) {
headers.setValue("Content-Language").setString(contentLanguage);
}
long contentLength = response.getContentLengthLong();
if (contentLength >= 0) {
headers.setValue("Content-Length").setLong(contentLength);
}
sendResponseHead();
}
// in java/org/apache/coyote/spdy/SpdyProcessor.java
private void sendResponseHead() throws IOException {
SpdyFrame rframe = spdy.getFrame(SpdyConnection.TYPE_SYN_REPLY);
rframe.associated = 0;
MimeHeaders headers = response.getMimeHeaders();
for (int i = 0; i < headers.size(); i++) {
MessageBytes mb = headers.getName(i);
mb.toBytes();
ByteChunk bc = mb.getByteChunk();
byte[] bb = bc.getBuffer();
for (int j = bc.getStart(); j < bc.getEnd(); j++) {
bb[j] = (byte) Ascii.toLower(bb[j]);
}
// TODO: filter headers: Connection, Keep-Alive, Proxy-Connection,
rframe.headerName(bc.getBuffer(), bc.getStart(), bc.getLength());
mb = headers.getValue(i);
mb.toBytes();
bc = mb.getByteChunk();
rframe.headerValue(bc.getBuffer(), bc.getStart(), bc.getLength());
}
if (response.getStatus() == 0) {
rframe.addHeader(SpdyFrame.STATUS, SpdyFrame.OK200);
} else {
// HTTP header contents
String message = null;
if (org.apache.coyote.Constants.USE_CUSTOM_STATUS_MSG_IN_HEADER
&& HttpMessages.isSafeInHttpHeader(response.getMessage())) {
message = response.getMessage();
}
if (message == null) {
message = HttpMessages.getMessage(response.getStatus());
}
if (message == null) {
// mod_jk + httpd 2.x fails with a null status message - bug
// 45026
message = Integer.toString(response.getStatus());
}
// TODO: optimize
String status = response.getStatus() + " " + message;
byte[] statusB = status.getBytes();
rframe.headerName(SpdyFrame.STATUS, 0, SpdyFrame.STATUS.length);
rframe.headerValue(statusB, 0, statusB.length);
}
rframe.addHeader(SpdyFrame.VERSION, SpdyFrame.HTTP11);
rframe.streamId = spdyStream.reqFrame.streamId;
spdy.send(rframe, spdyStream);
// we can't reuse the frame - it'll be queued, the coyote processor
// may be reused as well.
outCommit = true;
}
// in java/org/apache/coyote/spdy/SpdyProcessor.java
Override
public SocketState process(SocketWrapper<Object> socket)
throws IOException {
throw new IOException("Unimplemented");
}
// in java/org/apache/coyote/spdy/SpdyProcessor.java
Override
public SocketState event(SocketStatus status) throws IOException {
System.err.println("EVENT: " + status);
return null;
}
// in java/org/apache/coyote/spdy/SpdyProcessor.java
Override
public SocketState upgradeDispatch() throws IOException {
return null;
}
// in java/org/apache/coyote/spdy/SpdyProcessor.java
public void onSynStream(SpdyStream str) throws IOException {
this.spdyStream = str;
SpdyFrame frame = str.reqFrame;
// We need to make a copy - the frame buffer will be reused.
// We use the 'wrap' methods of MimeHeaders - which should be
// lighter on mem in some cases.
RequestInfo rp = request.getRequestProcessor();
rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
// Request received.
MimeHeaders mimeHeaders = request.getMimeHeaders();
for (int i = 0; i < frame.nvCount; i++) {
int nameLen = frame.read16();
if (nameLen > frame.remaining()) {
throw new IOException("Name too long");
}
keyBuffer.setBytes(frame.data, frame.off, nameLen);
if (keyBuffer.equals("method")) {
frame.advance(nameLen);
int valueLen = frame.read16();
if (valueLen > frame.remaining()) {
throw new IOException("Name too long");
}
request.method().setBytes(frame.data, frame.off, valueLen);
frame.advance(valueLen);
} else if (keyBuffer.equals("url")) {
frame.advance(nameLen);
int valueLen = frame.read16();
if (valueLen > frame.remaining()) {
throw new IOException("Name too long");
}
request.requestURI().setBytes(frame.data, frame.off, valueLen);
if (SpdyContext.debug) {
System.err.println("URL= " + request.requestURI());
}
frame.advance(valueLen);
} else if (keyBuffer.equals("version")) {
frame.advance(nameLen);
int valueLen = frame.read16();
if (valueLen > frame.remaining()) {
throw new IOException("Name too long");
}
frame.advance(valueLen);
} else {
MessageBytes value = mimeHeaders.addValue(frame.data,
frame.off, nameLen);
frame.advance(nameLen);
int valueLen = frame.read16();
if (valueLen > frame.remaining()) {
throw new IOException("Name too long");
}
value.setBytes(frame.data, frame.off, valueLen);
frame.advance(valueLen);
}
}
onRequest();
}
// in java/org/apache/coyote/spdy/SpdyProxyProtocol.java
Override
public void start() throws Exception {
super.start();
spdyContext = new SpdyContext();
spdyContext.setTlsComprression(false, false);
spdyContext.setHandler(new SpdyHandler() {
@Override
public void onStream(SpdyConnection con, SpdyStream ch) throws IOException {
SpdyProcessor sp = new SpdyProcessor(con, endpoint);
sp.setAdapter(adapter);
sp.onSynStream(ch);
}
});
spdyContext.setNetSupport(new NetSupportSocket());
spdyContext.setExecutor(endpoint.getExecutor());
}
// in java/org/apache/coyote/spdy/SpdyProxyProtocol.java
Override
public void onStream(SpdyConnection con, SpdyStream ch) throws IOException {
SpdyProcessor sp = new SpdyProcessor(con, endpoint);
sp.setAdapter(adapter);
sp.onSynStream(ch);
}
// in java/org/apache/tomcat/jni/socket/AprSocketContext.java
public AprSocketContext setKeys(String certPemFile, String keyDerFile)
throws IOException {
this.sslMode = true;
setTls();
certFile = certPemFile;
keyFile = keyDerFile;
return this;
}
// in java/org/apache/tomcat/jni/socket/AprSocketContext.java
public void listen(final int port) throws IOException {
if (acceptor != null) {
throw new IOException("Already accepting on " + acceptor.port);
}
if (sslMode && certFile == null) {
throw new IOException("Missing certificates for server");
}
if (sslMode || !nonBlockingAccept) {
acceptorDispatch = new AcceptorDispatchThread(port);
acceptorDispatch.setName("AprAcceptorDispatch-" + port);
acceptorDispatch.start();
}
acceptor = new AcceptorThread(port);
acceptor.prepare();
acceptor.setName("AprAcceptor-" + port);
acceptor.start();
}
// in java/org/apache/tomcat/jni/socket/AprSocketContext.java
public AprSocket socket(String host, int port, boolean ssl) throws IOException {
HostInfo hi = getHostInfo(host, port, ssl);
return socket(hi);
}
// in java/org/apache/tomcat/jni/socket/AprSocketContext.java
public AprSocket socket(HostInfo hi) throws IOException {
AprSocket sock = newSocket(this);
sock.setHost(hi);
return sock;
}
// in java/org/apache/tomcat/jni/socket/AprSocketContext.java
public AprSocket socket(long socket) throws IOException {
AprSocket sock = newSocket(this);
// Tomcat doesn't set this
SSLExt.sslSetMode(socket, SSLExt.SSL_MODE_ENABLE_PARTIAL_WRITE |
SSLExt.SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
sock.setStatus(AprSocket.ACCEPTED);
sock.socket = socket;
return sock;
}
// in java/org/apache/tomcat/jni/socket/AprSocketContext.java
protected void connectBlocking(AprSocket apr) throws IOException {
try {
if (!running) {
throw new IOException("Stopped");
}
HostInfo hi = apr.getHost();
long clientSockP;
synchronized (pollers) {
long socketpool = Pool.create(getRootPool());
int family = Socket.APR_INET;
clientSockP = Socket.create(family,
Socket.SOCK_STREAM,
Socket.APR_PROTO_TCP, socketpool); // or rootPool ?
}
Socket.timeoutSet(clientSockP, connectTimeout * 1000);
if (OS.IS_UNIX) {
Socket.optSet(clientSockP, Socket.APR_SO_REUSEADDR, 1);
}
Socket.optSet(clientSockP, Socket.APR_SO_KEEPALIVE, 1);
// Blocking
// TODO: use socket pool
// TODO: cache it ( and TTL ) in hi
long inetAddress = Address.info(hi.host, Socket.APR_INET,
hi.port, 0, rootPool);
// this may take a long time - stop/destroy must wait
// at least connect timeout
int rc = Socket.connect(clientSockP, inetAddress);
if (rc != 0) {
synchronized (pollers) {
Socket.close(clientSockP);
Socket.destroy(clientSockP);
}
/////Pool.destroy(socketpool);
throw new IOException("Socket.connect(): " + rc + " " + Error.strerror(rc) + " " + connectTimeout);
}
if (!running) {
throw new IOException("Stopped");
}
connectionsCount.incrementAndGet();
if (tcpNoDelay) {
Socket.optSet(clientSockP, Socket.APR_TCP_NODELAY, 1);
}
Socket.timeoutSet(clientSockP, defaultTimeout * 1000);
apr.socket = clientSockP;
apr.afterConnect();
} catch (IOException e) {
apr.reset();
throw e;
} catch (Throwable e) {
apr.reset();
e.printStackTrace();
throw new IOException(e);
}
}
// in java/org/apache/tomcat/jni/socket/AprSocketContext.java
AprSocket newSocket(AprSocketContext context) throws IOException {
return new AprSocket(context);
}
// in java/org/apache/tomcat/jni/socket/AprSocketContext.java
public void stop() throws IOException {
synchronized (pollers) {
if (!running) {
return;
}
running = false;
}
if (rootPool != 0) {
if (acceptor != null) {
try {
acceptor.unblock();
acceptor.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (acceptorDispatch != null) {
acceptedQueue.add(END);
try {
acceptorDispatch.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (threadPool != null) {
threadPool.shutdownNow();
}
log.info("Stopping pollers " + contextId);
while (true) {
AprPoller a;
synchronized (pollers) {
if (pollers.size() == 0) {
break;
}
a = pollers.remove(0);
}
a.interruptPoll();
try {
a.join();
log.info("Poller " + a.id + " done ");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
// in java/org/apache/tomcat/jni/socket/AprSocketContext.java
private long getRootPool() throws IOException {
if (rootPool == 0) {
if (noApr != null) {
throw noApr;
}
// Create the root APR memory pool
rootPool = Pool.create(0);
// Adjust poller sizes
if ((OS.IS_WIN32 || OS.IS_WIN64) && (maxConnections > 1024)) {
// The maximum per poller to get reasonable performance is 1024
pollerThreadCount = maxConnections / 1024;
// Adjust poller size so that it won't reach the limit
maxConnections = maxConnections - (maxConnections % 1024);
}
}
return rootPool;
}
// in java/org/apache/tomcat/jni/socket/AprSocketContext.java
void findPollerAndAdd(AprSocket ch) throws IOException {
if (ch.poller != null) {
ch.poller.requestUpdate(ch);
return;
}
assignPoller(ch);
}
// in java/org/apache/tomcat/jni/socket/AprSocketContext.java
void assignPoller(AprSocket ch) throws IOException {
AprPoller target = null;
synchronized (pollers) {
// Make sure we have min number of pollers
int needPollers = pollerThreadCount - pollers.size();
if (needPollers > 0) {
for (int i = needPollers; i > 0; i--) {
pollers.add(allocatePoller());
}
}
int max = 0;
for (AprPoller poller: pollers) {
int rem = poller.remaining();
if (rem > max) {
target = poller;
max = rem;
}
}
}
if (target != null && target.add(ch)) {
return;
}
// can't be added - add a new poller
synchronized (pollers) {
AprPoller poller = allocatePoller();
poller.add(ch);
pollers.add(poller);
}
}
// in java/org/apache/tomcat/jni/socket/AprSocketContext.java
protected void onSocket(AprSocket s) throws IOException {
}
// in java/org/apache/tomcat/jni/socket/AprSocketContext.java
void prepare() throws IOException {
try {
// Create the pool for the server socket
serverSockPool = Pool.create(getRootPool());
int family = Socket.APR_INET;
inetAddress = Address.info(addressStr, family,
port, 0, serverSockPool);
// Create the APR server socket
serverSock = Socket.create(family,
Socket.SOCK_STREAM,
Socket.APR_PROTO_TCP, serverSockPool);
if (OS.IS_UNIX) {
Socket.optSet(serverSock, Socket.APR_SO_REUSEADDR, 1);
}
// Deal with the firewalls that tend to drop the inactive sockets
Socket.optSet(serverSock, Socket.APR_SO_KEEPALIVE, 1);
// Bind the server socket
int ret = Socket.bind(serverSock, inetAddress);
if (ret != 0) {
throw new IOException("Socket.bind " + ret + " " +
Error.strerror(ret) + " port=" + port);
}
// Start listening on the server socket
ret = Socket.listen(serverSock, backlog );
if (ret != 0) {
throw new IOException("endpoint.init.listen"
+ ret + " " + Error.strerror(ret));
}
if (OS.IS_WIN32 || OS.IS_WIN64) {
// On Windows set the reuseaddr flag after the bind/listen
Socket.optSet(serverSock, Socket.APR_SO_REUSEADDR, 1);
}
// Sendfile usage on systems which don't support it cause major problems
if (useSendfile && !Library.APR_HAS_SENDFILE) {
useSendfile = false;
}
// Delay accepting of new connections until data is available
// Only Linux kernels 2.4 + have that implemented
// on other platforms this call is noop and will return APR_ENOTIMPL.
if (deferAccept) {
if (Socket.optSet(serverSock, Socket.APR_TCP_DEFER_ACCEPT, 1) == Status.APR_ENOTIMPL) {
deferAccept = false;
}
}
} catch (Throwable t) {
throw new IOException(t);
}
}
// in java/org/apache/tomcat/jni/socket/AprSocketContext.java
AprPoller allocatePoller() throws IOException {
long pool = Pool.create(getRootPool());
int size = maxConnections / pollerThreadCount;
int timeout = keepAliveTimeout;
long serverPollset = allocatePoller(size, pool, timeout);
if (serverPollset == 0 && size > 1024) {
log.severe("Falling back to 1024-sized poll, won't scale");
size = 1024;
serverPollset = allocatePoller(size, pool, timeout);
}
if (serverPollset == 0) {
log.severe("Falling back to 62-sized poll, won't scale");
size = 62;
serverPollset = allocatePoller(size, pool, timeout);
}
AprPoller res = new AprPoller();
res.pool = pool;
res.serverPollset = serverPollset;
res.desc = new long[size * 2];
res.size = size;
res.id = contextId++;
res.setDaemon(true);
res.setName("AprPoller-" + res.id);
res.start();
if (debugPoll && !sizeLogged) {
sizeLogged = true;
log.info("Poller size " + (res.desc.length / 2));
}
return res;
}
// in java/org/apache/tomcat/jni/socket/AprSocketContext.java
protected void updates() throws IOException {
synchronized (this) {
for (AprSocket up: updates) {
updateIOThread(up);
}
updates.clear();
}
}
// in java/org/apache/tomcat/jni/socket/AprSocketContext.java
boolean add(AprSocket ch) throws IOException {
synchronized (this) {
if (!running) {
return false;
}
if (keepAliveCount.get() >= size) {
return false;
}
keepAliveCount.incrementAndGet();
ch.poller = this;
}
requestUpdate(ch);
return true;
}
// in java/org/apache/tomcat/jni/socket/AprSocketContext.java
protected void requestUpdate(AprSocket ch) throws IOException {
synchronized (this) {
if (!running) {
return;
}
}
if (isPollerThread()) {
updateIOThread(ch);
} else {
synchronized (this) {
if (!updates.contains(ch)) {
updates.add(ch);
}
interruptPoll();
}
if (debugPoll) {
log.info("Poll: requestUpdate " + id + " " + ch);
}
}
}
// in java/org/apache/tomcat/jni/socket/AprSocketContext.java
private void updateIOThread(AprSocket ch) throws IOException {
if (!running || ch.socket == 0) {
return;
}
// called from IO thread, either in 'updates' or after
// poll.
//synchronized (ch)
boolean polling = ch.checkPreConnect(AprSocket.POLL);
int requested = ch.requestedPolling();
if (requested == 0) {
if (polling) {
removeSafe(ch);
}
if (ch.isClosed()) {
synchronized (channels) {
ch.poller = null;
channels.remove(ch.socket);
}
keepAliveCount.decrementAndGet();
ch.reset();
}
} else {
if (polling) {
removeSafe(ch);
}
// will close if error
pollAdd(ch, requested);
}
if (debugPoll) {
log.info("Poll: updated=" + id + " " + ch);
}
}
// in java/org/apache/tomcat/jni/socket/AprSocketContext.java
private void pollAdd(AprSocket up, int req) throws IOException {
boolean failed = false;
int rv;
synchronized (channels) {
if (up.isClosed()) {
return;
}
rv = Poll.add(serverPollset, up.socket, req);
if (rv != Status.APR_SUCCESS) {
up.poller = null;
keepAliveCount.decrementAndGet();
failed = true;
} else {
polledCount.incrementAndGet();
channels.put(up.socket, up);
up.setStatus(AprSocket.POLL);
}
}
if (failed) {
up.reset();
throw new IOException("poll add error " + rv + " " + up + " " + Error.strerror(rv));
}
}
// in java/org/apache/tomcat/jni/socket/AprSocketContext.java
private void removeSafe(AprSocket up) throws IOException {
int rv = Status.APR_EGENERAL;
if (running && serverPollset != 0 && up.socket != 0
&& !up.isClosed()) {
rv = Poll.remove(serverPollset, up.socket);
}
up.clearStatus(AprSocket.POLL);
if (rv != Status.APR_SUCCESS) {
log.severe("poll remove error " + Error.strerror(rv) + " " + up);
} else {
polledCount.decrementAndGet();
}
}
// in java/org/apache/tomcat/jni/socket/AprSocket.java
public void connect() throws IOException {
if (isBlocking()) {
// will call handleConnected() at the end.
context.connectBlocking(this);
} else {
synchronized(this) {
if ((status & CONNECTING) != 0) {
return;
}
status |= CONNECTING;
}
context.connectExecutor.execute(this);
}
}
// in java/org/apache/tomcat/jni/socket/AprSocket.java
void afterConnect() throws IOException {
if (hostInfo.secure) {
blockingStartTLS();
}
setNonBlocking(); // call again, to set the bits ( connect was blocking )
setStatus(CONNECTED);
clearStatus(CONNECTING);
notifyConnected(false);
}
// in java/org/apache/tomcat/jni/socket/AprSocket.java
public int write(byte[] data, int off, int len, long to) throws IOException {
long max = System.currentTimeMillis() + to;
while (true) {
int rc = writeInternal(data, off, len);
if (rc < 0) {
throw new IOException("Write error " + rc);
} else if (rc == 0) {
// need poll out - do we need to update polling ?
context.findPollerAndAdd(this);
} else {
return rc;
}
try {
long waitTime = max - System.currentTimeMillis();
if (waitTime <= 0) {
return 0;
}
wait(waitTime);
} catch (InterruptedException e) {
return 0;
}
}
}
// in java/org/apache/tomcat/jni/socket/AprSocket.java
public int write(byte[] data, int off, int len) throws IOException {
// In SSL mode, read/write can't be called at the same time.
int rc = writeInternal(data, off, len);
if (rc < 0) {
throw new IOException("Write error " + rc);
} else if (rc == 0) {
// need poll out - do we need to update polling ?
synchronized (this) {
context.findPollerAndAdd(this);
}
}
return rc;
}
// in java/org/apache/tomcat/jni/socket/AprSocket.java
private int writeInternal(byte[] data, int off, int len) throws IOException {
int rt = 0;
int sent = 0;
synchronized(this) {
if ((status & CLOSED) != 0
|| socket == 0
|| !context.running) {
throw new IOException("Closed");
}
if ((status & WRITING) != 0) {
throw new IOException("Write from 2 threads not allowed");
}
status |= WRITING;
while (len > 0) {
sent = Socket.send(socket, data, off, len);
if (sent <= 0) {
break;
}
off += sent;
len -= sent;
}
status &= ~WRITING;
}
if (context.rawDataHandler != null) {
context.rawData(this, false, data, off, sent, len, false);
}
if (sent <= 0) {
if (sent == -Status.TIMEUP || sent == -Status.EAGAIN || sent == 0) {
setStatus(POLLOUT);
updatePolling();
return rt;
}
if (context.debug) {
log.warning("apr.send(): Failed to send, closing " + sent);
}
reset();
throw new IOException("Error sending " + sent + " " + Error.strerror(-sent));
} else {
off += sent;
len -= sent;
rt += sent;
return sent;
}
}
// in java/org/apache/tomcat/jni/socket/AprSocket.java
public int read(byte[] data, int off, int len, long to) throws IOException {
int rd = readNB(data, off, len);
if (rd == 0) {
synchronized(this) {
try {
wait(to);
} catch (InterruptedException e) {
return 0;
}
}
rd = readNB(data, off, len);
}
return processReadResult(data, off, len, rd);
}
// in java/org/apache/tomcat/jni/socket/AprSocket.java
public int read(byte[] data, int off, int len) throws IOException {
return readNB(data, off, len);
}
// in java/org/apache/tomcat/jni/socket/AprSocket.java
private int processReadResult(byte[] data, int off, int len, int read)
throws IOException {
if (context.rawDataHandler != null) {
context.rawData(this, true, data, off, read, len, false);
}
if (read > 0) {
return read;
}
if (read == 0 || read == -Status.TIMEUP || read == -Status.ETIMEDOUT
|| read == -Status.EAGAIN) {
read = 0;
setStatus(POLLIN);
updatePolling();
return 0;
}
if (read == -Status.APR_EOF || read == -1) {
close();
return -1;
}
// abrupt close
reset();
throw new IOException("apr.read(): " + read + " " + Error.strerror(-read));
}
// in java/org/apache/tomcat/jni/socket/AprSocket.java
public int readNB(byte[] data, int off, int len) throws IOException {
int read;
synchronized(this) {
if ((status & CLOSED) != 0
|| socket == 0
|| !context.running) {
return -1;
}
if ((status & READING) != 0) {
throw new IOException("Read from 2 threads not allowed");
}
status |= READING;
read = Socket.recv(socket, data, off, len);
status &= ~READING;
}
return processReadResult(data, off, len, read);
}
// in java/org/apache/tomcat/jni/socket/AprSocket.java
public void close() throws IOException {
synchronized (this) {
if ((status & CLOSED) != 0 || socket == 0) {
return;
}
status |= CLOSED;
status &= ~POLLIN;
status &= ~POLLOUT;
}
if (context.rawDataHandler != null) {
context.rawDataHandler.rawData(this, false, null, 0, 0, 0, true);
}
Socket.close(socket);
if (poller == null) {
maybeDestroy();
} else {
try {
poller.requestUpdate(this);
} catch (IOException e) {
e.printStackTrace();
}
}
}
// in java/org/apache/tomcat/jni/socket/AprSocket.java
public long getIOTimeout() throws IOException {
if (socket != 0 && context.running) {
try {
return Socket.timeoutGet(socket) / 1000;
} catch (Exception e) {
throw new IOException(e);
}
} else {
throw new IOException("Socket is closed");
}
}
// in java/org/apache/tomcat/jni/socket/AprSocket.java
public byte[][] getPeerCert(boolean check) throws IOException {
getHost();
if (hostInfo.certs != null && hostInfo.certs != NO_CERTS && !check) {
return hostInfo.certs;
}
if (!checkBitAndSocket(SSL_ATTACHED)) {
return NO_CERTS;
}
try {
int certLength = SSLSocket.getInfoI(socket,
SSL.SSL_INFO_CLIENT_CERT_CHAIN);
// TODO: if resumed, old certs are good.
// If not - warn if certs changed, remember first cert, etc.
if (certLength <= 0) {
// Can also happen on session resume - keep the old
if (hostInfo.certs == null) {
hostInfo.certs = NO_CERTS;
}
return hostInfo.certs;
}
hostInfo.certs = new byte[certLength + 1][];
hostInfo.certs[0] = SSLSocket.getInfoB(socket,
SSL.SSL_INFO_CLIENT_CERT);
for (int i = 0; i < certLength; i++) {
hostInfo.certs[i + 1] = SSLSocket.getInfoB(socket,
SSL.SSL_INFO_CLIENT_CERT_CHAIN + i);
}
return hostInfo.certs;
} catch (Exception e) {
throw new IOException(e);
}
}
// in java/org/apache/tomcat/jni/socket/AprSocket.java
public X509Certificate[] getPeerX509Cert() throws IOException {
byte[][] certs = getPeerCert(false);
X509Certificate[] xcerts = new X509Certificate[certs.length];
if (certs.length == 0) {
return xcerts;
}
try {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
for (int i = 0; i < certs.length; i++) {
if (certs[i] != null) {
ByteArrayInputStream bis = new ByteArrayInputStream(
certs[i]);
xcerts[i] = (X509Certificate) cf.generateCertificate(bis);
bis.close();
}
}
} catch (CertificateException ex) {
throw new IOException(ex);
}
return xcerts;
}
// in java/org/apache/tomcat/jni/socket/AprSocket.java
public String getCipherSuite() throws IOException {
if (checkBitAndSocket(SSL_ATTACHED)) {
return null;
}
try {
return SSLSocket.getInfoS(socket, SSL.SSL_INFO_CIPHER);
} catch (Exception e) {
throw new IOException(e);
}
}
// in java/org/apache/tomcat/jni/socket/AprSocket.java
public int getKeySize() throws IOException {
if (checkBitAndSocket(SSL_ATTACHED)) {
return -1;
}
try {
return SSLSocket.getInfoI(socket, SSL.SSL_INFO_CIPHER_USEKEYSIZE);
} catch (Exception e) {
throw new IOException(e);
}
}
// in java/org/apache/tomcat/jni/socket/AprSocket.java
public int getRemotePort() throws IOException {
if (socket != 0 && context.running) {
try {
long sa = Address.get(Socket.APR_REMOTE, socket);
Sockaddr addr = Address.getInfo(sa);
return addr.port;
} catch (Exception ex) {
throw new IOException(ex);
}
}
throw new IOException("Socket closed");
}
// in java/org/apache/tomcat/jni/socket/AprSocket.java
public String getRemoteAddress() throws IOException {
if (socket != 0 && context.running) {
try {
long sa = Address.get(Socket.APR_REMOTE, socket);
return Address.getip(sa);
} catch (Exception ex) {
throw new IOException(ex);
}
}
throw new IOException("Socket closed");
}
// in java/org/apache/tomcat/jni/socket/AprSocket.java
public String getRemoteHostname() throws IOException {
if (socket != 0 && context.running) {
try {
long sa = Address.get(Socket.APR_REMOTE, socket);
String remoteHost = Address.getnameinfo(sa, 0);
if (remoteHost == null) {
remoteHost = Address.getip(sa);
}
return remoteHost;
} catch (Exception ex) {
throw new IOException(ex);
}
}
throw new IOException("Socket closed");
}
// in java/org/apache/tomcat/jni/socket/AprSocket.java
public int getLocalPort() throws IOException {
if (socket != 0 && context.running) {
try {
long sa = Address.get(Socket.APR_LOCAL, socket);
Sockaddr addr = Address.getInfo(sa);
return addr.port;
} catch (Exception ex) {
throw new IOException(ex);
}
}
throw new IOException("Socket closed");
}
// in java/org/apache/tomcat/jni/socket/AprSocket.java
public String getLocalAddress() throws IOException {
if (socket != 0 && context.running) {
try {
long sa = Address.get(Socket.APR_LOCAL, socket);
return Address.getip(sa);
} catch (Exception ex) {
throw new IOException(ex);
}
}
throw new IOException("Socket closed");
}
// in java/org/apache/tomcat/jni/socket/AprSocket.java
public String getLocalHostname() throws IOException {
if (socket != 0 && context.running) {
try {
long sa = Address.get(Socket.APR_LOCAL, socket);
return Address.getnameinfo(sa, 0);
} catch (Exception ex) {
throw new IOException(ex);
}
}
throw new IOException("Socket closed");
}
// in java/org/apache/tomcat/jni/socket/AprSocket.java
void notifyIO() throws IOException {
long t0 = System.currentTimeMillis();
try {
if (handler != null) {
handler.process(this, true, false, false);
}
} catch (Throwable t) {
throw new IOException(t);
} finally {
long t1 = System.currentTimeMillis();
t1 -= t0;
if (t1 > context.maxHandlerTime.get()) {
context.maxHandlerTime.set(t1);
}
context.totalHandlerTime.addAndGet(t1);
context.handlerCount.incrementAndGet();
}
}
// in java/org/apache/tomcat/jni/socket/AprSocket.java
private void notifyConnected(boolean server) throws IOException {
// Will set the handler on the channel for accepted
context.onSocket(this);
if (handler instanceof AprSocketContext.NonBlockingPollHandler) {
((AprSocketContext.NonBlockingPollHandler) handler).connected(this);
((AprSocketContext.NonBlockingPollHandler) handler).process(this, true, true, false);
// Now register for polling - unless process() set suspendRead and
// doesn't need out notifications
updatePolling();
} else {
if (server) {
// client will block in connect().
// Server: call process();
notifyIO();
}
}
}
// in java/org/apache/tomcat/jni/socket/AprSocket.java
private void updatePolling() throws IOException {
synchronized (this) {
if ((status & CLOSED) != 0) {
maybeDestroy();
return;
}
}
context.findPollerAndAdd(this);
}
// in java/org/apache/tomcat/jni/socket/AprSocket.java
public void blockingStartTLS() throws IOException {
synchronized(this) {
if (socket == 0 || !context.running) {
return;
}
if ((status & SSL_ATTACHED) != 0) {
return;
}
status |= SSL_ATTACHED;
}
try {
if (context.debug) {
log.info(this + " StartSSL");
}
AprSocketContext aprCon = context;
SSLSocket.attach(aprCon.getSslCtx(), socket);
if (context.debugSSL) {
SSLExt.debug(socket);
}
if (!getContext().isServer()) {
if (context.USE_TICKETS && hostInfo.ticketLen > 0) {
SSLExt.setTicket(socket, hostInfo.ticket,
hostInfo.ticketLen);
} else if (hostInfo.sessDer != null) {
SSLExt.setSessionData(socket, hostInfo.sessDer,
hostInfo.sessDer.length);
}
}
SSLExt.sslSetMode(socket, SSLExt.SSL_MODE_ENABLE_PARTIAL_WRITE |
SSLExt.SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
int rc = SSLSocket.handshake(socket);
// At this point we have the session ID, remote certs, etc
// we can lookup host info
if (hostInfo == null) {
hostInfo = new HostInfo();
}
if (rc != Status.APR_SUCCESS) {
throw new IOException(this + " Handshake failed " + rc + " "
+ Error.strerror(rc) + " SSLL "
+ SSL.getLastError());
} else { // SUCCESS
handshakeDone();
}
} catch (IOException e) {
throw e;
} catch (Exception e) {
throw new IOException(e);
}
}
// in java/org/apache/tomcat/jni/socket/AprSocket.java
private void handshakeDone() throws IOException {
getHost();
if (socket == 0 || !context.running) {
throw new IOException("Socket closed");
}
if (context.USE_TICKETS && ! context.isServer()) {
if (hostInfo.ticket == null) {
hostInfo.ticket = new byte[2048];
}
int ticketLen = SSLExt.getTicket(socket, hostInfo.ticket);
if (ticketLen > 0) {
hostInfo.ticketLen = ticketLen;
if (context.debug) {
log.info("Received ticket: " + ticketLen);
}
}
}
// TODO: if the ticket, session id or session changed - callback to
// save the session again
try {
hostInfo.sessDer = SSLExt.getSessionData(socket);
getPeerCert(true);
hostInfo.sessionId = SSLSocket.getInfoS(socket,
SSL.SSL_INFO_SESSION_ID);
} catch (Exception e) {
throw new IOException(e);
}
hostInfo.npn = new byte[32];
hostInfo.npnLen = SSLExt.getNPN(socket, hostInfo.npn);
// If custom verification is used - should check the certificates
if (context.tlsCertVerifier != null) {
context.tlsCertVerifier.handshakeDone(this);
}
}
// in java/org/apache/tomcat/buildutil/CheckEol.java
private void check(File file, List<CheckFailure> errors, Mode mode)
throws IOException {
BufferedInputStream is = new BufferedInputStream(new FileInputStream(
file));
try {
int line = 1;
int prev = -1;
int ch;
while ((ch = is.read()) != -1) {
if (ch == '\n') {
if (mode == Mode.LF && prev == '\r') {
errors.add(new CheckFailure(file, line, "CRLF"));
return;
} else if (mode == Mode.CRLF && prev != '\r') {
errors.add(new CheckFailure(file, line, "LF"));
return;
}
line++;
} else if (prev == '\r') {
errors.add(new CheckFailure(file, line, "CR"));
return;
}
prev = ch;
}
} finally {
is.close();
}
}
// in java/org/apache/tomcat/buildutil/Txt2Html.java
private void convert( File from, File to )
throws IOException
{
// Open files:
BufferedReader in = new BufferedReader( new FileReader( from ) );
PrintWriter out = new PrintWriter( new FileWriter( to ) );
// Output header:
out.println( "<html><body><pre>" );
// Convert, line-by-line:
String line;
while( (line = in.readLine()) != null ) {
StringBuilder result = new StringBuilder();
int len = line.length();
for( int i = 0; i < len; i++ ) {
char c = line.charAt( i );
switch( c ) {
case '&':
result.append( "&" );
break;
case '<':
result.append( "<" );
break;
default:
result.append( c );
}
}
out.println( result.toString() );
}
// Output footer:
out.println( "</pre></body></html>" );
// Close streams:
out.close();
in.close();
}
// in java/org/apache/tomcat/spdy/SpdyStream.java
public void onCtlFrame(SpdyFrame frame) throws IOException {
// TODO: handle RST
if (frame.type == SpdyConnection.TYPE_SYN_STREAM) {
reqFrame = frame;
} else if (frame.type == SpdyConnection.TYPE_SYN_REPLY) {
resFrame = frame;
}
synchronized (this) {
inData.add(frame);
if (frame.isHalfClose()) {
finRcvd = true;
}
}
}
// in java/org/apache/tomcat/spdy/SpdyStream.java
public SpdyFrame getDataFrame(long to) throws IOException {
while (true) {
SpdyFrame res = getFrame(to);
if (res == null || res.isData()) {
return res;
}
if (res.type == SpdyConnection.TYPE_RST_STREAM) {
throw new IOException("Reset");
}
}
}
// in java/org/apache/tomcat/spdy/SpdyStream.java
public SpdyFrame getFrame(long to) throws IOException {
SpdyFrame in;
try {
synchronized (this) {
if (inData.size() == 0 && finRcvd) {
return END_FRAME;
}
}
in = inData.poll(to, TimeUnit.MILLISECONDS);
return in;
} catch (InterruptedException e) {
return null;
}
}
// in java/org/apache/tomcat/spdy/SpdyStream.java
public synchronized void sendDataFrame(byte[] data, int start,
int length, boolean close) throws IOException {
SpdyFrame oframe = spdy.getDataFrame();
// Options:
// 1. wrap the byte[] data, use a separate header[], wait frame sent
// -> 2 socket writes
// 2. copy the data to frame byte[] -> non-blocking queue
// 3. copy the data, blocking drain -> like 1, trade one copy to
// avoid
// 1 tcp packet. That's the current choice, seems closer to rest of
// tomcat
if (close)
oframe.halfClose();
oframe.append(data, start, length);
spdy.send(oframe, this);
}
// in java/org/apache/tomcat/spdy/SpdyStream.java
public void send() throws IOException {
send("http", "GET");
}
// in java/org/apache/tomcat/spdy/SpdyStream.java
public void send(String host, String url, String scheme, String method) throws IOException {
getRequest().addHeader("host", host);
getRequest().addHeader("url", url);
send(scheme, method);
}
// in java/org/apache/tomcat/spdy/SpdyStream.java
public void send(String scheme, String method) throws IOException {
getRequest();
if ("GET".equalsIgnoreCase(method)) {
// TODO: add the others
reqFrame.halfClose();
}
getRequest().addHeader("scheme", "http"); // todo
getRequest().addHeader("method", method);
getRequest().addHeader("version", "HTTP/1.1");
if (reqFrame.isHalfClose()) {
finSent = true;
}
spdy.send(reqFrame, this);
}
// in java/org/apache/tomcat/spdy/SpdyStream.java
private void fill() throws IOException {
if (current == null || current.off == current.endData) {
if (current != null) {
spdy.spdyContext.releaseFrame(current);
}
current = getFrame(to);
}
}
// in java/org/apache/tomcat/spdy/SpdyStream.java
Override
public int read() throws IOException {
fill();
if (current == null) {
return -1;
}
return current.readByte();
}
// in java/org/apache/tomcat/spdy/SpdyStream.java
Override
public int read(byte b[], int off, int len) throws IOException {
fill();
if (current == null) {
return -1;
}
// don't wait for next frame
int rd = Math.min(len, current.endData - current.off);
System.arraycopy(current.data, current.off, b, off, rd);
current.off += rd;
return rd;
}
// in java/org/apache/tomcat/spdy/SpdyStream.java
Override
public int available() throws IOException {
return 0;
}
// in java/org/apache/tomcat/spdy/SpdyStream.java
Override
public void close() throws IOException {
// send RST if not closed
}
// in java/org/apache/tomcat/spdy/SpdyConnection.java
public void nonBlockingSend(SpdyFrame oframe, SpdyStream proc)
throws IOException {
queueFrame(oframe, proc, oframe.pri == 0 ? outQueue : prioriyQueue);
getSpdyContext().getExecutor().execute(nbDrain);
}
// in java/org/apache/tomcat/spdy/SpdyConnection.java
public void send(SpdyFrame oframe, SpdyStream proc)
throws IOException {
queueFrame(oframe, proc, oframe.pri == 0 ? outQueue : prioriyQueue);
drain();
}
// in java/org/apache/tomcat/spdy/SpdyConnection.java
private void queueFrame(SpdyFrame oframe, SpdyStream proc,
LinkedList<SpdyFrame> queue) throws IOException {
oframe.endData = oframe.off;
oframe.off = 0;
// We can't assing a stream ID until it is sent - priorities
// we can't compress either - it's stateful.
oframe.stream = proc;
// all sync for adding/removing is on outQueue
synchronized (outQueue) {
queue.add(oframe);
}
}
// in java/org/apache/tomcat/spdy/SpdyConnection.java
public int processInput() throws IOException {
while (true) {
if (inFrame == null) {
inFrame = getSpdyContext().getFrame();
}
if (inFrame.data == null) {
inFrame.data = new byte[16 * 1024];
}
// we might already have data from previous frame
if (inFrame.endReadData < 8 || // we don't have the header
inFrame.endReadData < inFrame.endData) {
int rd = read(inFrame.data, inFrame.endReadData,
inFrame.data.length - inFrame.endReadData);
if (rd == -1) {
if (channels.size() == 0) {
return CLOSE;
} else {
abort("Closed");
}
} else if (rd < 0) {
abort("Closed - read error");
return CLOSE;
} else if (rd == 0) {
return LONG;
// Non-blocking channel - will resume reading at off
}
inFrame.endReadData += rd;
}
if (inFrame.endReadData < 8) {
continue; // keep reading
}
if (inFrame.endData == 0) {
inFrame.parse();
if (inFrame.version != 2) {
abort("Wrong version");
return CLOSE;
}
// MAX_FRAME_SIZE
if (inFrame.endData < 0 || inFrame.endData > 32000) {
abort("Framing error, size = " + inFrame.endData);
return CLOSE;
}
// TODO: if data, split it in 2 frames
// grow the buffer if needed.
if (inFrame.data.length < inFrame.endData) {
byte[] tmp = new byte[inFrame.endData];
System.arraycopy(inFrame.data, 0, tmp, 0, inFrame.endReadData);
inFrame.data = tmp;
}
}
if (inFrame.endReadData < inFrame.endData) {
continue; // keep reading to fill current frame
}
// else: we have at least the current frame
int extra = inFrame.endReadData - inFrame.endData;
if (extra > 0) {
// and a bit more - to keep things simple for now we
// copy them to next frame, at least we saved reads.
// it is possible to avoid copy - but later.
nextFrame = getSpdyContext().getFrame();
nextFrame.makeSpace(extra);
System.arraycopy(inFrame.data, inFrame.endData,
nextFrame.data, 0, extra);
nextFrame.endReadData = extra;
inFrame.endReadData = inFrame.endData;
}
// decompress
if (inFrame.type == TYPE_SYN_STREAM) {
inFrame.streamId = inFrame.readInt(); // 4
lastChannel = inFrame.streamId;
inFrame.associated = inFrame.readInt(); // 8
inFrame.pri = inFrame.read16(); // 10 pri and unused
if (compressSupport != null) {
compressSupport.decompress(inFrame, 18);
}
inFrame.nvCount = inFrame.read16();
} else if (inFrame.type == TYPE_SYN_REPLY
|| inFrame.type == TYPE_HEADERS) {
inFrame.streamId = inFrame.readInt(); // 4
inFrame.read16();
if (compressSupport != null) {
compressSupport.decompress(inFrame, 14);
}
inFrame.nvCount = inFrame.read16();
}
if (SpdyContext.debug) {
trace("< " + inFrame);
}
try {
int state = handleFrame();
if (state == CLOSE) {
return state;
}
} catch (Throwable t) {
abort("Error handling frame");
t.printStackTrace();
return CLOSE;
}
if (inFrame != null) {
inFrame.recyle();
if (nextFrame != null) {
getSpdyContext().releaseFrame(inFrame);
inFrame = nextFrame;
nextFrame = null;
}
} else {
inFrame = nextFrame;
nextFrame = null;
if (inFrame == null) {
inFrame = getSpdyContext().getFrame();
}
}
}
}
// in java/org/apache/tomcat/spdy/SpdyConnection.java
protected int handleFrame() throws IOException {
if (inFrame.c) {
switch (inFrame.type) {
case TYPE_SETTINGS: {
int cnt = inFrame.readInt();
for (int i = 0; i < cnt; i++) {
int flag = inFrame.readByte();
int id = inFrame.read24();
int value = inFrame.readInt();
}
// TODO: save/interpret settings
break;
}
case TYPE_GOAWAY: {
int lastStream = inFrame.readInt();
log.info("GOAWAY last=" + lastStream);
// Server will shut down - but will keep processing the current requests,
// up to lastStream. If we sent any new ones - they need to be canceled.
abort("GO_AWAY", lastStream);
goAway = lastStream;
return CLOSE;
}
case TYPE_RST_STREAM: {
inFrame.streamId = inFrame.read32();
int errCode = inFrame.read32();
if (SpdyContext.debug) {
trace("> RST "
+ inFrame.streamId
+ " "
+ ((errCode < RST_ERRORS.length) ? RST_ERRORS[errCode]
: errCode));
}
SpdyStream sch;
synchronized(channels) {
sch = channels.remove(inFrame.streamId);
}
// if RST stream is for a closed channel - we can ignore.
if (sch != null) {
sch.onReset();
}
inFrame = null;
break;
}
case TYPE_SYN_STREAM: {
SpdyStream ch = getSpdyContext().getStream(this);
synchronized (channels) {
channels.put(inFrame.streamId, ch);
}
try {
ch.onCtlFrame(inFrame);
inFrame = null;
} catch (Throwable t) {
log.log(Level.SEVERE, "Error parsing head SYN_STREAM", t);
abort("Error reading headers " + t);
return CLOSE;
}
spdyContext.onStream(this, ch);
break;
}
case TYPE_SYN_REPLY: {
SpdyStream sch;
synchronized(channels) {
sch = channels.get(inFrame.streamId);
}
if (sch == null) {
abort("Missing channel");
return CLOSE;
}
try {
sch.onCtlFrame(inFrame);
inFrame = null;
} catch (Throwable t) {
log.info("Error parsing head SYN_STREAM" + t);
abort("Error reading headers " + t);
return CLOSE;
}
break;
}
case TYPE_PING: {
SpdyFrame oframe = getSpdyContext().getFrame();
oframe.type = TYPE_PING;
oframe.c = true;
oframe.append32(inFrame.read32());
oframe.pri = 0x80;
send(oframe, null);
break;
}
}
} else {
// Data frame
SpdyStream sch;
synchronized (channels) {
sch = channels.get(inFrame.streamId);
}
if (sch == null) {
abort("Missing channel");
return CLOSE;
}
sch.onDataFrame(inFrame);
synchronized (channels) {
if (sch.finRcvd && sch.finSent) {
channels.remove(inFrame.streamId);
}
}
inFrame = null;
}
return LONG;
}
// in java/org/apache/tomcat/spdy/SpdyConnection.java
public SpdyStream get(String host, String url) throws IOException {
SpdyStream sch = new SpdyStream(this);
sch.getRequest().addHeader("host", host);
sch.getRequest().addHeader("url", url);
sch.send();
return sch;
}
// in java/org/apache/tomcat/spdy/NetSupportOpenSSL.java
Override
public SpdyConnection getConnection(String host, int port) throws IOException {
SpdyConnectionAprSocket spdy = new SpdyConnectionAprSocket(ctx);
AprSocket ch = con.socket(host, port, ctx.tls);
spdy.setSocket(ch);
ch.connect();
ch.setHandler(new SpdySocketHandler(spdy));
// need to consume the input to receive more read events
int rc = spdy.processInput();
if (rc == SpdyConnection.CLOSE) {
ch.close();
throw new IOException("Error connecting");
}
return spdy;
}
// in java/org/apache/tomcat/spdy/NetSupportOpenSSL.java
Override
public void onAccept(Object socket) throws IOException {
onAcceptLong((Long) socket);
}
// in java/org/apache/tomcat/spdy/NetSupportOpenSSL.java
public void onAcceptLong(long socket) throws IOException {
SpdyConnectionAprSocket spdy = new SpdyConnectionAprSocket(ctx);
AprSocket s = con.socket(socket);
spdy.setSocket(s);
SpdySocketHandler handler = new SpdySocketHandler(spdy);
s.setHandler(handler);
handler.process(s, true, true, false);
}
// in java/org/apache/tomcat/spdy/NetSupportOpenSSL.java
Override
public void listen(final int port, String cert, String key) throws IOException {
con = new AprSocketContext() {
@Override
protected void onSocket(AprSocket s) throws IOException {
SpdyConnectionAprSocket spdy = new SpdyConnectionAprSocket(ctx);
spdy.setSocket(s);
SpdySocketHandler handler = new SpdySocketHandler(spdy);
s.setHandler(handler);
}
};
con.setNpn(SpdyContext.SPDY_NPN_OUT);
con.setKeys(cert, key);
con.listen(port);
}
// in java/org/apache/tomcat/spdy/NetSupportOpenSSL.java
Override
protected void onSocket(AprSocket s) throws IOException {
SpdyConnectionAprSocket spdy = new SpdyConnectionAprSocket(ctx);
spdy.setSocket(s);
SpdySocketHandler handler = new SpdySocketHandler(spdy);
s.setHandler(handler);
}
// in java/org/apache/tomcat/spdy/NetSupportOpenSSL.java
Override
public void stop() throws IOException {
con.stop();
}
// in java/org/apache/tomcat/spdy/NetSupportOpenSSL.java
Override
public void close() throws IOException {
socket.close();
}
// in java/org/apache/tomcat/spdy/NetSupportOpenSSL.java
Override
public int write(byte[] data, int off, int len) throws IOException {
if (socket == null) {
return -1;
}
int sent = socket.write(data, off, len);
if (sent < 0) {
return -1;
}
return sent;
}
// in java/org/apache/tomcat/spdy/NetSupportOpenSSL.java
Override
public int read(byte[] data, int off, int len) throws IOException {
if (socket == null) {
return -1;
}
int rd = socket.read(data, off, len);
// org.apache.tomcat.jni.Socket.recv(socket, data, off, len);
if (rd == -Status.APR_EOF) {
return -1;
}
if (rd == -Status.TIMEUP || rd == -Status.EINTR || rd == -Status.EAGAIN) {
rd = 0;
}
if (rd < 0) {
return -1;
}
off += rd;
len -= rd;
return rd;
}
// in java/org/apache/tomcat/spdy/CompressDeflater6.java
Override
public synchronized void compress(SpdyFrame frame, int start)
throws IOException {
init();
if (compressBuffer == null) {
compressBuffer = new byte[frame.data.length];
}
// last byte for flush ?
zipOut.setInput(frame.data, start, frame.endData - start - 1);
int coff = start;
zipOut.setLevel(Deflater.DEFAULT_COMPRESSION);
while (true) {
int rd = zipOut.deflate(compressBuffer, coff, compressBuffer.length - coff);
if (rd == 0) {
// needsInput needs to be called - we're done with this frame ?
zipOut.setInput(frame.data, frame.endData - 1, 1);
zipOut.setLevel(Deflater.BEST_SPEED);
while (true) {
rd = zipOut.deflate(compressBuffer, coff, compressBuffer.length - coff);
coff += rd;
if (rd == 0) {
break;
}
byte[] b = new byte[compressBuffer.length * 2];
System.arraycopy(compressBuffer, 0, b, 0, coff);
compressBuffer = b;
}
zipOut.setLevel(Deflater.DEFAULT_COMPRESSION);
break;
}
coff += rd;
}
byte[] tmp = frame.data;
frame.data = compressBuffer;
compressBuffer = tmp;
frame.endData = coff;
}
// in java/org/apache/tomcat/spdy/CompressDeflater6.java
Override
public synchronized void decompress(SpdyFrame frame, int start)
throws IOException {
// stream id ( 4 ) + unused ( 2 )
// nvCount is compressed in impl - spec is different
init();
if (decompressBuffer == null) {
decompressBuffer = new byte[frame.data.length];
}
// will read from dec buffer to frame.data
decMax = frame.endData;
decOff = start;
int off = start;
zipIn.setInput(frame.data, start, decMax - start);
while (true) {
int rd;
try {
rd = zipIn.inflate(decompressBuffer, off, decompressBuffer.length - off);
if (rd == 0 && zipIn.needsDictionary()) {
zipIn.setDictionary(SPDY_DICT);
continue;
}
} catch (DataFormatException e) {
throw new IOException(e);
}
if (rd == 0) {
break;
}
if (rd == -1) {
break;
}
off += rd;
byte[] b = new byte[decompressBuffer.length * 2];
System.arraycopy(decompressBuffer, 0, b, 0, off);
decompressBuffer = b;
}
byte[] tmpBuf = decompressBuffer;
decompressBuffer = frame.data;
frame.data = tmpBuf;
frame.off = start;
frame.endData = off;
}
// in java/org/apache/tomcat/spdy/NetSupportSocket.java
Override
public SpdyConnection getConnection(String host, int port) throws IOException {
try {
Socket sock = getSocket(host, port);
sock.getInputStream();
SpdyConnectionSocket con = new SpdyConnectionSocket(ctx, sock);
ctx.getExecutor().execute(con.inputThread);
return con;
} catch (IOException ex) {
ex.printStackTrace();
throw ex;
}
}
// in java/org/apache/tomcat/spdy/NetSupportSocket.java
protected Socket getSocket(String host, int port) throws IOException {
try {
if (ctx.tls) {
SSLContext sslCtx = SSLContext.getDefault();
SSLSocket socket = (SSLSocket) sslCtx.getSocketFactory().createSocket(host, port);
//socket.setEnabledProtocols(new String[] {"TLS1"});
socket.startHandshake();
return socket;
} else {
return new Socket(host, port);
}
} catch (NoSuchAlgorithmException e) {
throw new IOException(e);
}
}
// in java/org/apache/tomcat/spdy/NetSupportSocket.java
Override
public void stop() throws IOException {
running = false;
serverSocket.close();
}
// in java/org/apache/tomcat/spdy/NetSupportSocket.java
Override
public void listen(final int port, String cert, String key) throws IOException {
ctx.getExecutor().execute(new Runnable() {
@Override
public void run() {
accept(port);
}
});
}
// in java/org/apache/tomcat/spdy/NetSupportSocket.java
Override
public void close() throws IOException {
socket.close();
}
// in java/org/apache/tomcat/spdy/NetSupportSocket.java
Override
public synchronized int write(byte[] data, int off, int len) throws IOException {
socket.getOutputStream().write(data, off, len);
return len;
}
// in java/org/apache/tomcat/spdy/NetSupportSocket.java
Override
public int read(byte[] data, int off, int len) throws IOException {
try {
return socket.getInputStream().read(data, off, len);
} catch (SocketTimeoutException ex) {
return 0;
}
}
// in java/org/apache/tomcat/spdy/SpdyContext.java
public void onAccept(Object socket) throws IOException {
}
// in java/org/apache/tomcat/spdy/SpdyContext.java
public void listen(int port, String cert, String key)
throws IOException {
}
// in java/org/apache/tomcat/spdy/SpdyContext.java
public void stop() throws IOException {
}
// in java/org/apache/tomcat/spdy/SpdyContext.java
public SpdyConnection getConnection(String host, int port) throws IOException {
return netSupport.getConnection(host, port);
}
// in java/org/apache/tomcat/spdy/SpdyContext.java
public final void listen(final int port, String cert, String key) throws IOException {
netSupport.listen(port, cert, key);
}
// in java/org/apache/tomcat/spdy/SpdyContext.java
public final void stop() throws IOException {
netSupport.stop();
}
// in java/org/apache/tomcat/spdy/SpdyContext.java
public void onStream(SpdyConnection spdyConnection, SpdyStream ch) throws IOException {
if (handler instanceof NonBlockingSpdyHandler) {
handler.onStream(spdyConnection, ch);
} else {
getExecutor().execute(ch);
}
}
// in java/org/apache/tomcat/util/net/NioChannel.java
public void reset() throws IOException {
bufHandler.getReadBuffer().clear();
bufHandler.getWriteBuffer().clear();
this.sendFile = false;
}
// in java/org/apache/tomcat/util/net/NioChannel.java
public boolean flush(boolean block, Selector s, long timeout)
throws IOException {
return true;
}
// in java/org/apache/tomcat/util/net/NioChannel.java
Override
public void close() throws IOException {
getIOChannel().socket().close();
getIOChannel().close();
}
// in java/org/apache/tomcat/util/net/NioChannel.java
public void close(boolean force) throws IOException {
if (isOpen() || force ) close();
}
// in java/org/apache/tomcat/util/net/NioChannel.java
Override
public int write(ByteBuffer src) throws IOException {
return sc.write(src);
}
// in java/org/apache/tomcat/util/net/NioChannel.java
Override
public int read(ByteBuffer dst) throws IOException {
return sc.read(dst);
}
// in java/org/apache/tomcat/util/net/NioChannel.java
public int handshake(boolean read, boolean write) throws IOException {
return 0;
}
// in java/org/apache/tomcat/util/net/NioChannel.java
public boolean flushOutbound() throws IOException {
return false;
}
// in java/org/apache/tomcat/util/net/SecureNioChannel.java
public void reset(SSLEngine engine) throws IOException {
this.sslEngine = engine;
reset();
}
// in java/org/apache/tomcat/util/net/SecureNioChannel.java
Override
public void reset() throws IOException {
super.reset();
netOutBuffer.position(0);
netOutBuffer.limit(0);
netInBuffer.position(0);
netInBuffer.limit(0);
handshakeComplete = false;
closed = false;
closing = false;
//initiate handshake
sslEngine.beginHandshake();
handshakeStatus = sslEngine.getHandshakeStatus();
}
// in java/org/apache/tomcat/util/net/SecureNioChannel.java
Override
public boolean flush(boolean block, Selector s, long timeout)
throws IOException {
if (!block) {
flush(netOutBuffer);
} else {
pool.write(netOutBuffer, this, s, timeout,block);
}
return !netOutBuffer.hasRemaining();
}
// in java/org/apache/tomcat/util/net/SecureNioChannel.java
protected boolean flush(ByteBuffer buf) throws IOException {
int remaining = buf.remaining();
if ( remaining > 0 ) {
int written = sc.write(buf);
return written >= remaining;
}else {
return true;
}
}
// in java/org/apache/tomcat/util/net/SecureNioChannel.java
Override
public int handshake(boolean read, boolean write) throws IOException {
if ( handshakeComplete ) return 0; //we have done our initial handshake
if (!flush(netOutBuffer)) return SelectionKey.OP_WRITE; //we still have data to write
SSLEngineResult handshake = null;
while (!handshakeComplete) {
switch ( handshakeStatus ) {
case NOT_HANDSHAKING: {
//should never happen
throw new IOException("NOT_HANDSHAKING during handshake");
}
case FINISHED: {
//we are complete if we have delivered the last package
handshakeComplete = !netOutBuffer.hasRemaining();
//return 0 if we are complete, otherwise we still have data to write
return handshakeComplete?0:SelectionKey.OP_WRITE;
}
case NEED_WRAP: {
//perform the wrap function
handshake = handshakeWrap(write);
if ( handshake.getStatus() == Status.OK ){
if (handshakeStatus == HandshakeStatus.NEED_TASK)
handshakeStatus = tasks();
} else {
//wrap should always work with our buffers
throw new IOException("Unexpected status:" + handshake.getStatus() + " during handshake WRAP.");
}
if ( handshakeStatus != HandshakeStatus.NEED_UNWRAP || (!flush(netOutBuffer)) ) {
//should actually return OP_READ if we have NEED_UNWRAP
return SelectionKey.OP_WRITE;
}
//fall down to NEED_UNWRAP on the same call, will result in a
//BUFFER_UNDERFLOW if it needs data
}
//$FALL-THROUGH$
case NEED_UNWRAP: {
//perform the unwrap function
handshake = handshakeUnwrap(read);
if ( handshake.getStatus() == Status.OK ) {
if (handshakeStatus == HandshakeStatus.NEED_TASK)
handshakeStatus = tasks();
} else if ( handshake.getStatus() == Status.BUFFER_UNDERFLOW ){
//read more data, reregister for OP_READ
return SelectionKey.OP_READ;
} else {
throw new IOException("Invalid handshake status:"+handshakeStatus+" during handshake UNWRAP.");
}//switch
break;
}
case NEED_TASK: {
handshakeStatus = tasks();
break;
}
default: throw new IllegalStateException("Invalid handshake status:"+handshakeStatus);
}//switch
}//while
//return 0 if we are complete, otherwise reregister for any activity that
//would cause this method to be called again.
return handshakeComplete?0:(SelectionKey.OP_WRITE|SelectionKey.OP_READ);
}
// in java/org/apache/tomcat/util/net/SecureNioChannel.java
protected SSLEngineResult handshakeWrap(boolean doWrite) throws IOException {
//this should never be called with a network buffer that contains data
//so we can clear it here.
netOutBuffer.clear();
//perform the wrap
SSLEngineResult result = sslEngine.wrap(bufHandler.getWriteBuffer(), netOutBuffer);
//prepare the results to be written
netOutBuffer.flip();
//set the status
handshakeStatus = result.getHandshakeStatus();
//optimization, if we do have a writable channel, write it now
if ( doWrite ) flush(netOutBuffer);
return result;
}
// in java/org/apache/tomcat/util/net/SecureNioChannel.java
protected SSLEngineResult handshakeUnwrap(boolean doread) throws IOException {
if (netInBuffer.position() == netInBuffer.limit()) {
//clear the buffer if we have emptied it out on data
netInBuffer.clear();
}
if ( doread ) {
//if we have data to read, read it
int read = sc.read(netInBuffer);
if (read == -1) throw new IOException("EOF encountered during handshake.");
}
SSLEngineResult result;
boolean cont = false;
//loop while we can perform pure SSLEngine data
do {
//prepare the buffer with the incoming data
netInBuffer.flip();
//call unwrap
result = sslEngine.unwrap(netInBuffer, bufHandler.getReadBuffer());
//compact the buffer, this is an optional method, wonder what would happen if we didn't
netInBuffer.compact();
//read in the status
handshakeStatus = result.getHandshakeStatus();
if ( result.getStatus() == SSLEngineResult.Status.OK &&
result.getHandshakeStatus() == HandshakeStatus.NEED_TASK ) {
//execute tasks if we need to
handshakeStatus = tasks();
}
//perform another unwrap?
cont = result.getStatus() == SSLEngineResult.Status.OK &&
handshakeStatus == HandshakeStatus.NEED_UNWRAP;
}while ( cont );
return result;
}
// in java/org/apache/tomcat/util/net/SecureNioChannel.java
Override
public void close() throws IOException {
if (closing) return;
closing = true;
sslEngine.closeOutbound();
if (!flush(netOutBuffer)) {
throw new IOException("Remaining data in the network buffer, can't send SSL close message, force a close with close(true) instead");
}
//prep the buffer for the close message
netOutBuffer.clear();
//perform the close, since we called sslEngine.closeOutbound
SSLEngineResult handshake = sslEngine.wrap(getEmptyBuf(), netOutBuffer);
//we should be in a close state
if (handshake.getStatus() != SSLEngineResult.Status.CLOSED) {
throw new IOException("Invalid close state, will not send network data.");
}
//prepare the buffer for writing
netOutBuffer.flip();
//if there is data to be written
flush(netOutBuffer);
//is the channel closed?
closed = (!netOutBuffer.hasRemaining() && (handshake.getHandshakeStatus() != HandshakeStatus.NEED_WRAP));
}
// in java/org/apache/tomcat/util/net/SecureNioChannel.java
Override
public void close(boolean force) throws IOException {
try {
close();
}finally {
if ( force || closed ) {
closed = true;
sc.socket().close();
sc.close();
}
}
}
// in java/org/apache/tomcat/util/net/SecureNioChannel.java
Override
public int read(ByteBuffer dst) throws IOException {
//if we want to take advantage of the expand function, make sure we only use the ApplicationBufferHandler's buffers
if ( dst != bufHandler.getReadBuffer() ) throw new IllegalArgumentException("You can only read using the application read buffer provided by the handler.");
//are we in the middle of closing or closed?
if ( closing || closed) return -1;
//did we finish our handshake?
if (!handshakeComplete) throw new IllegalStateException("Handshake incomplete, you must complete handshake before reading data.");
//read from the network
int netread = sc.read(netInBuffer);
//did we reach EOF? if so send EOF up one layer.
if (netread == -1) return -1;
//the data read
int read = 0;
//the SSL engine result
SSLEngineResult unwrap;
do {
//prepare the buffer
netInBuffer.flip();
//unwrap the data
unwrap = sslEngine.unwrap(netInBuffer, dst);
//compact the buffer
netInBuffer.compact();
if ( unwrap.getStatus()==Status.OK || unwrap.getStatus()==Status.BUFFER_UNDERFLOW ) {
//we did receive some data, add it to our total
read += unwrap.bytesProduced();
//perform any tasks if needed
if (unwrap.getHandshakeStatus() == HandshakeStatus.NEED_TASK) tasks();
//if we need more network data, then bail out for now.
if ( unwrap.getStatus() == Status.BUFFER_UNDERFLOW ) break;
}else if ( unwrap.getStatus()==Status.BUFFER_OVERFLOW && read>0 ) {
//buffer overflow can happen, if we have read data, then
//empty out the dst buffer before we do another read
break;
}else {
//here we should trap BUFFER_OVERFLOW and call expand on the buffer
//for now, throw an exception, as we initialized the buffers
//in the constructor
throw new IOException("Unable to unwrap data, invalid status: " + unwrap.getStatus());
}
} while ( (netInBuffer.position() != 0)); //continue to unwrapping as long as the input buffer has stuff
return (read);
}
// in java/org/apache/tomcat/util/net/SecureNioChannel.java
Override
public int write(ByteBuffer src) throws IOException {
if ( src == this.netOutBuffer ) {
//we can get here through a recursive call
//by using the NioBlockingSelector
int written = sc.write(src);
return written;
} else {
//make sure we can handle expand, and that we only use on buffer
if ( (!this.isSendFile()) && (src != bufHandler.getWriteBuffer()) ) throw new IllegalArgumentException("You can only write using the application write buffer provided by the handler.");
//are we closing or closed?
if ( closing || closed) throw new IOException("Channel is in closing state.");
//the number of bytes written
int written = 0;
if (!flush(netOutBuffer)) {
//we haven't emptied out the buffer yet
return written;
}
/*
* The data buffer is empty, we can reuse the entire buffer.
*/
netOutBuffer.clear();
SSLEngineResult result = sslEngine.wrap(src, netOutBuffer);
written = result.bytesConsumed();
netOutBuffer.flip();
if (result.getStatus() == Status.OK) {
if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) tasks();
} else {
throw new IOException("Unable to wrap data, invalid engine state: " +result.getStatus());
}
//force a flush
flush(netOutBuffer);
return written;
}
}
// in java/org/apache/tomcat/util/net/SecureNioChannel.java
Override
public boolean flushOutbound() throws IOException {
int remaining = netOutBuffer.remaining();
flush(netOutBuffer);
int remaining2= netOutBuffer.remaining();
return remaining2 < remaining;
}
// in java/org/apache/tomcat/util/net/NioBlockingSelector.java
public int write(ByteBuffer buf, NioChannel socket, long writeTimeout)
throws IOException {
SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector());
if ( key == null ) throw new IOException("Key no longer registered");
KeyReference reference = new KeyReference();
KeyAttachment att = (KeyAttachment) key.attachment();
int written = 0;
boolean timedout = false;
int keycount = 1; //assume we can write
long time = System.currentTimeMillis(); //start the timeout timer
try {
while ( (!timedout) && buf.hasRemaining()) {
if (keycount > 0) { //only write if we were registered for a write
int cnt = socket.write(buf); //write the data
if (cnt == -1)
throw new EOFException();
written += cnt;
if (cnt > 0) {
time = System.currentTimeMillis(); //reset our timeout timer
continue; //we successfully wrote, try again without a selector
}
}
try {
if ( att.getWriteLatch()==null || att.getWriteLatch().getCount()==0) att.startWriteLatch(1);
poller.add(att,SelectionKey.OP_WRITE,reference);
if (writeTimeout < 0) {
att.awaitWriteLatch(Long.MAX_VALUE,TimeUnit.MILLISECONDS);
} else {
att.awaitWriteLatch(writeTimeout,TimeUnit.MILLISECONDS);
}
}catch (InterruptedException ignore) {
Thread.interrupted();
}
if ( att.getWriteLatch()!=null && att.getWriteLatch().getCount()> 0) {
//we got interrupted, but we haven't received notification from the poller.
keycount = 0;
}else {
//latch countdown has happened
keycount = 1;
att.resetWriteLatch();
}
if (writeTimeout > 0 && (keycount == 0))
timedout = (System.currentTimeMillis() - time) >= writeTimeout;
} //while
if (timedout)
throw new SocketTimeoutException();
} finally {
poller.remove(att,SelectionKey.OP_WRITE);
if (timedout && reference.key!=null) {
poller.cancelKey(reference.key);
}
reference.key = null;
}
return written;
}
// in java/org/apache/tomcat/util/net/NioBlockingSelector.java
public int read(ByteBuffer buf, NioChannel socket, long readTimeout) throws IOException {
SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector());
if ( key == null ) throw new IOException("Key no longer registered");
KeyReference reference = new KeyReference();
KeyAttachment att = (KeyAttachment) key.attachment();
int read = 0;
boolean timedout = false;
int keycount = 1; //assume we can read
long time = System.currentTimeMillis(); //start the timeout timer
try {
while(!timedout) {
if (keycount > 0) { //only read if we were registered for a read
read = socket.read(buf);
if (read == -1)
throw new EOFException();
if (read > 0)
break;
}
try {
if ( att.getReadLatch()==null || att.getReadLatch().getCount()==0) att.startReadLatch(1);
poller.add(att,SelectionKey.OP_READ, reference);
if (readTimeout < 0) {
att.awaitReadLatch(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
} else {
att.awaitReadLatch(readTimeout, TimeUnit.MILLISECONDS);
}
}catch (InterruptedException ignore) {
Thread.interrupted();
}
if ( att.getReadLatch()!=null && att.getReadLatch().getCount()> 0) {
//we got interrupted, but we haven't received notification from the poller.
keycount = 0;
}else {
//latch countdown has happened
keycount = 1;
att.resetReadLatch();
}
if (readTimeout >= 0 && (keycount == 0))
timedout = (System.currentTimeMillis() - time) >= readTimeout;
} //while
if (timedout)
throw new SocketTimeoutException();
} finally {
poller.remove(att,SelectionKey.OP_READ);
if (timedout && reference.key!=null) {
poller.cancelKey(reference.key);
}
reference.key = null;
}
return read;
}
// in java/org/apache/tomcat/util/net/DefaultServerSocketFactory.java
Override
public ServerSocket createSocket (int port) throws IOException {
return new ServerSocket (port);
}
// in java/org/apache/tomcat/util/net/DefaultServerSocketFactory.java
Override
public ServerSocket createSocket (int port, int backlog)
throws IOException {
return new ServerSocket (port, backlog);
}
// in java/org/apache/tomcat/util/net/DefaultServerSocketFactory.java
Override
public ServerSocket createSocket (int port, int backlog,
InetAddress ifAddress) throws IOException {
return new ServerSocket (port, backlog, ifAddress);
}
// in java/org/apache/tomcat/util/net/DefaultServerSocketFactory.java
Override
public Socket acceptSocket(ServerSocket socket) throws IOException {
return socket.accept();
}
// in java/org/apache/tomcat/util/net/DefaultServerSocketFactory.java
Override
public void handshake(Socket sock) throws IOException {
// NOOP
}
// in java/org/apache/tomcat/util/net/jsse/JSSESupport.java
Override
public String getCipherSuite() throws IOException {
// Look up the current SSLSession
if (session == null)
return null;
return session.getCipherSuite();
}
// in java/org/apache/tomcat/util/net/jsse/JSSESupport.java
Override
public Object[] getPeerCertificateChain()
throws IOException {
return getPeerCertificateChain(false);
}
// in java/org/apache/tomcat/util/net/jsse/JSSESupport.java
Override
public Object[] getPeerCertificateChain(boolean force)
throws IOException {
// Look up the current SSLSession
if (session == null)
return null;
// Convert JSSE's certificate format to the ones we need
X509Certificate [] jsseCerts = null;
try {
jsseCerts = session.getPeerCertificateChain();
} catch(Exception bex) {
// ignore.
}
if (jsseCerts == null)
jsseCerts = new X509Certificate[0];
if(jsseCerts.length <= 0 && force && ssl != null) {
session.invalidate();
handShake();
session = ssl.getSession();
}
return getX509Certificates(session);
}
// in java/org/apache/tomcat/util/net/jsse/JSSESupport.java
protected void handShake() throws IOException {
if( ssl.getWantClientAuth() ) {
log.debug(sm.getString("jsseSupport.noCertWant"));
} else {
ssl.setNeedClientAuth(true);
}
if (ssl.getEnabledCipherSuites().length == 0) {
// Handshake is never going to be successful.
// Assume this is because handshakes are disabled
log.warn(sm.getString("jsseSupport.serverRenegDisabled"));
session.invalidate();
ssl.close();
return;
}
InputStream in = ssl.getInputStream();
int oldTimeout = ssl.getSoTimeout();
ssl.setSoTimeout(1000);
byte[] b = new byte[1];
listener.reset();
ssl.startHandshake();
int maxTries = 60; // 60 * 1000 = example 1 minute time out
for (int i = 0; i < maxTries; i++) {
if (log.isTraceEnabled())
log.trace("Reading for try #" + i);
try {
int read = in.read(b);
if (read > 0) {
// Shouldn't happen as all input should have been swallowed
// before trying to do the handshake. If it does, something
// went wrong so lets bomb out now.
throw new SSLException(
sm.getString("jsseSupport.unexpectedData"));
}
} catch(SSLException sslex) {
log.info(sm.getString("jsseSupport.clientCertError"), sslex);
throw sslex;
} catch (IOException e) {
// ignore - presumably the timeout
}
if (listener.completed) {
break;
}
}
ssl.setSoTimeout(oldTimeout);
if (listener.completed == false) {
throw new SocketException("SSL Cert handshake timeout");
}
}
// in java/org/apache/tomcat/util/net/jsse/JSSESupport.java
Override
public Integer getKeySize()
throws IOException {
// Look up the current SSLSession
SSLSupport.CipherData c_aux[]=ciphers;
if (session == null)
return null;
Integer keySize = null;
synchronized(keySizeCache) {
keySize = keySizeCache.get(session);
}
if (keySize == null) {
int size = 0;
String cipherSuite = session.getCipherSuite();
for (int i = 0; i < c_aux.length; i++) {
if (cipherSuite.indexOf(c_aux[i].phrase) >= 0) {
size = c_aux[i].keySize;
break;
}
}
keySize = Integer.valueOf(size);
synchronized(keySizeCache) {
keySizeCache.put(session, keySize);
}
}
return keySize;
}
// in java/org/apache/tomcat/util/net/jsse/JSSESupport.java
Override
public String getSessionId()
throws IOException {
// Look up the current SSLSession
if (session == null)
return null;
// Expose ssl_session (getId)
byte [] ssl_session = session.getId();
if ( ssl_session == null)
return null;
StringBuilder buf=new StringBuilder();
for(int x=0; x<ssl_session.length; x++) {
String digit=Integer.toHexString(ssl_session[x]);
if (digit.length()<2) buf.append('0');
if (digit.length()>2) digit=digit.substring(digit.length()-2);
buf.append(digit);
}
return buf.toString();
}
// in java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java
Override
public ServerSocket createSocket (int port)
throws IOException
{
init();
ServerSocket socket = sslProxy.createServerSocket(port);
initServerSocket(socket);
return socket;
}
// in java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java
Override
public ServerSocket createSocket (int port, int backlog)
throws IOException
{
init();
ServerSocket socket = sslProxy.createServerSocket(port, backlog);
initServerSocket(socket);
return socket;
}
// in java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java
Override
public ServerSocket createSocket (int port, int backlog,
InetAddress ifAddress)
throws IOException
{
init();
ServerSocket socket = sslProxy.createServerSocket(port, backlog,
ifAddress);
initServerSocket(socket);
return socket;
}
// in java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java
Override
public Socket acceptSocket(ServerSocket socket)
throws IOException
{
SSLSocket asock = null;
try {
asock = (SSLSocket)socket.accept();
} catch (SSLException e){
throw new SocketException("SSL handshake error" + e.toString());
}
return asock;
}
// in java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java
Override
public void handshake(Socket sock) throws IOException {
// We do getSession instead of startHandshake() so we can call this multiple times
SSLSession session = ((SSLSocket)sock).getSession();
if (session.getCipherSuite().equals("SSL_NULL_WITH_NULL_NULL"))
throw new IOException("SSL handshake failed. Ciper suite in SSL Session is SSL_NULL_WITH_NULL_NULL");
if (!allowUnsafeLegacyRenegotiation && !RFC_5746_SUPPORTED) {
// Prevent further handshakes by removing all cipher suites
((SSLSocket) sock).setEnabledCipherSuites(new String[0]);
}
}
// in java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java
protected KeyStore getKeystore(String type, String provider, String pass)
throws IOException {
String keystoreFile = endpoint.getKeystoreFile();
if (keystoreFile == null)
keystoreFile = defaultKeystoreFile;
return getStore(type, provider, keystoreFile, pass);
}
// in java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java
protected KeyStore getTrustStore(String keystoreType,
String keystoreProvider) throws IOException {
KeyStore trustStore = null;
String truststoreFile = endpoint.getTruststoreFile();
if(truststoreFile == null) {
truststoreFile = System.getProperty("javax.net.ssl.trustStore");
}
if(log.isDebugEnabled()) {
log.debug("Truststore = " + truststoreFile);
}
String truststorePassword = endpoint.getTruststorePass();
if( truststorePassword == null) {
truststorePassword =
System.getProperty("javax.net.ssl.trustStorePassword");
}
if(log.isDebugEnabled()) {
log.debug("TrustPass = " + truststorePassword);
}
String truststoreType = endpoint.getTruststoreType();
if( truststoreType == null) {
truststoreType = System.getProperty("javax.net.ssl.trustStoreType");
}
if(truststoreType == null) {
truststoreType = keystoreType;
}
if(log.isDebugEnabled()) {
log.debug("trustType = " + truststoreType);
}
String truststoreProvider = endpoint.getTruststoreProvider();
if( truststoreProvider == null) {
truststoreProvider =
System.getProperty("javax.net.ssl.trustStoreProvider");
}
if (truststoreProvider == null) {
truststoreProvider = keystoreProvider;
}
if(log.isDebugEnabled()) {
log.debug("trustProvider = " + truststoreProvider);
}
if (truststoreFile != null){
try {
trustStore = getStore(truststoreType, truststoreProvider,
truststoreFile, truststorePassword);
} catch (IOException ioe) {
Throwable cause = ioe.getCause();
if (cause instanceof UnrecoverableKeyException) {
// Log a warning we had a password issue
log.warn(sm.getString("jsse.invalid_truststore_password"),
cause);
// Re-try
trustStore = getStore(truststoreType, truststoreProvider,
truststoreFile, null);
} else {
// Something else went wrong - re-throw
throw ioe;
}
}
}
return trustStore;
}
// in java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java
private KeyStore getStore(String type, String provider, String path,
String pass) throws IOException {
KeyStore ks = null;
InputStream istream = null;
try {
if (provider == null) {
ks = KeyStore.getInstance(type);
} else {
ks = KeyStore.getInstance(type, provider);
}
if(!("PKCS11".equalsIgnoreCase(type) ||
"".equalsIgnoreCase(path))) {
File keyStoreFile = new File(path);
if (!keyStoreFile.isAbsolute()) {
keyStoreFile = new File(System.getProperty(
Constants.CATALINA_BASE_PROP), path);
}
istream = new FileInputStream(keyStoreFile);
}
char[] storePass = null;
if (pass != null && !"".equals(pass)) {
storePass = pass.toCharArray();
}
ks.load(istream, storePass);
} catch (FileNotFoundException fnfe) {
log.error(sm.getString("jsse.keystore_load_failed", type, path,
fnfe.getMessage()), fnfe);
throw fnfe;
} catch (IOException ioe) {
// May be expected when working with a trust store
// Re-throw. Caller will catch and log as required
throw ioe;
} catch(Exception ex) {
String msg = sm.getString("jsse.keystore_load_failed", type, path,
ex.getMessage());
log.error(msg, ex);
throw new IOException(msg);
} finally {
if (istream != null) {
try {
istream.close();
} catch (IOException ioe) {
// Do nothing
}
}
}
return ks;
}
// in java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java
void init() throws IOException {
try {
String clientAuthStr = endpoint.getClientAuth();
if("true".equalsIgnoreCase(clientAuthStr) ||
"yes".equalsIgnoreCase(clientAuthStr)) {
requireClientAuth = true;
} else if("want".equalsIgnoreCase(clientAuthStr)) {
wantClientAuth = true;
}
SSLContext context = createSSLContext();
context.init(getKeyManagers(), getTrustManagers(), null);
// Configure SSL session cache
SSLSessionContext sessionContext =
context.getServerSessionContext();
if (sessionContext != null) {
configureSessionContext(sessionContext);
}
// create proxy
sslProxy = context.getServerSocketFactory();
// Determine which cipher suites to enable
String requestedCiphers = endpoint.getCiphers();
enabledCiphers = getEnabledCiphers(requestedCiphers,
sslProxy.getSupportedCipherSuites());
allowUnsafeLegacyRenegotiation = "true".equals(
endpoint.getAllowUnsafeLegacyRenegotiation());
// Check the SSL config is OK
checkConfig();
} catch(Exception e) {
if( e instanceof IOException )
throw (IOException)e;
throw new IOException(e.getMessage(), e);
}
}
// in java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java
protected Collection<? extends CRL> getCRLs(String crlf)
throws IOException, CRLException, CertificateException {
File crlFile = new File(crlf);
if( !crlFile.isAbsolute() ) {
crlFile = new File(
System.getProperty(Constants.CATALINA_BASE_PROP), crlf);
}
Collection<? extends CRL> crls = null;
InputStream is = null;
try {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
is = new FileInputStream(crlFile);
crls = cf.generateCRLs(is);
} catch(IOException iex) {
throw iex;
} catch(CRLException crle) {
throw crle;
} catch(CertificateException ce) {
throw ce;
} finally {
if(is != null) {
try{
is.close();
} catch(Exception ex) {
// Ignore
}
}
}
return crls;
}
// in java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java
private void checkConfig() throws IOException {
// Create an unbound server socket
ServerSocket socket = sslProxy.createServerSocket();
initServerSocket(socket);
try {
// Set the timeout to 1ms as all we care about is if it throws an
// SSLException on accept.
socket.setSoTimeout(1);
socket.accept();
// Will never get here - no client can connect to an unbound port
} catch (SSLException ssle) {
// SSL configuration is invalid. Possibly cert doesn't match ciphers
IOException ioe = new IOException(sm.getString(
"jsse.invalid_ssl_conf", ssle.getMessage()));
ioe.initCause(ssle);
throw ioe;
} catch (Exception e) {
/*
* Possible ways of getting here
* socket.accept() throws a SecurityException
* socket.setSoTimeout() throws a SocketException
* socket.accept() throws some other exception (after a JDK change)
* In these cases the test won't work so carry on - essentially
* the behaviour before this patch
* socket.accept() throws a SocketTimeoutException
* In this case all is well so carry on
*/
} finally {
// Should be open here but just in case
if (!socket.isClosed()) {
socket.close();
}
}
}
// in java/org/apache/tomcat/util/net/NioSelectorPool.java
protected Selector getSharedSelector() throws IOException {
if (SHARED && SHARED_SELECTOR == null) {
synchronized ( NioSelectorPool.class ) {
if ( SHARED_SELECTOR == null ) {
synchronized (Selector.class) {
// Selector.open() isn't thread safe
// http://bugs.sun.com/view_bug.do?bug_id=6427854
// Affects 1.6.0_29, fixed in 1.7.0_01
SHARED_SELECTOR = Selector.open();
}
log.info("Using a shared selector for servlet write/read");
}
}
// in java/org/apache/tomcat/util/net/NioSelectorPool.java
public Selector get() throws IOException{
if ( SHARED ) {
return getSharedSelector();
}
if ( (!enabled) || active.incrementAndGet() >= maxSelectors ) {
if ( enabled ) active.decrementAndGet();
return null;
}
Selector s = null;
try {
s = selectors.size()>0?selectors.poll():null;
if (s == null) {
synchronized (Selector.class) {
// Selector.open() isn't thread safe
// http://bugs.sun.com/view_bug.do?bug_id=6427854
// Affects 1.6.0_29, fixed in 1.7.0_01
s = Selector.open();
}
}
else spare.decrementAndGet();
}
// in java/org/apache/tomcat/util/net/NioSelectorPool.java
public void put(Selector s) throws IOException {
if ( SHARED ) return;
if ( enabled ) active.decrementAndGet();
if ( enabled && (maxSpareSelectors==-1 || spare.get() < Math.min(maxSpareSelectors,maxSelectors)) ) {
spare.incrementAndGet();
selectors.offer(s);
}
else s.close();
}
// in java/org/apache/tomcat/util/net/NioSelectorPool.java
public void close() throws IOException {
enabled = false;
Selector s;
while ( (s = selectors.poll()) != null ) s.close();
spare.set(0);
active.set(0);
if (blockingSelector!=null) {
blockingSelector.close();
}
if ( SHARED && getSharedSelector()!=null ) {
getSharedSelector().close();
SHARED_SELECTOR = null;
}
}
// in java/org/apache/tomcat/util/net/NioSelectorPool.java
public void open() throws IOException {
enabled = true;
getSharedSelector();
if (SHARED) {
blockingSelector = new NioBlockingSelector();
blockingSelector.open(getSharedSelector());
}
}
// in java/org/apache/tomcat/util/net/NioSelectorPool.java
public int write(ByteBuffer buf, NioChannel socket, Selector selector, long writeTimeout) throws IOException {
return write(buf,socket,selector,writeTimeout,true);
}
// in java/org/apache/tomcat/util/net/NioSelectorPool.java
public int write(ByteBuffer buf, NioChannel socket, Selector selector,
long writeTimeout, boolean block) throws IOException {
if ( SHARED && block ) {
return blockingSelector.write(buf,socket,writeTimeout);
}
SelectionKey key = null;
int written = 0;
boolean timedout = false;
int keycount = 1; //assume we can write
long time = System.currentTimeMillis(); //start the timeout timer
try {
while ( (!timedout) && buf.hasRemaining() ) {
int cnt = 0;
if ( keycount > 0 ) { //only write if we were registered for a write
cnt = socket.write(buf); //write the data
if (cnt == -1) throw new EOFException();
written += cnt;
if (cnt > 0) {
time = System.currentTimeMillis(); //reset our timeout timer
continue; //we successfully wrote, try again without a selector
}
if (cnt==0 && (!block)) break; //don't block
}
if ( selector != null ) {
//register OP_WRITE to the selector
if (key==null) key = socket.getIOChannel().register(selector, SelectionKey.OP_WRITE);
else key.interestOps(SelectionKey.OP_WRITE);
keycount = selector.select(writeTimeout);
}
if (writeTimeout > 0 && (selector == null || keycount == 0) ) timedout = (System.currentTimeMillis()-time)>=writeTimeout;
}//while
if ( timedout ) throw new SocketTimeoutException();
} finally {
if (key != null) {
key.cancel();
if (selector != null) selector.selectNow();//removes the key from this selector
}
}
return written;
}
// in java/org/apache/tomcat/util/net/NioSelectorPool.java
public int read(ByteBuffer buf, NioChannel socket, Selector selector, long readTimeout) throws IOException {
return read(buf,socket,selector,readTimeout,true);
}
// in java/org/apache/tomcat/util/net/NioSelectorPool.java
public int read(ByteBuffer buf, NioChannel socket, Selector selector, long readTimeout, boolean block) throws IOException {
if ( SHARED && block ) {
return blockingSelector.read(buf,socket,readTimeout);
}
SelectionKey key = null;
int read = 0;
boolean timedout = false;
int keycount = 1; //assume we can write
long time = System.currentTimeMillis(); //start the timeout timer
try {
while ( (!timedout) ) {
int cnt = 0;
if ( keycount > 0 ) { //only read if we were registered for a read
cnt = socket.read(buf);
if (cnt == -1) throw new EOFException();
read += cnt;
if (cnt > 0) continue; //read some more
if (cnt==0 && (read>0 || (!block) ) ) break; //we are done reading
}
if ( selector != null ) {//perform a blocking read
//register OP_WRITE to the selector
if (key==null) key = socket.getIOChannel().register(selector, SelectionKey.OP_READ);
else key.interestOps(SelectionKey.OP_READ);
keycount = selector.select(readTimeout);
}
if (readTimeout > 0 && (selector == null || keycount == 0) ) timedout = (System.currentTimeMillis()-time)>=readTimeout;
}//while
if ( timedout ) throw new SocketTimeoutException();
} finally {
if (key != null) {
key.cancel();
if (selector != null) selector.selectNow();//removes the key from this selector
}
}
return read;
}
// in java/org/apache/tomcat/util/http/parser/SimpleCharStream.java
protected void FillBuff() throws java.io.IOException
{
if (maxNextCharInd == available)
{
if (available == bufsize)
{
if (tokenBegin > 2048)
{
bufpos = maxNextCharInd = 0;
available = tokenBegin;
}
else if (tokenBegin < 0)
bufpos = maxNextCharInd = 0;
else
ExpandBuff(false);
}
else if (available > tokenBegin)
available = bufsize;
else if ((tokenBegin - available) < 2048)
ExpandBuff(true);
else
available = tokenBegin;
}
int i;
try {
if ((i = inputStream.read(buffer, maxNextCharInd, available - maxNextCharInd)) == -1)
{
inputStream.close();
throw new java.io.IOException();
}
else
maxNextCharInd += i;
return;
}
catch(java.io.IOException e) {
--bufpos;
backup(0);
if (tokenBegin == -1)
tokenBegin = bufpos;
throw e;
}
}
// in java/org/apache/tomcat/util/http/parser/SimpleCharStream.java
public char BeginToken() throws java.io.IOException
{
tokenBegin = -1;
char c = readChar();
tokenBegin = bufpos;
return c;
}
// in java/org/apache/tomcat/util/http/parser/SimpleCharStream.java
public char readChar() throws java.io.IOException
{
if (inBuf > 0)
{
--inBuf;
if (++bufpos == bufsize)
bufpos = 0;
return buffer[bufpos];
}
if (++bufpos >= maxNextCharInd)
FillBuff();
char c = buffer[bufpos];
UpdateLineColumn(c);
return c;
}
// in java/org/apache/tomcat/util/http/Parameters.java
private void urlDecode(ByteChunk bc)
throws IOException {
if( urlDec==null ) {
urlDec=new UDecoder();
}
urlDec.convert(bc, true);
}
// in java/org/apache/tomcat/util/http/fileupload/MultipartStream.java
public byte readByte() throws IOException {
// Buffer depleted ?
if (head == tail) {
head = 0;
// Refill.
tail = input.read(buffer, head, bufSize);
if (tail == -1) {
// No more data available.
throw new IOException("No more data is available");
}
if (notifier != null) {
notifier.noteBytesRead(tail);
}
}
return buffer[head++];
}
// in java/org/apache/tomcat/util/http/fileupload/MultipartStream.java
public int readBodyData(OutputStream output)
throws MalformedStreamException, IOException {
final InputStream istream = newInputStream();
return (int) Streams.copy(istream, output, false);
}
// in java/org/apache/tomcat/util/http/fileupload/MultipartStream.java
public int discardBodyData()
throws MalformedStreamException,
IOException {
return readBodyData(null);
}
// in java/org/apache/tomcat/util/http/fileupload/MultipartStream.java
public boolean skipPreamble()
throws IOException {
// First delimiter may be not preceeded with a CRLF.
System.arraycopy(boundary, 2, boundary, 0, boundary.length - 2);
boundaryLength = boundary.length - 2;
try {
// Discard all data up to the delimiter.
discardBodyData();
// Read boundary - if succeeded, the stream contains an
// encapsulation.
return readBoundary();
} catch (MalformedStreamException e) {
return false;
} finally {
// Restore delimiter.
System.arraycopy(boundary, 0, boundary, 2, boundary.length - 2);
boundaryLength = boundary.length;
boundary[0] = CR;
boundary[1] = LF;
}
}
// in java/org/apache/tomcat/util/http/fileupload/MultipartStream.java
Override
public int available() throws IOException {
if (pos == -1) {
return tail - head - pad;
}
return pos - head;
}
// in java/org/apache/tomcat/util/http/fileupload/MultipartStream.java
Override
public int read() throws IOException {
if (closed) {
throw new FileItemStream.ItemSkippedException();
}
if (available() == 0) {
if (makeAvailable() == 0) {
return -1;
}
}
++total;
int b = buffer[head++];
if (b >= 0) {
return b;
}
return b + BYTE_POSITIVE_OFFSET;
}
// in java/org/apache/tomcat/util/http/fileupload/MultipartStream.java
Override
public int read(byte[] b, int off, int len) throws IOException {
if (closed) {
throw new FileItemStream.ItemSkippedException();
}
if (len == 0) {
return 0;
}
int res = available();
if (res == 0) {
res = makeAvailable();
if (res == 0) {
return -1;
}
}
res = Math.min(res, len);
System.arraycopy(buffer, head, b, off, res);
head += res;
total += res;
return res;
}
// in java/org/apache/tomcat/util/http/fileupload/MultipartStream.java
Override
public void close() throws IOException {
close(false);
}
// in java/org/apache/tomcat/util/http/fileupload/MultipartStream.java
public void close(boolean pCloseUnderlying) throws IOException {
if (closed) {
return;
}
if (pCloseUnderlying) {
closed = true;
input.close();
} else {
for (;;) {
int av = available();
if (av == 0) {
av = makeAvailable();
if (av == 0) {
break;
}
}
skip(av);
}
}
closed = true;
}
// in java/org/apache/tomcat/util/http/fileupload/MultipartStream.java
Override
public long skip(long bytes) throws IOException {
if (closed) {
throw new FileItemStream.ItemSkippedException();
}
int av = available();
if (av == 0) {
av = makeAvailable();
if (av == 0) {
return 0;
}
}
long res = Math.min(av, bytes);
head += res;
return res;
}
// in java/org/apache/tomcat/util/http/fileupload/MultipartStream.java
private int makeAvailable() throws IOException {
if (pos != -1) {
return 0;
}
// Move the data to the beginning of the buffer.
total += tail - head - pad;
System.arraycopy(buffer, tail - pad, buffer, 0, pad);
// Refill buffer with new data.
head = 0;
tail = pad;
for (;;) {
int bytesRead = input.read(buffer, tail, bufSize - tail);
if (bytesRead == -1) {
// The last pad amount is left in the buffer.
// Boundary can't be in there so signal an error
// condition.
final String msg = "Stream ended unexpectedly";
throw new MalformedStreamException(msg);
}
if (notifier != null) {
notifier.noteBytesRead(bytesRead);
}
tail += bytesRead;
findSeparator();
int av = available();
if (av > 0 || pos != -1) {
return av;
}
}
}
// in java/org/apache/tomcat/util/http/fileupload/IOUtils.java
public static int copy(InputStream input, OutputStream output) throws IOException {
long count = copyLarge(input, output);
if (count > Integer.MAX_VALUE) {
return -1;
}
return (int) count;
}
// in java/org/apache/tomcat/util/http/fileupload/IOUtils.java
public static long copyLarge(InputStream input, OutputStream output)
throws IOException {
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
long count = 0;
int n = 0;
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
}
return count;
}
// in java/org/apache/tomcat/util/http/fileupload/disk/DiskFileItem.java
Override
public InputStream getInputStream()
throws IOException {
if (!isInMemory()) {
return new FileInputStream(dfos.getFile());
}
if (cachedContent == null) {
cachedContent = dfos.getData();
}
return new ByteArrayInputStream(cachedContent);
}
// in java/org/apache/tomcat/util/http/fileupload/disk/DiskFileItem.java
Override
public OutputStream getOutputStream()
throws IOException {
if (dfos == null) {
File outputFile = getTempFile();
dfos = new DeferredFileOutputStream(sizeThreshold, outputFile);
}
return dfos;
}
// in java/org/apache/tomcat/util/http/fileupload/disk/DiskFileItem.java
private void writeObject(ObjectOutputStream out) throws IOException {
// Read the data
if (dfos.isInMemory()) {
cachedContent = get();
} else {
cachedContent = null;
dfosFile = dfos.getFile();
}
// write out values
out.defaultWriteObject();
}
// in java/org/apache/tomcat/util/http/fileupload/disk/DiskFileItem.java
private void readObject(ObjectInputStream in)
throws IOException, ClassNotFoundException {
// read values
in.defaultReadObject();
OutputStream output = getOutputStream();
if (cachedContent != null) {
output.write(cachedContent);
} else {
FileInputStream input = new FileInputStream(dfosFile);
IOUtils.copy(input, output);
dfosFile.delete();
dfosFile = null;
}
output.close();
cachedContent = null;
}
// in java/org/apache/tomcat/util/http/fileupload/servlet/ServletRequestContext.java
Override
public InputStream getInputStream() throws IOException {
return request.getInputStream();
}
// in java/org/apache/tomcat/util/http/fileupload/servlet/ServletFileUpload.java
public FileItemIterator getItemIterator(HttpServletRequest request)
throws FileUploadException, IOException {
return super.getItemIterator(new ServletRequestContext(request));
}
// in java/org/apache/tomcat/util/http/fileupload/DeferredFileOutputStream.java
Override
protected OutputStream getStream() throws IOException
{
return currentOutputStream;
}
// in java/org/apache/tomcat/util/http/fileupload/DeferredFileOutputStream.java
Override
protected void thresholdReached() throws IOException
{
if (prefix != null) {
outputFile = File.createTempFile(prefix, suffix, directory);
}
FileOutputStream fos = new FileOutputStream(outputFile);
memoryOutputStream.writeTo(fos);
currentOutputStream = fos;
memoryOutputStream = null;
}
// in java/org/apache/tomcat/util/http/fileupload/DeferredFileOutputStream.java
Override
public void close() throws IOException
{
super.close();
closed = true;
}
// in java/org/apache/tomcat/util/http/fileupload/DeferredFileOutputStream.java
public void writeTo(OutputStream out) throws IOException
{
// we may only need to check if this is closed if we are working with a file
// but we should force the habit of closing wether we are working with
// a file or memory.
if (!closed)
{
throw new IOException("Stream not closed");
}
if(isInMemory())
{
memoryOutputStream.writeTo(out);
}
else
{
FileInputStream fis = new FileInputStream(outputFile);
try {
IOUtils.copy(fis, out);
} finally {
IOUtils.closeQuietly(fis);
}
}
}
// in java/org/apache/tomcat/util/http/fileupload/FileUploadBase.java
public FileItemIterator getItemIterator(RequestContext ctx)
throws FileUploadException, IOException {
return new FileItemIteratorImpl(ctx);
}
// in java/org/apache/tomcat/util/http/fileupload/FileUploadBase.java
Override
protected void raiseError(long pSizeMax, long pCount)
throws IOException {
itemStream.close(true);
FileSizeLimitExceededException e =
new FileSizeLimitExceededException(
"The field " + fieldName
+ " exceeds its maximum permitted "
+ " size of " + pSizeMax
+ " bytes.",
pCount, pSizeMax);
e.setFieldName(fieldName);
e.setFileName(name);
throw new FileUploadIOException(e);
}
// in java/org/apache/tomcat/util/http/fileupload/FileUploadBase.java
Override
public InputStream openStream() throws IOException {
if (opened) {
throw new IllegalStateException(
"The stream was already opened.");
}
if (((Closeable) stream).isClosed()) {
throw new FileItemStream.ItemSkippedException();
}
return stream;
}
// in java/org/apache/tomcat/util/http/fileupload/FileUploadBase.java
void close() throws IOException {
stream.close();
}
// in java/org/apache/tomcat/util/http/fileupload/FileUploadBase.java
Override
protected void raiseError(long pSizeMax, long pCount)
throws IOException {
FileUploadException ex =
new SizeLimitExceededException(
"the request was rejected because"
+ " its size (" + pCount
+ ") exceeds the configured maximum"
+ " (" + pSizeMax + ")",
pCount, pSizeMax);
throw new FileUploadIOException(ex);
}
// in java/org/apache/tomcat/util/http/fileupload/FileUploadBase.java
private boolean findNextItem() throws IOException {
if (eof) {
return false;
}
if (currentItem != null) {
currentItem.close();
currentItem = null;
}
for (;;) {
boolean nextPart;
if (skipPreamble) {
nextPart = multi.skipPreamble();
} else {
nextPart = multi.readBoundary();
}
if (!nextPart) {
if (currentFieldName == null) {
// Outer multipart terminated -> No more data
eof = true;
return false;
}
// Inner multipart terminated -> Return to parsing the outer
multi.setBoundary(boundary);
currentFieldName = null;
continue;
}
FileItemHeaders headers = getParsedHeaders(multi.readHeaders());
if (currentFieldName == null) {
// We're parsing the outer multipart
String fieldName = getFieldName(headers);
if (fieldName != null) {
String subContentType = headers.getHeader(CONTENT_TYPE);
if (subContentType != null
&& subContentType.toLowerCase(Locale.ENGLISH)
.startsWith(MULTIPART_MIXED)) {
currentFieldName = fieldName;
// Multiple files associated with this field name
byte[] subBoundary = getBoundary(subContentType);
multi.setBoundary(subBoundary);
skipPreamble = true;
continue;
}
String fileName = getFileName(headers);
currentItem = new FileItemStreamImpl(fileName,
fieldName, headers.getHeader(CONTENT_TYPE),
fileName == null, getContentLength(headers));
currentItem.setHeaders(headers);
notifier.noteItem();
itemValid = true;
return true;
}
} else {
String fileName = getFileName(headers);
if (fileName != null) {
currentItem = new FileItemStreamImpl(fileName,
currentFieldName,
headers.getHeader(CONTENT_TYPE),
false, getContentLength(headers));
currentItem.setHeaders(headers);
notifier.noteItem();
itemValid = true;
return true;
}
}
multi.discardBodyData();
}
}
// in java/org/apache/tomcat/util/http/fileupload/FileUploadBase.java
Override
public boolean hasNext() throws FileUploadException, IOException {
if (eof) {
return false;
}
if (itemValid) {
return true;
}
return findNextItem();
}
// in java/org/apache/tomcat/util/http/fileupload/FileUploadBase.java
Override
public FileItemStream next() throws FileUploadException, IOException {
if (eof || (!itemValid && !hasNext())) {
throw new NoSuchElementException();
}
itemValid = false;
return currentItem;
}
// in java/org/apache/tomcat/util/http/fileupload/FileDeleteStrategy.java
public void delete(File fileToDelete) throws IOException {
if (fileToDelete.exists() && doDelete(fileToDelete) == false) {
throw new IOException("Deletion failed: " + fileToDelete);
}
}
// in java/org/apache/tomcat/util/http/fileupload/FileDeleteStrategy.java
protected boolean doDelete(File fileToDelete) throws IOException {
return fileToDelete.delete();
}
// in java/org/apache/tomcat/util/http/fileupload/FileDeleteStrategy.java
Override
protected boolean doDelete(File fileToDelete) throws IOException {
FileUtils.forceDelete(fileToDelete);
return true;
}
// in java/org/apache/tomcat/util/http/fileupload/ByteArrayOutputStream.java
public synchronized int write(InputStream in) throws IOException {
int readCount = 0;
int inBufferPos = count - filledBufferSum;
int n = in.read(currentBuffer, inBufferPos, currentBuffer.length - inBufferPos);
while (n != -1) {
readCount += n;
inBufferPos += n;
count += n;
if (inBufferPos == currentBuffer.length) {
needNewBuffer(currentBuffer.length);
inBufferPos = 0;
}
n = in.read(currentBuffer, inBufferPos, currentBuffer.length - inBufferPos);
}
return readCount;
}
// in java/org/apache/tomcat/util/http/fileupload/ByteArrayOutputStream.java
Override
public void close() throws IOException {
//nop
}
// in java/org/apache/tomcat/util/http/fileupload/ByteArrayOutputStream.java
public synchronized void writeTo(OutputStream out) throws IOException {
int remaining = count;
for (int i = 0; i < buffers.size(); i++) {
byte[] buf = getBuffer(i);
int c = Math.min(buf.length, remaining);
out.write(buf, 0, c);
remaining -= c;
if (remaining == 0) {
break;
}
}
}
// in java/org/apache/tomcat/util/http/fileupload/FileUtils.java
public static void deleteDirectory(File directory) throws IOException {
if (!directory.exists()) {
return;
}
cleanDirectory(directory);
if (!directory.delete()) {
String message =
"Unable to delete directory " + directory + ".";
throw new IOException(message);
}
}
// in java/org/apache/tomcat/util/http/fileupload/FileUtils.java
public static void cleanDirectory(File directory) throws IOException {
if (!directory.exists()) {
String message = directory + " does not exist";
throw new IllegalArgumentException(message);
}
if (!directory.isDirectory()) {
String message = directory + " is not a directory";
throw new IllegalArgumentException(message);
}
File[] files = directory.listFiles();
if (files == null) { // null if security restricted
throw new IOException("Failed to list contents of " + directory);
}
IOException exception = null;
for (int i = 0; i < files.length; i++) {
File file = files[i];
try {
forceDelete(file);
} catch (IOException ioe) {
exception = ioe;
}
}
if (null != exception) {
throw exception;
}
}
// in java/org/apache/tomcat/util/http/fileupload/FileUtils.java
public static void forceDelete(File file) throws IOException {
if (file.isDirectory()) {
deleteDirectory(file);
} else {
boolean filePresent = file.exists();
if (!file.delete()) {
if (!filePresent){
throw new FileNotFoundException("File does not exist: " + file);
}
String message =
"Unable to delete file: " + file;
throw new IOException(message);
}
}
}
// in java/org/apache/tomcat/util/http/fileupload/FileUtils.java
public static void forceDeleteOnExit(File file) throws IOException {
if (file.isDirectory()) {
deleteDirectoryOnExit(file);
} else {
file.deleteOnExit();
}
}
// in java/org/apache/tomcat/util/http/fileupload/FileUtils.java
private static void deleteDirectoryOnExit(File directory) throws IOException {
if (!directory.exists()) {
return;
}
cleanDirectoryOnExit(directory);
directory.deleteOnExit();
}
// in java/org/apache/tomcat/util/http/fileupload/FileUtils.java
private static void cleanDirectoryOnExit(File directory) throws IOException {
if (!directory.exists()) {
String message = directory + " does not exist";
throw new IllegalArgumentException(message);
}
if (!directory.isDirectory()) {
String message = directory + " is not a directory";
throw new IllegalArgumentException(message);
}
File[] files = directory.listFiles();
if (files == null) { // null if security restricted
throw new IOException("Failed to list contents of " + directory);
}
IOException exception = null;
for (int i = 0; i < files.length; i++) {
File file = files[i];
try {
forceDeleteOnExit(file);
} catch (IOException ioe) {
exception = ioe;
}
}
if (null != exception) {
throw exception;
}
}
// in java/org/apache/tomcat/util/http/fileupload/util/Streams.java
public static long copy(InputStream pInputStream,
OutputStream pOutputStream, boolean pClose)
throws IOException {
return copy(pInputStream, pOutputStream, pClose,
new byte[DEFAULT_BUFFER_SIZE]);
}
// in java/org/apache/tomcat/util/http/fileupload/util/Streams.java
public static long copy(InputStream pIn,
OutputStream pOut, boolean pClose,
byte[] pBuffer)
throws IOException {
OutputStream out = pOut;
InputStream in = pIn;
try {
long total = 0;
for (;;) {
int res = in.read(pBuffer);
if (res == -1) {
break;
}
if (res > 0) {
total += res;
if (out != null) {
out.write(pBuffer, 0, res);
}
}
}
if (out != null) {
if (pClose) {
out.close();
} else {
out.flush();
}
out = null;
}
in.close();
in = null;
return total;
} finally {
if (in != null) {
try {
in.close();
} catch (IOException ioe) {
/* Ignore me */
}
}
if (pClose && out != null) {
try {
out.close();
} catch (IOException ioe) {
/* Ignore me */
}
}
}
}
// in java/org/apache/tomcat/util/http/fileupload/util/Streams.java
public static String asString(InputStream pStream) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
copy(pStream, baos, true);
return baos.toString();
}
// in java/org/apache/tomcat/util/http/fileupload/util/Streams.java
public static String asString(InputStream pStream, String pEncoding)
throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
copy(pStream, baos, true);
return baos.toString(pEncoding);
}
// in java/org/apache/tomcat/util/http/fileupload/util/LimitedInputStream.java
private void checkLimit() throws IOException {
if (count > sizeMax) {
raiseError(sizeMax, count);
}
}
// in java/org/apache/tomcat/util/http/fileupload/util/LimitedInputStream.java
Override
public int read() throws IOException {
int res = super.read();
if (res != -1) {
count++;
checkLimit();
}
return res;
}
// in java/org/apache/tomcat/util/http/fileupload/util/LimitedInputStream.java
Override
public int read(byte[] b, int off, int len) throws IOException {
int res = super.read(b, off, len);
if (res > 0) {
count += res;
checkLimit();
}
return res;
}
// in java/org/apache/tomcat/util/http/fileupload/util/LimitedInputStream.java
Override
public boolean isClosed() throws IOException {
return closed;
}
// in java/org/apache/tomcat/util/http/fileupload/util/LimitedInputStream.java
Override
public void close() throws IOException {
closed = true;
super.close();
}
// in java/org/apache/tomcat/util/http/fileupload/ThresholdingOutputStream.java
Override
public void write(int b) throws IOException
{
checkThreshold(1);
getStream().write(b);
written++;
}
// in java/org/apache/tomcat/util/http/fileupload/ThresholdingOutputStream.java
Override
public void write(byte b[]) throws IOException
{
checkThreshold(b.length);
getStream().write(b);
written += b.length;
}
// in java/org/apache/tomcat/util/http/fileupload/ThresholdingOutputStream.java
Override
public void write(byte b[], int off, int len) throws IOException
{
checkThreshold(len);
getStream().write(b, off, len);
written += len;
}
// in java/org/apache/tomcat/util/http/fileupload/ThresholdingOutputStream.java
Override
public void flush() throws IOException
{
getStream().flush();
}
// in java/org/apache/tomcat/util/http/fileupload/ThresholdingOutputStream.java
Override
public void close() throws IOException
{
try
{
flush();
}
catch (IOException ignored)
{
// ignore
}
getStream().close();
}
// in java/org/apache/tomcat/util/http/fileupload/ThresholdingOutputStream.java
protected void checkThreshold(int count) throws IOException
{
if (!thresholdExceeded && (written + count > threshold))
{
thresholdExceeded = true;
thresholdReached();
}
}
// in java/org/apache/tomcat/util/buf/MessageBytes.java
public void duplicate( MessageBytes src ) throws IOException
{
switch( src.getType() ) {
case MessageBytes.T_BYTES:
type=T_BYTES;
ByteChunk bc=src.getByteChunk();
byteC.allocate( 2 * bc.getLength(), -1 );
byteC.append( bc );
break;
case MessageBytes.T_CHARS:
type=T_CHARS;
CharChunk cc=src.getCharChunk();
charC.allocate( 2 * cc.getLength(), -1 );
charC.append( cc );
break;
case MessageBytes.T_STR:
type=T_STR;
String sc=src.getString();
this.setString( sc );
break;
}
}
// in java/org/apache/tomcat/util/buf/B2CConverter.java
public void convert( ByteChunk bb, CharChunk cb, int limit)
throws IOException
{
iis.setByteChunk( bb );
try {
// read from the reader
int bbLengthBeforeRead = 0;
while( limit > 0 ) {
int size = limit < BUFFER_SIZE ? limit : BUFFER_SIZE;
bbLengthBeforeRead = bb.getLength();
int cnt=conv.read( result, 0, size );
if( cnt <= 0 ) {
// End of stream ! - we may be in a bad state
if(log.isDebugEnabled()) {
log.debug("B2CConverter: EOF");
}
return;
}
if(log.isDebugEnabled()) {
log.debug("B2CConverter: Converted: " +
new String(result, 0, cnt));
}
cb.append( result, 0, cnt );
limit = limit - (bbLengthBeforeRead - bb.getLength());
}
} catch( IOException ex) {
if(log.isDebugEnabled()) {
log.debug("B2CConverter: Reseting the converter " + ex.toString());
}
reset();
throw ex;
}
}
// in java/org/apache/tomcat/util/buf/B2CConverter.java
public void reset()
throws IOException
{
// destroy the reader/iis
iis=new IntermediateInputStream();
conv = new ReadConvertor(iis, getCharset(encoding));
}
// in java/org/apache/tomcat/util/buf/B2CConverter.java
Override
public final void close() throws IOException {
// NOTHING
// Calling super.close() would reset out and cb.
}
// in java/org/apache/tomcat/util/buf/B2CConverter.java
Override
public final int read(char cbuf[], int off, int len)
throws IOException
{
// will do the conversion and call write on the output stream
return super.read( cbuf, off, len );
}
// in java/org/apache/tomcat/util/buf/B2CConverter.java
Override
public final void close() throws IOException {
// shouldn't be called - we filter it out in writer
throw new IOException("close() called - shouldn't happen ");
}
// in java/org/apache/tomcat/util/buf/B2CConverter.java
Override
public final int read(byte cbuf[], int off, int len) throws IOException {
return bc.substract(cbuf, off, len);
}
// in java/org/apache/tomcat/util/buf/B2CConverter.java
Override
public final int read() throws IOException {
return bc.substract();
}
// in java/org/apache/tomcat/util/buf/CharChunk.java
public void append( char b )
throws IOException
{
makeSpace( 1 );
// couldn't make space
if( limit >0 && end >= limit ) {
flushBuffer();
}
buff[end++]=b;
}
// in java/org/apache/tomcat/util/buf/CharChunk.java
public void append( CharChunk src )
throws IOException
{
append( src.getBuffer(), src.getOffset(), src.getLength());
}
// in java/org/apache/tomcat/util/buf/CharChunk.java
public void append( char src[], int off, int len )
throws IOException
{
// will grow, up to limit
makeSpace( len );
// if we don't have limit: makeSpace can grow as it wants
if( limit < 0 ) {
// assert: makeSpace made enough space
System.arraycopy( src, off, buff, end, len );
end+=len;
return;
}
// Optimize on a common case.
// If the source is going to fill up all the space in buffer, may
// as well write it directly to the output, and avoid an extra copy
if ( optimizedWrite && len == limit && end == start && out != null ) {
out.realWriteChars( src, off, len );
return;
}
// if we have limit and we're below
if( len <= limit - end ) {
// makeSpace will grow the buffer to the limit,
// so we have space
System.arraycopy( src, off, buff, end, len );
end+=len;
return;
}
// need more space than we can afford, need to flush
// buffer
// the buffer is already at ( or bigger than ) limit
// Optimization:
// If len-avail < length ( i.e. after we fill the buffer with
// what we can, the remaining will fit in the buffer ) we'll just
// copy the first part, flush, then copy the second part - 1 write
// and still have some space for more. We'll still have 2 writes, but
// we write more on the first.
if( len + end < 2 * limit ) {
/* If the request length exceeds the size of the output buffer,
flush the output buffer and then write the data directly.
We can't avoid 2 writes, but we can write more on the second
*/
int avail=limit-end;
System.arraycopy(src, off, buff, end, avail);
end += avail;
flushBuffer();
System.arraycopy(src, off+avail, buff, end, len - avail);
end+= len - avail;
} else { // len > buf.length + avail
// long write - flush the buffer and write the rest
// directly from source
flushBuffer();
out.realWriteChars( src, off, len );
}
}
// in java/org/apache/tomcat/util/buf/CharChunk.java
public void append(String s) throws IOException {
append(s, 0, s.length());
}
// in java/org/apache/tomcat/util/buf/CharChunk.java
public void append(String s, int off, int len) throws IOException {
if (s==null) {
return;
}
// will grow, up to limit
makeSpace( len );
// if we don't have limit: makeSpace can grow as it wants
if( limit < 0 ) {
// assert: makeSpace made enough space
s.getChars(off, off+len, buff, end );
end+=len;
return;
}
int sOff = off;
int sEnd = off + len;
while (sOff < sEnd) {
int d = min(limit - end, sEnd - sOff);
s.getChars( sOff, sOff+d, buff, end);
sOff += d;
end += d;
if (end >= limit) {
flushBuffer();
}
}
}
// in java/org/apache/tomcat/util/buf/CharChunk.java
public int substract()
throws IOException {
if ((end - start) == 0) {
if (in == null) {
return -1;
}
int n = in.realReadChars(buff, end, buff.length - end);
if (n < 0) {
return -1;
}
}
return (buff[start++]);
}
// in java/org/apache/tomcat/util/buf/CharChunk.java
public int substract( char src[], int off, int len )
throws IOException {
if ((end - start) == 0) {
if (in == null) {
return -1;
}
int n = in.realReadChars( buff, end, buff.length - end);
if (n < 0) {
return -1;
}
}
int n = len;
if (len > getLength()) {
n = getLength();
}
System.arraycopy(buff, start, src, off, n);
start += n;
return n;
}
// in java/org/apache/tomcat/util/buf/CharChunk.java
public void flushBuffer()
throws IOException
{
//assert out!=null
if( out==null ) {
throw new IOException( "Buffer overflow, no sink " + limit + " " +
buff.length );
}
out.realWriteChars( buff, start, end - start );
end=start;
}
// in java/org/apache/tomcat/util/buf/UDecoder.java
public void convert( ByteChunk mb, boolean query )
throws IOException
{
int start=mb.getOffset();
byte buff[]=mb.getBytes();
int end=mb.getEnd();
int idx= ByteChunk.findByte( buff, start, end, (byte) '%' );
int idx2=-1;
if( query ) {
idx2= ByteChunk.findByte( buff, start, (idx >= 0 ? idx : end), (byte) '+' );
}
if( idx<0 && idx2<0 ) {
return;
}
// idx will be the smallest positive index ( first % or + )
if( (idx2 >= 0 && idx2 < idx) || idx < 0 ) {
idx=idx2;
}
final boolean noSlash = !(ALLOW_ENCODED_SLASH || query);
for( int j=idx; j<end; j++, idx++ ) {
if( buff[ j ] == '+' && query) {
buff[idx]= (byte)' ' ;
} else if( buff[ j ] != '%' ) {
buff[idx]= buff[j];
} else {
// read next 2 digits
if( j+2 >= end ) {
throw EXCEPTION_EOF;
}
byte b1= buff[j+1];
byte b2=buff[j+2];
if( !isHexDigit( b1 ) || ! isHexDigit(b2 )) {
throw EXCEPTION_NOT_HEX_DIGIT;
}
j+=2;
int res=x2c( b1, b2 );
if (noSlash && (res == '/')) {
throw EXCEPTION_SLASH;
}
buff[idx]=(byte)res;
}
}
mb.setEnd( idx );
return;
}
// in java/org/apache/tomcat/util/buf/UDecoder.java
public void convert( CharChunk mb, boolean query )
throws IOException
{
// log( "Converting a char chunk ");
int start=mb.getOffset();
char buff[]=mb.getBuffer();
int cend=mb.getEnd();
int idx= CharChunk.indexOf( buff, start, cend, '%' );
int idx2=-1;
if( query ) {
idx2= CharChunk.indexOf( buff, start, (idx >= 0 ? idx : cend), '+' );
}
if( idx<0 && idx2<0 ) {
return;
}
// idx will be the smallest positive index ( first % or + )
if( (idx2 >= 0 && idx2 < idx) || idx < 0 ) {
idx=idx2;
}
final boolean noSlash = !(ALLOW_ENCODED_SLASH || query);
for( int j=idx; j<cend; j++, idx++ ) {
if( buff[ j ] == '+' && query ) {
buff[idx]=( ' ' );
} else if( buff[ j ] != '%' ) {
buff[idx]=buff[j];
} else {
// read next 2 digits
if( j+2 >= cend ) {
// invalid
throw EXCEPTION_EOF;
}
char b1= buff[j+1];
char b2=buff[j+2];
if( !isHexDigit( b1 ) || ! isHexDigit(b2 )) {
throw EXCEPTION_NOT_HEX_DIGIT;
}
j+=2;
int res=x2c( b1, b2 );
if (noSlash && (res == '/')) {
throw EXCEPTION_SLASH;
}
buff[idx]=(char)res;
}
}
mb.setEnd( idx );
}
// in java/org/apache/tomcat/util/buf/UDecoder.java
public void convert(MessageBytes mb, boolean query)
throws IOException
{
switch (mb.getType()) {
case MessageBytes.T_STR:
String strValue=mb.toString();
if( strValue==null ) {
return;
}
try {
mb.setString( convert( strValue, query ));
} catch (RuntimeException ex) {
throw new DecodeException(ex.getMessage());
}
break;
case MessageBytes.T_CHARS:
CharChunk charC=mb.getCharChunk();
convert( charC, query );
break;
case MessageBytes.T_BYTES:
ByteChunk bytesC=mb.getByteChunk();
convert( bytesC, query );
break;
}
}
// in java/org/apache/tomcat/util/buf/C2BConverter.java
private void init() throws IOException {
ios = new IntermediateOutputStream(bb);
conv = new WriteConvertor(ios, B2CConverter.getCharset(encoding));
writer = new BufferedWriter(conv);
}
// in java/org/apache/tomcat/util/buf/C2BConverter.java
public final void convert(char c[], int off, int len) throws IOException {
writer.write(c, off, len);
}
// in java/org/apache/tomcat/util/buf/C2BConverter.java
public final void convert(String s, int off, int len) throws IOException {
writer.write(s, off, len);
}
// in java/org/apache/tomcat/util/buf/C2BConverter.java
public final void convert(String s) throws IOException {
writer.write(s);
}
// in java/org/apache/tomcat/util/buf/C2BConverter.java
public final void convert(char c) throws IOException {
writer.write(c);
}
// in java/org/apache/tomcat/util/buf/C2BConverter.java
public final void flushBuffer() throws IOException {
writer.flush();
}
// in java/org/apache/tomcat/util/buf/C2BConverter.java
Override
public final void close() throws IOException {
// NOTHING
// Calling super.close() would reset out and cb.
}
// in java/org/apache/tomcat/util/buf/C2BConverter.java
Override
public final void flush() throws IOException {
// Will flushBuffer and out()
// flushBuffer put any remaining chars in the byte[]
super.flush();
}
// in java/org/apache/tomcat/util/buf/C2BConverter.java
Override
public final void write(char cbuf[], int off, int len) throws IOException {
// Will do the conversion and call write on the output stream
super.write( cbuf, off, len );
}
// in java/org/apache/tomcat/util/buf/C2BConverter.java
Override
public final void close() throws IOException {
// shouldn't be called - we filter it out in writer
throw new IOException("close() called - shouldn't happen ");
}
// in java/org/apache/tomcat/util/buf/C2BConverter.java
Override
public final void flush() throws IOException {
// nothing - write will go directly to the buffer,
// we don't keep any state
}
// in java/org/apache/tomcat/util/buf/C2BConverter.java
Override
public final void write(byte cbuf[], int off, int len) throws IOException {
// will do the conversion and call write on the output stream
if( enabled ) {
tbuff.append( cbuf, off, len );
}
}
// in java/org/apache/tomcat/util/buf/C2BConverter.java
Override
public final void write(int i) throws IOException {
throw new IOException("write( int ) called - shouldn't happen ");
}
// in java/org/apache/tomcat/util/buf/UEncoder.java
public void urlEncode( Writer buf, String s )
throws IOException {
if( c2b==null ) {
bb=new ByteChunk(16); // small enough.
c2b=new C2BConverter( bb, ENCODING );
}
for (int i = 0; i < s.length(); i++) {
int c = s.charAt(i);
if( safeChars.get( c ) ) {
if(log.isDebugEnabled()) {
log.debug("Encoder: Safe: " + (char)c);
}
buf.write((char)c);
} else {
if(log.isDebugEnabled()) {
log.debug("Encoder: Unsafe: " + (char)c);
}
c2b.convert( (char)c );
// "surrogate" - UTF is _not_ 16 bit, but 21 !!!!
// ( while UCS is 31 ). Amazing...
if (c >= 0xD800 && c <= 0xDBFF) {
if ( (i+1) < s.length()) {
int d = s.charAt(i+1);
if (d >= 0xDC00 && d <= 0xDFFF) {
if(log.isDebugEnabled()) {
log.debug("Encoder: Unsafe: " + c);
}
c2b.convert( (char)d);
i++;
}
}
}
c2b.flushBuffer();
urlEncode( buf, bb.getBuffer(), bb.getOffset(),
bb.getLength() );
bb.recycle();
}
}
}
// in java/org/apache/tomcat/util/buf/UEncoder.java
public void urlEncode( Writer buf, byte bytes[], int off, int len)
throws IOException {
for( int j=off; j< len; j++ ) {
buf.write( '%' );
char ch = Character.forDigit((bytes[j] >> 4) & 0xF, 16);
if(log.isDebugEnabled()) {
log.debug("Encoder: Encode: " + ch);
}
buf.write(ch);
ch = Character.forDigit(bytes[j] & 0xF, 16);
if(log.isDebugEnabled()) {
log.debug("Encoder: Encode: " + ch);
}
buf.write(ch);
}
}
// in java/org/apache/tomcat/util/buf/ByteChunk.java
public void append( byte b )
throws IOException
{
makeSpace( 1 );
// couldn't make space
if( limit >0 && end >= limit ) {
flushBuffer();
}
buff[end++]=b;
}
// in java/org/apache/tomcat/util/buf/ByteChunk.java
public void append( ByteChunk src )
throws IOException
{
append( src.getBytes(), src.getStart(), src.getLength());
}
// in java/org/apache/tomcat/util/buf/ByteChunk.java
public void append( byte src[], int off, int len )
throws IOException
{
// will grow, up to limit
makeSpace( len );
// if we don't have limit: makeSpace can grow as it wants
if( limit < 0 ) {
// assert: makeSpace made enough space
System.arraycopy( src, off, buff, end, len );
end+=len;
return;
}
// Optimize on a common case.
// If the buffer is empty and the source is going to fill up all the
// space in buffer, may as well write it directly to the output,
// and avoid an extra copy
if ( len == limit && end == start && out != null ) {
out.realWriteBytes( src, off, len );
return;
}
// if we have limit and we're below
if( len <= limit - end ) {
// makeSpace will grow the buffer to the limit,
// so we have space
System.arraycopy( src, off, buff, end, len );
end+=len;
return;
}
// need more space than we can afford, need to flush
// buffer
// the buffer is already at ( or bigger than ) limit
// We chunk the data into slices fitting in the buffer limit, although
// if the data is written directly if it doesn't fit
int avail=limit-end;
System.arraycopy(src, off, buff, end, avail);
end += avail;
flushBuffer();
int remain = len - avail;
while (remain > (limit - end)) {
out.realWriteBytes( src, (off + len) - remain, limit - end );
remain = remain - (limit - end);
}
System.arraycopy(src, (off + len) - remain, buff, end, remain);
end += remain;
}
// in java/org/apache/tomcat/util/buf/ByteChunk.java
public int substract()
throws IOException {
if ((end - start) == 0) {
if (in == null) {
return -1;
}
int n = in.realReadBytes( buff, 0, buff.length );
if (n < 0) {
return -1;
}
}
return (buff[start++] & 0xFF);
}
// in java/org/apache/tomcat/util/buf/ByteChunk.java
public int substract( byte src[], int off, int len )
throws IOException {
if ((end - start) == 0) {
if (in == null) {
return -1;
}
int n = in.realReadBytes( buff, 0, buff.length );
if (n < 0) {
return -1;
}
}
int n = len;
if (len > getLength()) {
n = getLength();
}
System.arraycopy(buff, start, src, off, n);
start += n;
return n;
}
// in java/org/apache/tomcat/util/buf/ByteChunk.java
public void flushBuffer()
throws IOException
{
//assert out!=null
if( out==null ) {
throw new IOException( "Buffer overflow, no sink " + limit + " " +
buff.length );
}
out.realWriteBytes( buff, start, end-start );
end=start;
}
// in java/org/apache/tomcat/util/scan/NonClosingJarInputStream.java
Override
public void close() throws IOException {
// Make this a NO-OP so that further entries can be read from the stream
}
// in java/org/apache/tomcat/util/scan/NonClosingJarInputStream.java
public void reallyClose() throws IOException {
super.close();
}
// in java/org/apache/tomcat/util/scan/JarFactory.java
public static Jar newInstance(URL url) throws IOException {
String jarUrl = url.toString();
if (jarUrl.startsWith("jar:file:")) {
return new FileUrlJar(url);
} else {
return new UrlJar(url);
}
}
// in java/org/apache/tomcat/util/scan/StandardJarScanner.java
private void process(JarScannerCallback callback, URL url)
throws IOException {
if (log.isTraceEnabled()) {
log.trace(sm.getString("jarScan.jarUrlStart", url));
}
URLConnection conn = url.openConnection();
if (conn instanceof JarURLConnection) {
callback.scan((JarURLConnection) conn);
} else {
String urlStr = url.toString();
if (urlStr.startsWith("file:") || urlStr.startsWith("jndi:")) {
if (urlStr.endsWith(Constants.JAR_EXT)) {
URL jarURL = new URL("jar:" + urlStr + "!/");
callback.scan((JarURLConnection) jarURL.openConnection());
} else {
File f;
try {
f = new File(url.toURI());
if (f.isFile() && scanAllFiles) {
// Treat this file as a JAR
URL jarURL = new URL("jar:" + urlStr + "!/");
callback.scan((JarURLConnection) jarURL.openConnection());
} else if (f.isDirectory() && scanAllDirectories) {
File metainf = new File(f.getAbsoluteFile() +
File.separator + "META-INF");
if (metainf.isDirectory()) {
callback.scan(f);
}
}
} catch (URISyntaxException e) {
// Wrap the exception and re-throw
IOException ioe = new IOException();
ioe.initCause(e);
throw ioe;
}
}
}
}
}
// in java/org/apache/tomcat/util/scan/UrlJar.java
Override
public boolean entryExists(String name) throws IOException {
JarEntry entry = jarInputStream.getNextJarEntry();
while (entry != null) {
if (name.equals(entry.getName())) {
break;
}
entry = jarInputStream.getNextJarEntry();
}
return entry != null;
}
// in java/org/apache/tomcat/util/scan/UrlJar.java
Override
public InputStream getInputStream(String name) throws IOException {
JarEntry entry = jarInputStream.getNextJarEntry();
while (entry != null) {
if (name.equals(entry.getName())) {
break;
}
entry = jarInputStream.getNextJarEntry();
}
if (entry == null) {
return null;
} else {
return jarInputStream;
}
}
// in java/org/apache/tomcat/util/scan/UrlJar.java
private NonClosingJarInputStream createJarInputStream() throws IOException {
JarURLConnection jarConn = (JarURLConnection) url.openConnection();
URL resourceURL = jarConn.getJarFileURL();
URLConnection resourceConn = resourceURL.openConnection();
resourceConn.setUseCaches(false);
return new NonClosingJarInputStream(resourceConn.getInputStream());
}
// in java/org/apache/tomcat/util/scan/UrlJar.java
Override
public InputStream getEntryInputStream() throws IOException {
return jarInputStream;
}
// in java/org/apache/tomcat/util/scan/UrlJar.java
Override
public void reset() throws IOException {
close();
jarInputStream = createJarInputStream();
}
// in java/org/apache/tomcat/util/scan/FileUrlJar.java
Override
public InputStream getInputStream(String name) throws IOException {
ZipEntry entry = jarFile.getEntry(name);
if (entry == null) {
return null;
} else {
return jarFile.getInputStream(entry);
}
}
// in java/org/apache/tomcat/util/scan/FileUrlJar.java
Override
public InputStream getEntryInputStream() throws IOException {
if (entry == null) {
return null;
} else {
return jarFile.getInputStream(entry);
}
}
// in java/org/apache/tomcat/util/scan/FileUrlJar.java
Override
public void reset() throws IOException {
entries = null;
entry = null;
}
// in java/org/apache/tomcat/util/digester/Digester.java
public Object parse(File file) throws IOException, SAXException {
configure();
InputSource input = new InputSource(new FileInputStream(file));
input.setSystemId("file://" + file.getAbsolutePath());
getXMLReader().parse(input);
return (root);
}
// in java/org/apache/tomcat/util/digester/Digester.java
public Object parse(InputSource input) throws IOException, SAXException {
configure();
getXMLReader().parse(input);
return (root);
}
// in java/org/apache/tomcat/util/digester/Digester.java
public Object parse(InputStream input) throws IOException, SAXException {
configure();
InputSource is = new InputSource(input);
getXMLReader().parse(is);
return (root);
}
// in java/org/apache/tomcat/util/digester/Digester.java
public Object parse(Reader reader) throws IOException, SAXException {
configure();
InputSource is = new InputSource(reader);
getXMLReader().parse(is);
return (root);
}
// in java/org/apache/tomcat/util/digester/Digester.java
public Object parse(String uri) throws IOException, SAXException {
configure();
InputSource is = new InputSource(uri);
getXMLReader().parse(is);
return (root);
}
// in java/org/apache/tomcat/util/log/SystemLogHandler.java
Override
public void write(byte[] b)
throws IOException {
findStream().write(b);
}
// in java/org/apache/tomcat/util/bcel/classfile/ClassElementValue.java
Override
public void dump(DataOutputStream dos) throws IOException
{
dos.writeByte(type); // u1 kind of value
dos.writeShort(idx);
}
// in java/org/apache/tomcat/util/bcel/classfile/ConstantFloat.java
Override
public final void dump( DataOutputStream file ) throws IOException {
file.writeByte(tag);
file.writeFloat(bytes);
}
// in java/org/apache/tomcat/util/bcel/classfile/RuntimeInvisibleAnnotations.java
Override
public final void dump(DataOutputStream dos) throws IOException
{
super.dump(dos);
writeAnnotations(dos);
}
// in java/org/apache/tomcat/util/bcel/classfile/ConstantNameAndType.java
Override
public final void dump( DataOutputStream file ) throws IOException {
file.writeByte(tag);
file.writeShort(name_index);
file.writeShort(signature_index);
}
// in java/org/apache/tomcat/util/bcel/classfile/Synthetic.java
Override
public final void dump( DataOutputStream file ) throws IOException {
super.dump(file);
if (length > 0) {
file.write(bytes, 0, length);
}
}
// in java/org/apache/tomcat/util/bcel/classfile/ExceptionTable.java
Override
public final void dump( DataOutputStream file ) throws IOException {
super.dump(file);
file.writeShort(number_of_exceptions);
for (int i = 0; i < number_of_exceptions; i++) {
file.writeShort(exception_index_table[i]);
}
}
// in java/org/apache/tomcat/util/bcel/classfile/Utility.java
public static final String codeToString( ByteSequence bytes, ConstantPool constant_pool,
boolean verbose ) throws IOException {
short opcode = (short) bytes.readUnsignedByte();
int default_offset = 0, low, high, npairs;
int index, vindex, constant;
int[] match, jump_table;
int no_pad_bytes = 0, offset;
StringBuilder buf = new StringBuilder(Constants.OPCODE_NAMES[opcode]);
/* Special case: Skip (0-3) padding bytes, i.e., the
* following bytes are 4-byte-aligned
*/
if ((opcode == Constants.TABLESWITCH) || (opcode == Constants.LOOKUPSWITCH)) {
int remainder = bytes.getIndex() % 4;
no_pad_bytes = (remainder == 0) ? 0 : 4 - remainder;
for (int i = 0; i < no_pad_bytes; i++) {
byte b;
if ((b = bytes.readByte()) != 0) {
System.err.println("Warning: Padding byte != 0 in "
+ Constants.OPCODE_NAMES[opcode] + ":" + b);
}
}
// Both cases have a field default_offset in common
default_offset = bytes.readInt();
}
switch (opcode) {
/* Table switch has variable length arguments.
*/
case Constants.TABLESWITCH:
low = bytes.readInt();
high = bytes.readInt();
offset = bytes.getIndex() - 12 - no_pad_bytes - 1;
default_offset += offset;
buf.append("\tdefault = ").append(default_offset).append(", low = ").append(low)
.append(", high = ").append(high).append("(");
jump_table = new int[high - low + 1];
for (int i = 0; i < jump_table.length; i++) {
jump_table[i] = offset + bytes.readInt();
buf.append(jump_table[i]);
if (i < jump_table.length - 1) {
buf.append(", ");
}
}
buf.append(")");
break;
/* Lookup switch has variable length arguments.
*/
case Constants.LOOKUPSWITCH: {
npairs = bytes.readInt();
offset = bytes.getIndex() - 8 - no_pad_bytes - 1;
match = new int[npairs];
jump_table = new int[npairs];
default_offset += offset;
buf.append("\tdefault = ").append(default_offset).append(", npairs = ").append(
npairs).append(" (");
for (int i = 0; i < npairs; i++) {
match[i] = bytes.readInt();
jump_table[i] = offset + bytes.readInt();
buf.append("(").append(match[i]).append(", ").append(jump_table[i]).append(")");
if (i < npairs - 1) {
buf.append(", ");
}
}
buf.append(")");
}
break;
/* Two address bytes + offset from start of byte stream form the
* jump target
*/
case Constants.GOTO:
case Constants.IFEQ:
case Constants.IFGE:
case Constants.IFGT:
case Constants.IFLE:
case Constants.IFLT:
case Constants.JSR:
case Constants.IFNE:
case Constants.IFNONNULL:
case Constants.IFNULL:
case Constants.IF_ACMPEQ:
case Constants.IF_ACMPNE:
case Constants.IF_ICMPEQ:
case Constants.IF_ICMPGE:
case Constants.IF_ICMPGT:
case Constants.IF_ICMPLE:
case Constants.IF_ICMPLT:
case Constants.IF_ICMPNE:
buf.append("\t\t#").append((bytes.getIndex() - 1) + bytes.readShort());
break;
/* 32-bit wide jumps
*/
case Constants.GOTO_W:
case Constants.JSR_W:
buf.append("\t\t#").append(((bytes.getIndex() - 1) + bytes.readInt()));
break;
/* Index byte references local variable (register)
*/
case Constants.ALOAD:
case Constants.ASTORE:
case Constants.DLOAD:
case Constants.DSTORE:
case Constants.FLOAD:
case Constants.FSTORE:
case Constants.ILOAD:
case Constants.ISTORE:
case Constants.LLOAD:
case Constants.LSTORE:
case Constants.RET:
if (wide) {
vindex = bytes.readUnsignedShort();
wide = false; // Clear flag
} else {
vindex = bytes.readUnsignedByte();
}
buf.append("\t\t%").append(vindex);
break;
/*
* Remember wide byte which is used to form a 16-bit address in the
* following instruction. Relies on that the method is called again with
* the following opcode.
*/
case Constants.WIDE:
wide = true;
buf.append("\t(wide)");
break;
/* Array of basic type.
*/
case Constants.NEWARRAY:
buf.append("\t\t<").append(Constants.TYPE_NAMES[bytes.readByte()]).append(">");
break;
/* Access object/class fields.
*/
case Constants.GETFIELD:
case Constants.GETSTATIC:
case Constants.PUTFIELD:
case Constants.PUTSTATIC:
index = bytes.readUnsignedShort();
buf.append("\t\t").append(
constant_pool.constantToString(index, Constants.CONSTANT_Fieldref)).append(
(verbose ? " (" + index + ")" : ""));
break;
/* Operands are references to classes in constant pool
*/
case Constants.NEW:
case Constants.CHECKCAST:
buf.append("\t");
//$FALL-THROUGH$
case Constants.INSTANCEOF:
index = bytes.readUnsignedShort();
buf.append("\t<").append(
constant_pool.constantToString(index, Constants.CONSTANT_Class))
.append(">").append((verbose ? " (" + index + ")" : ""));
break;
/* Operands are references to methods in constant pool
*/
case Constants.INVOKESPECIAL:
case Constants.INVOKESTATIC:
case Constants.INVOKEVIRTUAL:
index = bytes.readUnsignedShort();
buf.append("\t").append(
constant_pool.constantToString(index, Constants.CONSTANT_Methodref))
.append((verbose ? " (" + index + ")" : ""));
break;
case Constants.INVOKEINTERFACE:
index = bytes.readUnsignedShort();
int nargs = bytes.readUnsignedByte(); // historical, redundant
buf.append("\t").append(
constant_pool
.constantToString(index, Constants.CONSTANT_InterfaceMethodref))
.append(verbose ? " (" + index + ")\t" : "").append(nargs).append("\t")
.append(bytes.readUnsignedByte()); // Last byte is a reserved space
break;
/* Operands are references to items in constant pool
*/
case Constants.LDC_W:
case Constants.LDC2_W:
index = bytes.readUnsignedShort();
buf.append("\t\t").append(
constant_pool.constantToString(index, constant_pool.getConstant(index)
.getTag())).append((verbose ? " (" + index + ")" : ""));
break;
case Constants.LDC:
index = bytes.readUnsignedByte();
buf.append("\t\t").append(
constant_pool.constantToString(index, constant_pool.getConstant(index)
.getTag())).append((verbose ? " (" + index + ")" : ""));
break;
/* Array of references.
*/
case Constants.ANEWARRAY:
index = bytes.readUnsignedShort();
buf.append("\t\t<").append(
compactClassName(constant_pool.getConstantString(index,
Constants.CONSTANT_Class), false)).append(">").append(
(verbose ? " (" + index + ")" : ""));
break;
/* Multidimensional array of references.
*/
case Constants.MULTIANEWARRAY: {
index = bytes.readUnsignedShort();
int dimensions = bytes.readUnsignedByte();
buf.append("\t<").append(
compactClassName(constant_pool.getConstantString(index,
Constants.CONSTANT_Class), false)).append(">\t").append(dimensions)
.append((verbose ? " (" + index + ")" : ""));
}
break;
/* Increment local variable.
*/
case Constants.IINC:
if (wide) {
vindex = bytes.readUnsignedShort();
constant = bytes.readShort();
wide = false;
} else {
vindex = bytes.readUnsignedByte();
constant = bytes.readByte();
}
buf.append("\t\t%").append(vindex).append("\t").append(constant);
break;
default:
if (Constants.NO_OF_OPERANDS[opcode] > 0) {
for (int i = 0; i < Constants.TYPE_OF_OPERANDS[opcode].length; i++) {
buf.append("\t\t");
switch (Constants.TYPE_OF_OPERANDS[opcode][i]) {
case Constants.T_BYTE:
buf.append(bytes.readByte());
break;
case Constants.T_SHORT:
buf.append(bytes.readShort());
break;
case Constants.T_INT:
buf.append(bytes.readInt());
break;
default: // Never reached
System.err.println("Unreachable default case reached!");
System.exit(-1);
}
}
}
}
return buf.toString();
}
// in java/org/apache/tomcat/util/bcel/classfile/ConstantInteger.java
Override
public final void dump( DataOutputStream file ) throws IOException {
file.writeByte(tag);
file.writeInt(bytes);
}
// in java/org/apache/tomcat/util/bcel/classfile/Deprecated.java
Override
public final void dump( DataOutputStream file ) throws IOException {
super.dump(file);
if (length > 0) {
file.write(bytes, 0, length);
}
}
// in java/org/apache/tomcat/util/bcel/classfile/ConstantValue.java
Override
public final void dump( DataOutputStream file ) throws IOException {
super.dump(file);
file.writeShort(constantvalue_index);
}
// in java/org/apache/tomcat/util/bcel/classfile/InnerClasses.java
Override
public final void dump( DataOutputStream file ) throws IOException {
super.dump(file);
file.writeShort(number_of_classes);
for (int i = 0; i < number_of_classes; i++) {
inner_classes[i].dump(file);
}
}
// in java/org/apache/tomcat/util/bcel/classfile/ElementValue.java
public static ElementValue readElementValue(DataInputStream dis,
ConstantPool cpool) throws IOException
{
byte type = dis.readByte();
switch (type)
{
case 'B': // byte
return new SimpleElementValue(PRIMITIVE_BYTE, dis
.readUnsignedShort(), cpool);
case 'C': // char
return new SimpleElementValue(PRIMITIVE_CHAR, dis
.readUnsignedShort(), cpool);
case 'D': // double
return new SimpleElementValue(PRIMITIVE_DOUBLE, dis
.readUnsignedShort(), cpool);
case 'F': // float
return new SimpleElementValue(PRIMITIVE_FLOAT, dis
.readUnsignedShort(), cpool);
case 'I': // int
return new SimpleElementValue(PRIMITIVE_INT, dis
.readUnsignedShort(), cpool);
case 'J': // long
return new SimpleElementValue(PRIMITIVE_LONG, dis
.readUnsignedShort(), cpool);
case 'S': // short
return new SimpleElementValue(PRIMITIVE_SHORT, dis
.readUnsignedShort(), cpool);
case 'Z': // boolean
return new SimpleElementValue(PRIMITIVE_BOOLEAN, dis
.readUnsignedShort(), cpool);
case 's': // String
return new SimpleElementValue(STRING, dis.readUnsignedShort(),
cpool);
case 'e': // Enum constant
return new EnumElementValue(ENUM_CONSTANT, dis.readUnsignedShort(),
dis.readUnsignedShort(), cpool);
case 'c': // Class
return new ClassElementValue(CLASS, dis.readUnsignedShort(), cpool);
case '@': // Annotation
// TODO isRuntimeVisible
return new AnnotationElementValue(ANNOTATION, AnnotationEntry.read(
dis, cpool), cpool);
case '[': // Array
int numArrayVals = dis.readUnsignedShort();
ElementValue[] evalues = new ElementValue[numArrayVals];
for (int j = 0; j < numArrayVals; j++)
{
evalues[j] = ElementValue.readElementValue(dis, cpool);
}
return new ArrayElementValue(ARRAY, evalues, cpool);
default:
throw new RuntimeException(
"Unexpected element value kind in annotation: " + type);
}
}
// in java/org/apache/tomcat/util/bcel/classfile/StackMap.java
Override
public final void dump( DataOutputStream file ) throws IOException {
super.dump(file);
file.writeShort(map_length);
for (int i = 0; i < map_length; i++) {
map[i].dump(file);
}
}
// in java/org/apache/tomcat/util/bcel/classfile/ConstantString.java
Override
public final void dump( DataOutputStream file ) throws IOException {
file.writeByte(tag);
file.writeShort(string_index);
}
// in java/org/apache/tomcat/util/bcel/classfile/SourceFile.java
Override
public final void dump( DataOutputStream file ) throws IOException {
super.dump(file);
file.writeShort(sourcefile_index);
}
// in java/org/apache/tomcat/util/bcel/classfile/Constant.java
static final Constant readConstant( DataInputStream file ) throws IOException,
ClassFormatException {
byte b = file.readByte(); // Read tag byte
switch (b) {
case Constants.CONSTANT_Class:
return new ConstantClass(file);
case Constants.CONSTANT_Fieldref:
return new ConstantFieldref(file);
case Constants.CONSTANT_Methodref:
return new ConstantMethodref(file);
case Constants.CONSTANT_InterfaceMethodref:
return new ConstantInterfaceMethodref(file);
case Constants.CONSTANT_String:
return new ConstantString(file);
case Constants.CONSTANT_Integer:
return new ConstantInteger(file);
case Constants.CONSTANT_Float:
return new ConstantFloat(file);
case Constants.CONSTANT_Long:
return new ConstantLong(file);
case Constants.CONSTANT_Double:
return new ConstantDouble(file);
case Constants.CONSTANT_NameAndType:
return new ConstantNameAndType(file);
case Constants.CONSTANT_Utf8:
return new ConstantUtf8(file);
default:
throw new ClassFormatException("Invalid byte tag in constant pool: " + b);
}
}
// in java/org/apache/tomcat/util/bcel/classfile/ConstantLong.java
Override
public final void dump( DataOutputStream file ) throws IOException {
file.writeByte(tag);
file.writeLong(bytes);
}
// in java/org/apache/tomcat/util/bcel/classfile/ConstantDouble.java
Override
public final void dump( DataOutputStream file ) throws IOException {
file.writeByte(tag);
file.writeDouble(bytes);
}
// in java/org/apache/tomcat/util/bcel/classfile/StackMapEntry.java
public final void dump( DataOutputStream file ) throws IOException {
file.writeShort(byte_code_offset);
file.writeShort(number_of_locals);
for (int i = 0; i < number_of_locals; i++) {
types_of_locals[i].dump(file);
}
file.writeShort(number_of_stack_items);
for (int i = 0; i < number_of_stack_items; i++) {
types_of_stack_items[i].dump(file);
}
}
// in java/org/apache/tomcat/util/bcel/classfile/Annotations.java
protected void writeAnnotations(DataOutputStream dos) throws IOException {
if (annotation_table == null) {
return;
}
dos.writeShort(annotation_table.length);
for (int i = 0; i < annotation_table.length; i++) {
annotation_table[i].dump(dos);
}
}
// in java/org/apache/tomcat/util/bcel/classfile/LocalVariableTable.java
Override
public final void dump( DataOutputStream file ) throws IOException {
super.dump(file);
file.writeShort(local_variable_table_length);
for (int i = 0; i < local_variable_table_length; i++) {
local_variable_table[i].dump(file);
}
}
// in java/org/apache/tomcat/util/bcel/classfile/EnumElementValue.java
Override
public void dump(DataOutputStream dos) throws IOException
{
dos.writeByte(type); // u1 type of value (ENUM_CONSTANT == 'e')
dos.writeShort(typeIdx); // u2
dos.writeShort(valueIdx); // u2
}
// in java/org/apache/tomcat/util/bcel/classfile/Unknown.java
Override
public final void dump( DataOutputStream file ) throws IOException {
super.dump(file);
if (length > 0) {
file.write(bytes, 0, length);
}
}
// in java/org/apache/tomcat/util/bcel/classfile/Attribute.java
public void dump(DataOutputStream file) throws IOException
{
file.writeShort(name_index);
file.writeInt(length);
}
// in java/org/apache/tomcat/util/bcel/classfile/Attribute.java
public static final Attribute readAttribute(DataInputStream file,
ConstantPool constant_pool) throws IOException,
ClassFormatException
{
ConstantUtf8 c;
String name;
int name_index;
int length;
byte tag = Constants.ATTR_UNKNOWN; // Unknown attribute
// Get class name from constant pool via `name_index' indirection
name_index = file.readUnsignedShort();
c = (ConstantUtf8) constant_pool.getConstant(name_index,
Constants.CONSTANT_Utf8);
name = c.getBytes();
// Length of data in bytes
length = file.readInt();
// Compare strings to find known attribute
// System.out.println(name);
for (byte i = 0; i < Constants.KNOWN_ATTRIBUTES; i++)
{
if (name.equals(Constants.ATTRIBUTE_NAMES[i]))
{
tag = i; // found!
break;
}
}
// Call proper constructor, depending on `tag'
switch (tag)
{
case Constants.ATTR_UNKNOWN:
AttributeReader r = readers.get(name);
if (r != null)
{
return r.createAttribute(name_index, length, file,
constant_pool);
}
return new Unknown(name_index, length, file, constant_pool);
case Constants.ATTR_CONSTANT_VALUE:
return new ConstantValue(name_index, length, file, constant_pool);
case Constants.ATTR_SOURCE_FILE:
return new SourceFile(name_index, length, file, constant_pool);
case Constants.ATTR_CODE:
return new Code(name_index, length, file, constant_pool);
case Constants.ATTR_EXCEPTIONS:
return new ExceptionTable(name_index, length, file, constant_pool);
case Constants.ATTR_LINE_NUMBER_TABLE:
return new LineNumberTable(name_index, length, file, constant_pool);
case Constants.ATTR_LOCAL_VARIABLE_TABLE:
return new LocalVariableTable(name_index, length, file,
constant_pool);
case Constants.ATTR_INNER_CLASSES:
return new InnerClasses(name_index, length, file, constant_pool);
case Constants.ATTR_SYNTHETIC:
return new Synthetic(name_index, length, file, constant_pool);
case Constants.ATTR_DEPRECATED:
return new Deprecated(name_index, length, file, constant_pool);
case Constants.ATTR_PMG:
return new PMGClass(name_index, length, file, constant_pool);
case Constants.ATTR_SIGNATURE:
return new Signature(name_index, length, file, constant_pool);
case Constants.ATTR_STACK_MAP:
return new StackMap(name_index, length, file, constant_pool);
case Constants.ATTR_RUNTIME_VISIBLE_ANNOTATIONS:
return new RuntimeVisibleAnnotations(name_index, length, file,
constant_pool);
case Constants.ATTR_RUNTIMEIN_VISIBLE_ANNOTATIONS:
return new RuntimeInvisibleAnnotations(name_index, length, file,
constant_pool);
case Constants.ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS:
return new RuntimeVisibleParameterAnnotations(name_index, length,
file, constant_pool);
case Constants.ATTR_RUNTIMEIN_VISIBLE_PARAMETER_ANNOTATIONS:
return new RuntimeInvisibleParameterAnnotations(name_index, length,
file, constant_pool);
case Constants.ATTR_ANNOTATION_DEFAULT:
return new AnnotationDefault(name_index, length, file,
constant_pool);
case Constants.ATTR_LOCAL_VARIABLE_TYPE_TABLE:
return new LocalVariableTypeTable(name_index, length, file,
constant_pool);
case Constants.ATTR_ENCLOSING_METHOD:
return new EnclosingMethod(name_index, length, file, constant_pool);
case Constants.ATTR_STACK_MAP_TABLE:
return new StackMapTable(name_index, length, file, constant_pool);
default: // Never reached
throw new IllegalStateException("Unrecognized attribute type tag parsed: " + tag);
}
}
// in java/org/apache/tomcat/util/bcel/classfile/ConstantUtf8.java
Override
public final void dump( DataOutputStream file ) throws IOException {
file.writeByte(tag);
file.writeUTF(bytes);
}
// in java/org/apache/tomcat/util/bcel/classfile/LocalVariable.java
public final void dump( DataOutputStream file ) throws IOException {
file.writeShort(start_pc);
file.writeShort(length);
file.writeShort(name_index);
file.writeShort(signature_index);
file.writeShort(index);
}
// in java/org/apache/tomcat/util/bcel/classfile/AnnotationDefault.java
Override
public final void dump(DataOutputStream dos) throws IOException
{
super.dump(dos);
default_value.dump(dos);
}
// in java/org/apache/tomcat/util/bcel/classfile/StackMapTable.java
Override
public final void dump( DataOutputStream file ) throws IOException {
super.dump(file);
file.writeShort(map_length);
for (int i = 0; i < map_length; i++) {
map[i].dump(file);
}
}
// in java/org/apache/tomcat/util/bcel/classfile/AnnotationElementValue.java
Override
public void dump(DataOutputStream dos) throws IOException
{
dos.writeByte(type); // u1 type of value (ANNOTATION == '@')
annotationEntry.dump(dos);
}
// in java/org/apache/tomcat/util/bcel/classfile/Signature.java
Override
public final void dump( DataOutputStream file ) throws IOException {
super.dump(file);
file.writeShort(signature_index);
}
// in java/org/apache/tomcat/util/bcel/classfile/EnclosingMethod.java
Override
public final void dump(DataOutputStream file) throws IOException {
super.dump(file);
file.writeShort(classIndex);
file.writeShort(methodIndex);
}
// in java/org/apache/tomcat/util/bcel/classfile/InnerClass.java
public final void dump( DataOutputStream file ) throws IOException {
file.writeShort(inner_class_index);
file.writeShort(outer_class_index);
file.writeShort(inner_name_index);
file.writeShort(inner_access_flags);
}
// in java/org/apache/tomcat/util/bcel/classfile/ArrayElementValue.java
Override
public void dump(DataOutputStream dos) throws IOException
{
dos.writeByte(type); // u1 type of value (ARRAY == '[')
dos.writeShort(evalues.length);
for (int i = 0; i < evalues.length; i++)
{
evalues[i].dump(dos);
}
}
// in java/org/apache/tomcat/util/bcel/classfile/PMGClass.java
Override
public final void dump( DataOutputStream file ) throws IOException {
super.dump(file);
file.writeShort(pmg_index);
file.writeShort(pmg_class_index);
}
// in java/org/apache/tomcat/util/bcel/classfile/AnnotationEntry.java
public static AnnotationEntry read(DataInputStream file, ConstantPool constant_pool) throws IOException {
final AnnotationEntry annotationEntry = new AnnotationEntry(file.readUnsignedShort(), constant_pool);
final int num_element_value_pairs = (file.readUnsignedShort());
annotationEntry.element_value_pairs = new ArrayList<ElementValuePair>();
for (int i = 0; i < num_element_value_pairs; i++) {
annotationEntry.element_value_pairs.add(new ElementValuePair(file.readUnsignedShort(), ElementValue.readElementValue(file, constant_pool),
constant_pool));
}
return annotationEntry;
}
// in java/org/apache/tomcat/util/bcel/classfile/AnnotationEntry.java
public void dump(DataOutputStream dos) throws IOException {
dos.writeShort(type_index); // u2 index of type name in cpool
dos.writeShort(element_value_pairs.size()); // u2 element_value pair
// count
for (int i = 0; i < element_value_pairs.size(); i++) {
final ElementValuePair envp = element_value_pairs.get(i);
envp.dump(dos);
}
}
// in java/org/apache/tomcat/util/bcel/classfile/StackMapTableEntry.java
public final void dump( DataOutputStream file ) throws IOException {
file.write(frame_type);
if (frame_type >= Constants.SAME_FRAME && frame_type <= Constants.SAME_FRAME_MAX) {
// nothing to be done
} else if (frame_type >= Constants.SAME_LOCALS_1_STACK_ITEM_FRAME && frame_type <= Constants.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) {
types_of_stack_items[0].dump(file);
} else if (frame_type == Constants.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {
file.writeShort(byte_code_offset_delta);
types_of_stack_items[0].dump(file);
} else if (frame_type >= Constants.CHOP_FRAME && frame_type <= Constants.CHOP_FRAME_MAX) {
file.writeShort(byte_code_offset_delta);
} else if (frame_type == Constants.SAME_FRAME_EXTENDED) {
file.writeShort(byte_code_offset_delta);
} else if (frame_type >= Constants.APPEND_FRAME && frame_type <= Constants.APPEND_FRAME_MAX) {
file.writeShort(byte_code_offset_delta);
for (int i = 0; i < number_of_locals; i++) {
types_of_locals[i].dump(file);
}
} else if (frame_type == Constants.FULL_FRAME) {
file.writeShort(byte_code_offset_delta);
file.writeShort(number_of_locals);
for (int i = 0; i < number_of_locals; i++) {
types_of_locals[i].dump(file);
}
file.writeShort(number_of_stack_items);
for (int i = 0; i < number_of_stack_items; i++) {
types_of_stack_items[i].dump(file);
}
} else {
/* Can't happen */
throw new ClassFormatException ("Invalid Stack map table tag: " + frame_type);
}
}
// in java/org/apache/tomcat/util/bcel/classfile/LineNumberTable.java
Override
public final void dump( DataOutputStream file ) throws IOException {
super.dump(file);
file.writeShort(line_number_table_length);
for (int i = 0; i < line_number_table_length; i++) {
line_number_table[i].dump(file);
}
}
// in java/org/apache/tomcat/util/bcel/classfile/StackMapType.java
public final void dump( DataOutputStream file ) throws IOException {
file.writeByte(type);
if (hasIndex()) {
file.writeShort(getIndex());
}
}
// in java/org/apache/tomcat/util/bcel/classfile/ClassParser.java
public JavaClass parse() throws IOException, ClassFormatException {
/****************** Read headers ********************************/
// Check magic tag of class file
readID();
// Get compiler version
readVersion();
/****************** Read constant pool and related **************/
// Read constant pool entries
readConstantPool();
// Get class information
readClassInfo();
// Get interface information, i.e., implemented interfaces
readInterfaces();
/****************** Read class fields and methods ***************/
// Read class fields, i.e., the variables of the class
readFields();
// Read class methods, i.e., the functions in the class
readMethods();
// Read class attributes
readAttributes();
// Check for unknown variables
//Unknown[] u = Unknown.getUnknownAttributes();
//for(int i=0; i < u.length; i++)
// System.err.println("WARNING: " + u[i]);
// Everything should have been read now
// if(file.available() > 0) {
// int bytes = file.available();
// byte[] buf = new byte[bytes];
// file.read(buf);
// if(!(is_zip && (buf.length == 1))) {
// System.err.println("WARNING: Trailing garbage at end of " + file_name);
// System.err.println(bytes + " extra bytes: " + Utility.toHexString(buf));
// }
// }
// Return the information we have gathered in a new object
return new JavaClass(class_name_index, superclass_name_index, file_name, major, minor,
access_flags, constant_pool, interfaces, fields, methods, attributes);
}
// in java/org/apache/tomcat/util/bcel/classfile/ClassParser.java
private final void readAttributes() throws IOException, ClassFormatException {
int attributes_count;
attributes_count = file.readUnsignedShort();
attributes = new Attribute[attributes_count];
for (int i = 0; i < attributes_count; i++) {
attributes[i] = Attribute.readAttribute(file, constant_pool);
}
}
// in java/org/apache/tomcat/util/bcel/classfile/ClassParser.java
private final void readClassInfo() throws IOException, ClassFormatException {
access_flags = file.readUnsignedShort();
/* Interfaces are implicitely abstract, the flag should be set
* according to the JVM specification.
*/
if ((access_flags & Constants.ACC_INTERFACE) != 0) {
access_flags |= Constants.ACC_ABSTRACT;
}
if (((access_flags & Constants.ACC_ABSTRACT) != 0)
&& ((access_flags & Constants.ACC_FINAL) != 0)) {
throw new ClassFormatException("Class " + file_name + " can't be both final and abstract");
}
class_name_index = file.readUnsignedShort();
superclass_name_index = file.readUnsignedShort();
}
// in java/org/apache/tomcat/util/bcel/classfile/ClassParser.java
private final void readConstantPool() throws IOException, ClassFormatException {
constant_pool = new ConstantPool(file);
}
// in java/org/apache/tomcat/util/bcel/classfile/ClassParser.java
private final void readFields() throws IOException, ClassFormatException {
int fields_count;
fields_count = file.readUnsignedShort();
fields = new Field[fields_count];
for (int i = 0; i < fields_count; i++) {
fields[i] = new Field(file, constant_pool);
}
}
// in java/org/apache/tomcat/util/bcel/classfile/ClassParser.java
private final void readID() throws IOException, ClassFormatException {
int magic = 0xCAFEBABE;
if (file.readInt() != magic) {
throw new ClassFormatException(file_name + " is not a Java .class file");
}
}
// in java/org/apache/tomcat/util/bcel/classfile/ClassParser.java
private final void readInterfaces() throws IOException, ClassFormatException {
int interfaces_count;
interfaces_count = file.readUnsignedShort();
interfaces = new int[interfaces_count];
for (int i = 0; i < interfaces_count; i++) {
interfaces[i] = file.readUnsignedShort();
}
}
// in java/org/apache/tomcat/util/bcel/classfile/ClassParser.java
private final void readMethods() throws IOException, ClassFormatException {
int methods_count;
methods_count = file.readUnsignedShort();
methods = new Method[methods_count];
for (int i = 0; i < methods_count; i++) {
methods[i] = new Method(file, constant_pool);
}
}
// in java/org/apache/tomcat/util/bcel/classfile/ClassParser.java
private final void readVersion() throws IOException, ClassFormatException {
minor = file.readUnsignedShort();
major = file.readUnsignedShort();
}
// in java/org/apache/tomcat/util/bcel/classfile/LocalVariableTypeTable.java
Override
public final void dump(DataOutputStream file) throws IOException
{
super.dump(file);
file.writeShort(local_variable_type_table_length);
for(int i=0; i < local_variable_type_table_length; i++)
local_variable_type_table[i].dump(file);
}
// in java/org/apache/tomcat/util/bcel/classfile/SimpleElementValue.java
Override
public void dump(DataOutputStream dos) throws IOException
{
dos.writeByte(type); // u1 kind of value
switch (type)
{
case PRIMITIVE_INT:
case PRIMITIVE_BYTE:
case PRIMITIVE_CHAR:
case PRIMITIVE_FLOAT:
case PRIMITIVE_LONG:
case PRIMITIVE_BOOLEAN:
case PRIMITIVE_SHORT:
case PRIMITIVE_DOUBLE:
case STRING:
dos.writeShort(getIndex());
break;
default:
throw new RuntimeException(
"SimpleElementValue doesnt know how to write out type "
+ type);
}
}
// in java/org/apache/tomcat/util/bcel/classfile/CodeException.java
public final void dump( DataOutputStream file ) throws IOException {
file.writeShort(start_pc);
file.writeShort(end_pc);
file.writeShort(handler_pc);
file.writeShort(catch_type);
}
// in java/org/apache/tomcat/util/bcel/classfile/RuntimeVisibleAnnotations.java
Override
public final void dump(DataOutputStream dos) throws IOException
{
super.dump(dos);
writeAnnotations(dos);
}
// in java/org/apache/tomcat/util/bcel/classfile/ConstantClass.java
Override
public final void dump( DataOutputStream file ) throws IOException {
file.writeByte(tag);
file.writeShort(name_index);
}
// in java/org/apache/tomcat/util/bcel/classfile/Code.java
Override
public final void dump( DataOutputStream file ) throws IOException {
super.dump(file);
file.writeShort(max_stack);
file.writeShort(max_locals);
file.writeInt(code_length);
file.write(code, 0, code_length);
file.writeShort(exception_table_length);
for (int i = 0; i < exception_table_length; i++) {
exception_table[i].dump(file);
}
file.writeShort(attributes_count);
for (int i = 0; i < attributes_count; i++) {
attributes[i].dump(file);
}
}
// in java/org/apache/tomcat/util/bcel/classfile/ConstantCP.java
Override
public final void dump( DataOutputStream file ) throws IOException {
file.writeByte(tag);
file.writeShort(class_index);
file.writeShort(name_and_type_index);
}
// in java/org/apache/tomcat/util/bcel/classfile/ElementValuePair.java
protected void dump(DataOutputStream dos) throws IOException {
dos.writeShort(elementNameIndex); // u2 name of the element
elementValue.dump(dos);
}
// in java/org/apache/tomcat/util/bcel/classfile/LineNumber.java
public final void dump( DataOutputStream file ) throws IOException {
file.writeShort(start_pc);
file.writeShort(line_number);
}
// in java/org/apache/el/lang/FunctionMapperImpl.java
Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(this.functions);
}
// in java/org/apache/el/lang/FunctionMapperImpl.java
Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeUTF((this.prefix != null) ? this.prefix : "");
out.writeUTF(this.localName);
// make sure m isn't null
getMethod();
out.writeUTF((this.owner != null) ?
this.owner :
this.m.getDeclaringClass().getName());
out.writeUTF((this.name != null) ?
this.name :
this.m.getName());
out.writeObject((this.types != null) ?
this.types :
ReflectionUtil.toTypeNameArray(this.m.getParameterTypes()));
}
// in java/org/apache/el/lang/FunctionMapperImpl.java
Override
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
this.prefix = in.readUTF();
if ("".equals(this.prefix)) this.prefix = null;
this.localName = in.readUTF();
this.owner = in.readUTF();
this.name = in.readUTF();
this.types = (String[]) in.readObject();
}
// in java/org/apache/el/MethodExpressionImpl.java
Override
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
this.expr = in.readUTF();
String type = in.readUTF();
if (!"".equals(type)) {
this.expectedType = ReflectionUtil.forName(type);
}
this.paramTypes = ReflectionUtil.toTypeArray(((String[]) in
.readObject()));
this.fnMapper = (FunctionMapper) in.readObject();
this.varMapper = (VariableMapper) in.readObject();
}
// in java/org/apache/el/MethodExpressionImpl.java
Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeUTF(this.expr);
out.writeUTF((this.expectedType != null) ? this.expectedType.getName()
: "");
out.writeObject(ReflectionUtil.toTypeNameArray(this.paramTypes));
out.writeObject(this.fnMapper);
out.writeObject(this.varMapper);
}
// in java/org/apache/el/MethodExpressionLiteral.java
Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
this.expr = in.readUTF();
String type = in.readUTF();
if (!"".equals(type)) {
this.expectedType = ReflectionUtil.forName(type);
}
this.paramTypes = ReflectionUtil.toTypeArray(((String[]) in
.readObject()));
}
// in java/org/apache/el/MethodExpressionLiteral.java
Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeUTF(this.expr);
out.writeUTF((this.expectedType != null) ? this.expectedType.getName()
: "");
out.writeObject(ReflectionUtil.toTypeNameArray(this.paramTypes));
}
// in java/org/apache/el/parser/SimpleCharStream.java
protected void FillBuff() throws java.io.IOException
{
if (maxNextCharInd == available)
{
if (available == bufsize)
{
if (tokenBegin > 2048)
{
bufpos = maxNextCharInd = 0;
available = tokenBegin;
}
else if (tokenBegin < 0)
bufpos = maxNextCharInd = 0;
else
ExpandBuff(false);
}
else if (available > tokenBegin)
available = bufsize;
else if ((tokenBegin - available) < 2048)
ExpandBuff(true);
else
available = tokenBegin;
}
int i;
try {
if ((i = inputStream.read(buffer, maxNextCharInd, available - maxNextCharInd)) == -1)
{
inputStream.close();
throw new java.io.IOException();
}
else
maxNextCharInd += i;
return;
}
catch(java.io.IOException e) {
--bufpos;
backup(0);
if (tokenBegin == -1)
tokenBegin = bufpos;
throw e;
}
}
// in java/org/apache/el/parser/SimpleCharStream.java
public char BeginToken() throws java.io.IOException
{
tokenBegin = -1;
char c = readChar();
tokenBegin = bufpos;
return c;
}
// in java/org/apache/el/parser/SimpleCharStream.java
public char readChar() throws java.io.IOException
{
if (inBuf > 0)
{
--inBuf;
if (++bufpos == bufsize)
bufpos = 0;
return buffer[bufpos];
}
if (++bufpos >= maxNextCharInd)
FillBuff();
char c = buffer[bufpos];
UpdateLineColumn(c);
return c;
}
// in java/org/apache/el/ValueExpressionLiteral.java
Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(this.value);
out.writeUTF((this.expectedType != null) ? this.expectedType.getName()
: "");
}
// in java/org/apache/el/ValueExpressionLiteral.java
Override
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
this.value = in.readObject();
String type = in.readUTF();
if (!"".equals(type)) {
this.expectedType = ReflectionUtil.forName(type);
}
}
// in java/org/apache/el/ValueExpressionImpl.java
Override
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
this.expr = in.readUTF();
String type = in.readUTF();
if (!"".equals(type)) {
this.expectedType = ReflectionUtil.forName(type);
}
this.fnMapper = (FunctionMapper) in.readObject();
this.varMapper = (VariableMapper) in.readObject();
}
// in java/org/apache/el/ValueExpressionImpl.java
Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeUTF(this.expr);
out.writeUTF((this.expectedType != null) ? this.expectedType.getName()
: "");
out.writeObject(this.fnMapper);
out.writeObject(this.varMapper);
}
// in java/org/apache/catalina/startup/ContextConfig.java
protected void fixDocBase()
throws IOException {
Host host = (Host) context.getParent();
File appBase = host.getAppBaseFile();
String docBase = context.getDocBase();
if (docBase == null) {
// Trying to guess the docBase according to the path
String path = context.getPath();
if (path == null) {
return;
}
ContextName cn = new ContextName(path, context.getWebappVersion());
docBase = cn.getBaseName();
}
File file = new File(docBase);
if (!file.isAbsolute()) {
docBase = (new File(appBase, docBase)).getPath();
} else {
docBase = file.getCanonicalPath();
}
file = new File(docBase);
String origDocBase = docBase;
ContextName cn = new ContextName(context.getPath(),
context.getWebappVersion());
String pathName = cn.getBaseName();
boolean unpackWARs = true;
if (host instanceof StandardHost &&
context instanceof StandardContext) {
unpackWARs = ((StandardHost) host).isUnpackWARs() &&
((StandardContext) context).getUnpackWAR() &&
(docBase.startsWith(host.getAppBaseFile().getPath()));
}
if (docBase.toLowerCase(Locale.ENGLISH).endsWith(".war") && !file.isDirectory() && unpackWARs) {
URL war = new URL("jar:" + (new File(docBase)).toURI().toURL() + "!/");
docBase = ExpandWar.expand(host, war, pathName);
file = new File(docBase);
docBase = file.getCanonicalPath();
if (context instanceof StandardContext) {
((StandardContext) context).setOriginalDocBase(origDocBase);
}
} else if (docBase.toLowerCase(Locale.ENGLISH).endsWith(".war") &&
!file.isDirectory() && !unpackWARs) {
URL war =
new URL("jar:" + (new File (docBase)).toURI().toURL() + "!/");
ExpandWar.validate(host, war, pathName);
} else {
File docDir = new File(docBase);
if (!docDir.exists()) {
File warFile = new File(docBase + ".war");
if (warFile.exists()) {
URL war =
new URL("jar:" + warFile.toURI().toURL() + "!/");
if (unpackWARs) {
docBase = ExpandWar.expand(host, war, pathName);
file = new File(docBase);
docBase = file.getCanonicalPath();
} else {
docBase = warFile.getCanonicalPath();
ExpandWar.validate(host, war, pathName);
}
}
if (context instanceof StandardContext) {
((StandardContext) context).setOriginalDocBase(origDocBase);
}
}
}
if (docBase.startsWith(appBase.getPath() + File.separatorChar)) {
docBase = docBase.substring(appBase.getPath().length());
docBase = docBase.replace(File.separatorChar, '/');
if (docBase.startsWith("/")) {
docBase = docBase.substring(1);
}
} else {
docBase = docBase.replace(File.separatorChar, '/');
}
context.setDocBase(docBase);
}
// in java/org/apache/catalina/startup/ContextConfig.java
protected ServletContainerInitializer getServletContainerInitializer(
InputStream is) throws IOException {
String className = null;
if (is != null) {
String line = null;
try {
BufferedReader br =
new BufferedReader(new InputStreamReader(is, "UTF-8"));
line = br.readLine();
if (line != null && line.trim().length() > 0) {
className = line.trim();
}
} catch (UnsupportedEncodingException e) {
// Should never happen with UTF-8
// If it does - ignore & return null
}
}
ServletContainerInitializer sci = null;
try {
Class<?> clazz = Class.forName(className,true,
context.getLoader().getClassLoader());
sci = (ServletContainerInitializer) clazz.newInstance();
} catch (ClassNotFoundException e) {
log.error(sm.getString("contextConfig.invalidSci", className), e);
throw new IOException(e);
} catch (InstantiationException e) {
log.error(sm.getString("contextConfig.invalidSci", className), e);
throw new IOException(e);
} catch (IllegalAccessException e) {
log.error(sm.getString("contextConfig.invalidSci", className), e);
throw new IOException(e);
}
return sci;
}
// in java/org/apache/catalina/startup/ContextConfig.java
protected void processAnnotationsStream(InputStream is, WebXml fragment)
throws ClassFormatException, IOException {
ClassParser parser = new ClassParser(is, null);
JavaClass clazz = parser.parse();
checkHandlesTypes(clazz);
String className = clazz.getClassName();
AnnotationEntry[] annotationsEntries = clazz.getAnnotationEntries();
for (AnnotationEntry ae : annotationsEntries) {
String type = ae.getAnnotationType();
if ("Ljavax/servlet/annotation/WebServlet;".equals(type)) {
processAnnotationWebServlet(className, ae, fragment);
}else if ("Ljavax/servlet/annotation/WebFilter;".equals(type)) {
processAnnotationWebFilter(className, ae, fragment);
}else if ("Ljavax/servlet/annotation/WebListener;".equals(type)) {
fragment.addListener(className);
} else {
// Unknown annotation - ignore
}
}
}
// in java/org/apache/catalina/startup/ContextConfig.java
Override
public void scan(JarURLConnection jarConn) throws IOException {
URL url = jarConn.getURL();
URL resourceURL = jarConn.getJarFileURL();
Jar jar = null;
InputStream is = null;
WebXml fragment = new WebXml();
try {
jar = JarFactory.newInstance(url);
is = jar.getInputStream(FRAGMENT_LOCATION);
if (is == null) {
// If there is no web.xml, normal JAR no impact on
// distributable
fragment.setDistributable(true);
} else {
InputSource source = new InputSource(
resourceURL.toString() + "!/" + FRAGMENT_LOCATION);
source.setByteStream(is);
parseWebXml(source, fragment, true);
}
} finally {
if (is != null) {
try {
is.close();
} catch (IOException ioe) {
// Ignore
}
}
if (jar != null) {
jar.close();
}
fragment.setURL(url);
if (fragment.getName() == null) {
fragment.setName(fragment.getURL().toString());
}
fragments.put(fragment.getName(), fragment);
}
}
// in java/org/apache/catalina/startup/ContextConfig.java
Override
public void scan(File file) throws IOException {
InputStream stream = null;
WebXml fragment = new WebXml();
try {
File fragmentFile = new File(file, FRAGMENT_LOCATION);
if (fragmentFile.isFile()) {
stream = new FileInputStream(fragmentFile);
InputSource source =
new InputSource(fragmentFile.toURI().toURL().toString());
source.setByteStream(stream);
parseWebXml(source, fragment, true);
}
} finally {
if (stream != null) {
try {
stream.close();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
}
}
fragment.setURL(file.toURI().toURL());
if (fragment.getName() == null) {
fragment.setName(fragment.getURL().toString());
}
fragments.put(fragment.getName(), fragment);
}
}
// in java/org/apache/catalina/startup/TldConfig.java
Override
public void scan(JarURLConnection urlConn) throws IOException {
tldScanJar(urlConn);
}
// in java/org/apache/catalina/startup/TldConfig.java
private XmlErrorHandler tldScanStream(InputStream resourceStream)
throws IOException {
InputSource source = new InputSource(resourceStream);
XmlErrorHandler result = new XmlErrorHandler();
synchronized (tldDigester) {
try {
tldDigester.setErrorHandler(result);
tldDigester.push(this);
tldDigester.parse(source);
} catch (SAXException s) {
// Hack - makes exception handling simpler
throw new IOException(s);
} finally {
tldDigester.reset();
}
return result;
}
}
// in java/org/apache/catalina/startup/ClassLoaderFactory.java
private static boolean validateFile(File file,
RepositoryType type) throws IOException {
if (RepositoryType.DIR == type || RepositoryType.GLOB == type) {
if (!file.exists() || !file.isDirectory() || !file.canRead()) {
String msg = "Problem with directory [" + file +
"], exists: [" + file.exists() +
"], isDirectory: [" + file.isDirectory() +
"], canRead: [" + file.canRead() + "]";
File home = new File (Bootstrap.getCatalinaHome());
home = home.getCanonicalFile();
File base = new File (Bootstrap.getCatalinaBase());
base = base.getCanonicalFile();
File defaultValue = new File(base, "lib");
// Existence of ${catalina.base}/lib directory is optional.
// Hide the warning if Tomcat runs with separate catalina.home
// and catalina.base and that directory is absent.
if (!home.getPath().equals(base.getPath())
&& file.getPath().equals(defaultValue.getPath())
&& !file.exists()) {
log.debug(msg);
} else {
log.warn(msg);
}
return false;
}
} else if (RepositoryType.JAR == type) {
if (!file.exists() || !file.canRead()) {
log.warn("Problem with JAR file [" + file +
"], exists: [" + file.exists() +
"], canRead: [" + file.canRead() + "]");
return false;
}
}
return true;
}
// in java/org/apache/catalina/startup/ExpandWar.java
public static String expand(Host host, URL war, String pathname)
throws IOException {
// Make sure that there is no such directory already existing
File docBase = new File(host.getAppBaseFile(), pathname);
if (docBase.exists()) {
// War file is already installed
return (docBase.getAbsolutePath());
}
// Create the new document base directory
docBase.mkdir();
// Expand the WAR into the new document base directory
String canonicalDocBasePrefix = docBase.getCanonicalPath();
if (!canonicalDocBasePrefix.endsWith(File.separator)) {
canonicalDocBasePrefix += File.separator;
}
JarURLConnection juc = (JarURLConnection) war.openConnection();
juc.setUseCaches(false);
JarFile jarFile = null;
InputStream input = null;
boolean success = false;
try {
jarFile = juc.getJarFile();
Enumeration<JarEntry> jarEntries = jarFile.entries();
while (jarEntries.hasMoreElements()) {
JarEntry jarEntry = jarEntries.nextElement();
String name = jarEntry.getName();
File expandedFile = new File(docBase, name);
if (!expandedFile.getCanonicalPath().startsWith(
canonicalDocBasePrefix)) {
// Trying to expand outside the docBase
// Throw an exception to stop the deployment
throw new IllegalArgumentException(
sm.getString("expandWar.illegalPath",war, name,
expandedFile.getCanonicalPath(),
canonicalDocBasePrefix));
}
int last = name.lastIndexOf('/');
if (last >= 0) {
File parent = new File(docBase,
name.substring(0, last));
if (!parent.mkdirs() && !parent.isDirectory()) {
throw new IOException(
sm.getString("expandWar.createFailed", parent));
}
}
if (name.endsWith("/")) {
continue;
}
input = jarFile.getInputStream(jarEntry);
if(null == input)
throw new ZipException(sm.getString("expandWar.missingJarEntry", jarEntry.getName()));
// Bugzilla 33636
expand(input, expandedFile);
long lastModified = jarEntry.getTime();
if ((lastModified != -1) && (lastModified != 0)) {
expandedFile.setLastModified(lastModified);
}
input.close();
input = null;
}
success = true;
} catch (IOException e) {
throw e;
} finally {
if (!success) {
// If something went wrong, delete expanded dir to keep things
// clean
deleteDir(docBase);
}
if (input != null) {
try {
input.close();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
}
input = null;
}
if (jarFile != null) {
try {
jarFile.close();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
}
jarFile = null;
}
}
// Return the absolute path to our new document base directory
return (docBase.getAbsolutePath());
}
// in java/org/apache/catalina/startup/ExpandWar.java
public static void validate(Host host, URL war, String pathname)
throws IOException {
File docBase = new File(host.getAppBaseFile(), pathname);
// Calculate the document base directory
String canonicalDocBasePrefix = docBase.getCanonicalPath();
if (!canonicalDocBasePrefix.endsWith(File.separator)) {
canonicalDocBasePrefix += File.separator;
}
JarURLConnection juc = (JarURLConnection) war.openConnection();
juc.setUseCaches(false);
JarFile jarFile = null;
try {
jarFile = juc.getJarFile();
Enumeration<JarEntry> jarEntries = jarFile.entries();
while (jarEntries.hasMoreElements()) {
JarEntry jarEntry = jarEntries.nextElement();
String name = jarEntry.getName();
File expandedFile = new File(docBase, name);
if (!expandedFile.getCanonicalPath().startsWith(
canonicalDocBasePrefix)) {
// Entry located outside the docBase
// Throw an exception to stop the deployment
throw new IllegalArgumentException(
sm.getString("expandWar.illegalPath",war, name,
expandedFile.getCanonicalPath(),
canonicalDocBasePrefix));
}
}
} catch (IOException e) {
throw e;
} finally {
if (jarFile != null) {
try {
jarFile.close();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
}
jarFile = null;
}
}
}
// in java/org/apache/catalina/startup/ExpandWar.java
private static void expand(InputStream input, File file)
throws IOException {
BufferedOutputStream output = null;
try {
output =
new BufferedOutputStream(new FileOutputStream(file));
byte buffer[] = new byte[2048];
while (true) {
int n = input.read(buffer);
if (n <= 0)
break;
output.write(buffer, 0, n);
}
} finally {
if (output != null) {
try {
output.close();
} catch (IOException e) {
// Ignore
}
}
}
}
// in java/org/apache/catalina/loader/WebappClassLoader.java
synchronized void addJar(String jar, JarFile jarFile, File file)
throws IOException {
if (jar == null)
return;
if (jarFile == null)
return;
if (file == null)
return;
if (log.isDebugEnabled())
log.debug("addJar(" + jar + ")");
int i;
if ((jarPath != null) && (jar.startsWith(jarPath))) {
String jarName = jar.substring(jarPath.length());
while (jarName.startsWith("/"))
jarName = jarName.substring(1);
String[] result = new String[jarNames.length + 1];
for (i = 0; i < jarNames.length; i++) {
result[i] = jarNames[i];
}
result[jarNames.length] = jarName;
jarNames = result;
}
try {
// Register the JAR for tracking
long lastModified =
((ResourceAttributes) resources.getAttributes(jar))
.getLastModified();
String[] result = new String[paths.length + 1];
for (i = 0; i < paths.length; i++) {
result[i] = paths[i];
}
result[paths.length] = jar;
paths = result;
long[] result3 = new long[lastModifiedDates.length + 1];
for (i = 0; i < lastModifiedDates.length; i++) {
result3[i] = lastModifiedDates[i];
}
result3[lastModifiedDates.length] = lastModified;
lastModifiedDates = result3;
} catch (NamingException e) {
// Ignore
}
// If the JAR currently contains invalid classes, don't actually use it
// for classloading
if (!validateJarFile(file))
return;
JarFile[] result2 = new JarFile[jarFiles.length + 1];
for (i = 0; i < jarFiles.length; i++) {
result2[i] = jarFiles[i];
}
result2[jarFiles.length] = jarFile;
jarFiles = result2;
// Add the file to the list
File[] result4 = new File[jarRealFiles.length + 1];
for (i = 0; i < jarRealFiles.length; i++) {
result4[i] = jarRealFiles[i];
}
result4[jarRealFiles.length] = file;
jarRealFiles = result4;
}
// in java/org/apache/catalina/loader/WebappClassLoader.java
Override
public Enumeration<URL> findResources(String name) throws IOException {
if (log.isDebugEnabled())
log.debug(" findResources(" + name + ")");
//we use a LinkedHashSet instead of a Vector to avoid duplicates with virtualmappings
LinkedHashSet<URL> result = new LinkedHashSet<URL>();
int jarFilesLength = jarFiles.length;
int repositoriesLength = repositories.length;
int i;
// Adding the results of a call to the superclass
if (hasExternalRepositories && searchExternalFirst) {
Enumeration<URL> otherResourcePaths = super.findResources(name);
while (otherResourcePaths.hasMoreElements()) {
result.add(otherResourcePaths.nextElement());
}
}
// Looking at the repositories
for (i = 0; i < repositoriesLength; i++) {
try {
String fullPath = repositories[i] + name;
resources.lookup(fullPath);
// Note : Not getting an exception here means the resource was
// found
try {
result.add(getURI(new File(files[i], name)));
} catch (MalformedURLException e) {
// Ignore
}
} catch (NamingException e) {
// Ignore
}
}
// Looking at the JAR files
synchronized (jarFiles) {
if (openJARs()) {
for (i = 0; i < jarFilesLength; i++) {
JarEntry jarEntry = jarFiles[i].getJarEntry(name);
if (jarEntry != null) {
try {
String jarFakeUrl = getURI(jarRealFiles[i]).toString();
jarFakeUrl = "jar:" + jarFakeUrl + "!/" + name;
result.add(new URL(jarFakeUrl));
} catch (MalformedURLException e) {
// Ignore
}
}
}
}
}
// Adding the results of a call to the superclass
if (hasExternalRepositories && !searchExternalFirst) {
Enumeration<URL> otherResourcePaths = super.findResources(name);
while (otherResourcePaths.hasMoreElements()) {
result.add(otherResourcePaths.nextElement());
}
}
final Iterator<URL> iterator = result.iterator();
return new Enumeration<URL>() {
@Override
public boolean hasMoreElements() {
return iterator.hasNext();
}
@Override
public URL nextElement() {
return iterator.next();
}
};
}
// in java/org/apache/catalina/loader/WebappClassLoader.java
protected boolean validateJarFile(File file)
throws IOException {
if (triggers == null)
return (true);
JarFile jarFile = null;
try {
jarFile = new JarFile(file);
for (int i = 0; i < triggers.length; i++) {
Class<?> clazz = null;
try {
if (parent != null) {
clazz = parent.loadClass(triggers[i]);
} else {
clazz = Class.forName(triggers[i]);
}
} catch (Exception e) {
clazz = null;
}
if (clazz == null)
continue;
String name = triggers[i].replace('.', '/') + ".class";
if (log.isDebugEnabled())
log.debug(" Checking for " + name);
JarEntry jarEntry = jarFile.getJarEntry(name);
if (jarEntry != null) {
log.info("validateJarFile(" + file +
") - jar not loaded. See Servlet Spec 2.3, "
+ "section 9.7.2. Offending class: " + name);
return false;
}
}
return true;
} finally {
if (jarFile != null) {
try {
jarFile.close();
} catch (IOException ioe) {
// Ignore
}
}
}
}
// in java/org/apache/catalina/loader/WebappLoader.java
private void setRepositories() throws IOException {
if (!(container instanceof Context))
return;
ServletContext servletContext =
((Context) container).getServletContext();
if (servletContext == null)
return;
loaderRepositories=new ArrayList<String>();
// Loading the work directory
File workDir =
(File) servletContext.getAttribute(ServletContext.TEMPDIR);
if (workDir == null) {
log.info("No work dir for " + servletContext);
}
if( log.isDebugEnabled() && workDir != null)
log.debug(sm.getString("webappLoader.deploy", workDir.getAbsolutePath()));
classLoader.setWorkDir(workDir);
DirContext resources = container.getResources();
// Setting up the class repository (/WEB-INF/classes), if it exists
String classesPath = "/WEB-INF/classes";
DirContext classes = null;
try {
Object object = resources.lookup(classesPath);
if (object instanceof DirContext) {
classes = (DirContext) object;
}
} catch(NamingException e) {
// Silent catch: it's valid that no /WEB-INF/classes collection
// exists
}
if (classes != null) {
File classRepository = null;
String absoluteClassesPath =
servletContext.getRealPath(classesPath);
if (absoluteClassesPath != null) {
classRepository = new File(absoluteClassesPath);
} else {
classRepository = new File(workDir, classesPath);
if (!classRepository.mkdirs() &&
!classRepository.isDirectory()) {
throw new IOException(
sm.getString("webappLoader.mkdirFailure"));
}
if (!copyDir(classes, classRepository)) {
throw new IOException(
sm.getString("webappLoader.copyFailure"));
}
}
if(log.isDebugEnabled())
log.debug(sm.getString("webappLoader.classDeploy", classesPath,
classRepository.getAbsolutePath()));
// Adding the repository to the class loader
classLoader.addRepository(classesPath + "/", classRepository);
loaderRepositories.add(classesPath + "/" );
}
// Setting up the JAR repository (/WEB-INF/lib), if it exists
String libPath = "/WEB-INF/lib";
classLoader.setJarPath(libPath);
DirContext libDir = null;
// Looking up directory /WEB-INF/lib in the context
try {
Object object = resources.lookup(libPath);
if (object instanceof DirContext)
libDir = (DirContext) object;
} catch(NamingException e) {
// Silent catch: it's valid that no /WEB-INF/lib collection
// exists
}
if (libDir != null) {
boolean copyJars = false;
String absoluteLibPath = servletContext.getRealPath(libPath);
File destDir = null;
if (absoluteLibPath != null) {
destDir = new File(absoluteLibPath);
} else {
copyJars = true;
destDir = new File(workDir, libPath);
if (!destDir.mkdirs() && !destDir.isDirectory()) {
throw new IOException(
sm.getString("webappLoader.mkdirFailure"));
}
}
// Looking up directory /WEB-INF/lib in the context
NamingEnumeration<NameClassPair> enumeration = null;
try {
enumeration = libDir.list("");
} catch (NamingException e) {
IOException ioe = new IOException(sm.getString(
"webappLoader.namingFailure", libPath));
ioe.initCause(e);
throw ioe;
}
while (enumeration.hasMoreElements()) {
NameClassPair ncPair = enumeration.nextElement();
String filename = libPath + "/" + ncPair.getName();
if (!filename.endsWith(".jar"))
continue;
// Copy JAR in the work directory, always (the JAR file
// would get locked otherwise, which would make it
// impossible to update it or remove it at runtime)
File destFile = new File(destDir, ncPair.getName());
if( log.isDebugEnabled())
log.debug(sm.getString("webappLoader.jarDeploy", filename,
destFile.getAbsolutePath()));
// Bug 45403 - Explicitly call lookup() on the name to check
// that the resource is readable. We cannot use resources
// returned by listBindings(), because that lists all of them,
// but does not perform the necessary checks on each.
Object obj = null;
try {
obj = libDir.lookup(ncPair.getName());
} catch (NamingException e) {
IOException ioe = new IOException(sm.getString(
"webappLoader.namingFailure", filename));
ioe.initCause(e);
throw ioe;
}
if (!(obj instanceof Resource))
continue;
Resource jarResource = (Resource) obj;
if (copyJars) {
if (!copy(jarResource.streamContent(),
new FileOutputStream(destFile))) {
throw new IOException(
sm.getString("webappLoader.copyFailure"));
}
}
try {
JarFile jarFile = new JarFile(destFile);
classLoader.addJar(filename, jarFile, destFile);
} catch (Exception ex) {
// Catch the exception if there is an empty jar file
// Should ignore and continue loading other jar files
// in the dir
}
loaderRepositories.add( filename );
}
}
}
// in java/org/apache/catalina/realm/RealmBase.java
Override
public boolean hasResourcePermission(Request request,
Response response,
SecurityConstraint []constraints,
Context context)
throws IOException {
if (constraints == null || constraints.length == 0)
return (true);
// Specifically allow access to the form login and form error pages
// and the "j_security_check" action
LoginConfig config = context.getLoginConfig();
if ((config != null) &&
(Constants.FORM_METHOD.equals(config.getAuthMethod()))) {
String requestURI = request.getRequestPathMB().toString();
String loginPage = config.getLoginPage();
if (loginPage.equals(requestURI)) {
if (log.isDebugEnabled())
log.debug(" Allow access to login page " + loginPage);
return (true);
}
String errorPage = config.getErrorPage();
if (errorPage.equals(requestURI)) {
if (log.isDebugEnabled())
log.debug(" Allow access to error page " + errorPage);
return (true);
}
if (requestURI.endsWith(Constants.FORM_ACTION)) {
if (log.isDebugEnabled())
log.debug(" Allow access to username/password submission");
return (true);
}
}
// Which user principal have we already authenticated?
Principal principal = request.getPrincipal();
boolean status = false;
boolean denyfromall = false;
for(int i=0; i < constraints.length; i++) {
SecurityConstraint constraint = constraints[i];
String roles[];
if (constraint.getAllRoles()) {
// * means all roles defined in web.xml
roles = request.getContext().findSecurityRoles();
} else {
roles = constraint.findAuthRoles();
}
if (roles == null)
roles = new String[0];
if (log.isDebugEnabled())
log.debug(" Checking roles " + principal);
if (roles.length == 0 && !constraint.getAllRoles()) {
if(constraint.getAuthConstraint()) {
if( log.isDebugEnabled() )
log.debug("No roles");
status = false; // No listed roles means no access at all
denyfromall = true;
break;
}
if(log.isDebugEnabled())
log.debug("Passing all access");
status = true;
} else if (principal == null) {
if (log.isDebugEnabled())
log.debug(" No user authenticated, cannot grant access");
} else {
for (int j = 0; j < roles.length; j++) {
if (hasRole(null, principal, roles[j])) {
status = true;
if( log.isDebugEnabled() )
log.debug( "Role found: " + roles[j]);
}
else if( log.isDebugEnabled() )
log.debug( "No role found: " + roles[j]);
}
}
}
if (!denyfromall && allRolesMode != AllRolesMode.STRICT_MODE &&
!status && principal != null) {
if (log.isDebugEnabled()) {
log.debug("Checking for all roles mode: " + allRolesMode);
}
// Check for an all roles(role-name="*")
for (int i = 0; i < constraints.length; i++) {
SecurityConstraint constraint = constraints[i];
String roles[];
// If the all roles mode exists, sets
if (constraint.getAllRoles()) {
if (allRolesMode == AllRolesMode.AUTH_ONLY_MODE) {
if (log.isDebugEnabled()) {
log.debug("Granting access for role-name=*, auth-only");
}
status = true;
break;
}
// For AllRolesMode.STRICT_AUTH_ONLY_MODE there must be zero roles
roles = request.getContext().findSecurityRoles();
if (roles.length == 0 && allRolesMode == AllRolesMode.STRICT_AUTH_ONLY_MODE) {
if (log.isDebugEnabled()) {
log.debug("Granting access for role-name=*, strict auth-only");
}
status = true;
break;
}
}
}
}
// Return a "Forbidden" message denying access to this resource
if(!status) {
response.sendError
(HttpServletResponse.SC_FORBIDDEN,
sm.getString("realmBase.forbidden"));
}
return status;
}
// in java/org/apache/catalina/realm/RealmBase.java
Override
public boolean hasUserDataPermission(Request request,
Response response,
SecurityConstraint []constraints)
throws IOException {
// Is there a relevant user data constraint?
if (constraints == null || constraints.length == 0) {
if (log.isDebugEnabled())
log.debug(" No applicable security constraint defined");
return (true);
}
for(int i=0; i < constraints.length; i++) {
SecurityConstraint constraint = constraints[i];
String userConstraint = constraint.getUserConstraint();
if (userConstraint == null) {
if (log.isDebugEnabled())
log.debug(" No applicable user data constraint defined");
return (true);
}
if (userConstraint.equals(Constants.NONE_TRANSPORT)) {
if (log.isDebugEnabled())
log.debug(" User data constraint has no restrictions");
return (true);
}
}
// Validate the request against the user data constraint
if (request.getRequest().isSecure()) {
if (log.isDebugEnabled())
log.debug(" User data constraint already satisfied");
return (true);
}
// Initialize variables we need to determine the appropriate action
int redirectPort = request.getConnector().getRedirectPort();
// Is redirecting disabled?
if (redirectPort <= 0) {
if (log.isDebugEnabled())
log.debug(" SSL redirect is disabled");
response.sendError
(HttpServletResponse.SC_FORBIDDEN,
request.getRequestURI());
return (false);
}
// Redirect to the corresponding SSL port
StringBuilder file = new StringBuilder();
String protocol = "https";
String host = request.getServerName();
// Protocol
file.append(protocol).append("://").append(host);
// Host with port
if(redirectPort != 443) {
file.append(":").append(redirectPort);
}
// URI
file.append(request.getRequestURI());
String requestedSessionId = request.getRequestedSessionId();
if ((requestedSessionId != null) &&
request.isRequestedSessionIdFromURL()) {
file.append(";");
file.append(SessionConfig.getSessionUriParamName(
request.getContext()));
file.append("=");
file.append(requestedSessionId);
}
String queryString = request.getQueryString();
if (queryString != null) {
file.append('?');
file.append(queryString);
}
if (log.isDebugEnabled())
log.debug(" Redirecting to " + file.toString());
response.sendRedirect(file.toString());
return (false);
}
// in java/org/apache/catalina/realm/JAASCallbackHandler.java
Override
public void handle(Callback callbacks[])
throws IOException, UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof NameCallback) {
if (realm.getContainer().getLogger().isTraceEnabled())
realm.getContainer().getLogger().trace(sm.getString("jaasCallback.username", username));
((NameCallback) callbacks[i]).setName(username);
} else if (callbacks[i] instanceof PasswordCallback) {
final char[] passwordcontents;
if (password != null) {
passwordcontents = password.toCharArray();
} else {
passwordcontents = new char[0];
}
((PasswordCallback) callbacks[i]).setPassword
(passwordcontents);
} else if (callbacks[i] instanceof TextInputCallback) {
TextInputCallback cb = ((TextInputCallback) callbacks[i]);
if (cb.getPrompt().equals("nonce")) {
cb.setText(nonce);
} else if (cb.getPrompt().equals("nc")) {
cb.setText(nc);
} else if (cb.getPrompt().equals("cnonce")) {
cb.setText(cnonce);
} else if (cb.getPrompt().equals("qop")) {
cb.setText(qop);
} else if (cb.getPrompt().equals("realmName")) {
cb.setText(realmName);
} else if (cb.getPrompt().equals("md5a2")) {
cb.setText(md5a2);
} else if (cb.getPrompt().equals("authMethod")) {
cb.setText(authMethod);
} else {
throw new UnsupportedCallbackException(callbacks[i]);
}
} else {
throw new UnsupportedCallbackException(callbacks[i]);
}
}
}
// in java/org/apache/catalina/mbeans/JmxRemoteLifecycleListener.java
Override
public Socket createSocket(String host, int port) throws IOException {
if (factory == null) {
return new Socket(FORCED_HOST, port);
} else {
return factory.createSocket(FORCED_HOST, port);
}
}
// in java/org/apache/catalina/filters/SetCharacterEncodingFilter.java
Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
// Conditionally select and set the character encoding to be used
if (ignore || (request.getCharacterEncoding() == null)) {
String characterEncoding = selectEncoding(request);
if (characterEncoding != null) {
request.setCharacterEncoding(characterEncoding);
}
}
// Pass control on to the next filter
chain.doFilter(request, response);
}
// in java/org/apache/catalina/filters/RequestDumperFilter.java
Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
HttpServletRequest hRequest = null;
HttpServletResponse hResponse = null;
if (request instanceof HttpServletRequest) {
hRequest = (HttpServletRequest) request;
}
if (response instanceof HttpServletResponse) {
hResponse = (HttpServletResponse) response;
}
// Log pre-service information
doLog("START TIME ", getTimestamp());
if (hRequest == null) {
doLog(" requestURI", NON_HTTP_REQ_MSG);
doLog(" authType", NON_HTTP_REQ_MSG);
} else {
doLog(" requestURI", hRequest.getRequestURI());
doLog(" authType", hRequest.getAuthType());
}
doLog(" characterEncoding", request.getCharacterEncoding());
doLog(" contentLength",
Integer.valueOf(request.getContentLength()).toString());
doLog(" contentType", request.getContentType());
if (hRequest == null) {
doLog(" contextPath", NON_HTTP_REQ_MSG);
doLog(" cookie", NON_HTTP_REQ_MSG);
doLog(" header", NON_HTTP_REQ_MSG);
} else {
doLog(" contextPath", hRequest.getContextPath());
Cookie cookies[] = hRequest.getCookies();
if (cookies != null) {
for (int i = 0; i < cookies.length; i++) {
doLog(" cookie", cookies[i].getName() +
"=" + cookies[i].getValue());
}
}
Enumeration<String> hnames = hRequest.getHeaderNames();
while (hnames.hasMoreElements()) {
String hname = hnames.nextElement();
Enumeration<String> hvalues = hRequest.getHeaders(hname);
while (hvalues.hasMoreElements()) {
String hvalue = hvalues.nextElement();
doLog(" header", hname + "=" + hvalue);
}
}
}
doLog(" locale", request.getLocale().toString());
if (hRequest == null) {
doLog(" method", NON_HTTP_REQ_MSG);
} else {
doLog(" method", hRequest.getMethod());
}
Enumeration<String> pnames = request.getParameterNames();
while (pnames.hasMoreElements()) {
String pname = pnames.nextElement();
String pvalues[] = request.getParameterValues(pname);
StringBuilder result = new StringBuilder(pname);
result.append('=');
for (int i = 0; i < pvalues.length; i++) {
if (i > 0) {
result.append(", ");
}
result.append(pvalues[i]);
}
doLog(" parameter", result.toString());
}
if (hRequest == null) {
doLog(" pathInfo", NON_HTTP_REQ_MSG);
} else {
doLog(" pathInfo", hRequest.getPathInfo());
}
doLog(" protocol", request.getProtocol());
if (hRequest == null) {
doLog(" queryString", NON_HTTP_REQ_MSG);
} else {
doLog(" queryString", hRequest.getQueryString());
}
doLog(" remoteAddr", request.getRemoteAddr());
doLog(" remoteHost", request.getRemoteHost());
if (hRequest == null) {
doLog(" remoteUser", NON_HTTP_REQ_MSG);
doLog("requestedSessionId", NON_HTTP_REQ_MSG);
} else {
doLog(" remoteUser", hRequest.getRemoteUser());
doLog("requestedSessionId", hRequest.getRequestedSessionId());
}
doLog(" scheme", request.getScheme());
doLog(" serverName", request.getServerName());
doLog(" serverPort",
Integer.valueOf(request.getServerPort()).toString());
if (hRequest == null) {
doLog(" servletPath", NON_HTTP_REQ_MSG);
} else {
doLog(" servletPath", hRequest.getServletPath());
}
doLog(" isSecure",
Boolean.valueOf(request.isSecure()).toString());
doLog("------------------",
"--------------------------------------------");
// Perform the request
chain.doFilter(request, response);
// Log post-service information
doLog("------------------",
"--------------------------------------------");
if (hRequest == null) {
doLog(" authType", NON_HTTP_REQ_MSG);
} else {
doLog(" authType", hRequest.getAuthType());
}
doLog(" contentType", response.getContentType());
if (hResponse == null) {
doLog(" header", NON_HTTP_RES_MSG);
} else {
Iterable<String> rhnames = hResponse.getHeaderNames();
for (String rhname : rhnames) {
Iterable<String> rhvalues = hResponse.getHeaders(rhname);
for (String rhvalue : rhvalues) {
doLog(" header", rhname + "=" + rhvalue);
}
}
}
if (hRequest == null) {
doLog(" remoteUser", NON_HTTP_REQ_MSG);
} else {
doLog(" remoteUser", hRequest.getRemoteUser());
}
if (hResponse == null) {
doLog(" remoteUser", NON_HTTP_RES_MSG);
} else {
doLog(" status",
Integer.valueOf(hResponse.getStatus()).toString());
}
doLog("END TIME ", getTimestamp());
doLog("==================",
"============================================");
}
// in java/org/apache/catalina/filters/RequestFilter.java
protected void process(String property, ServletRequest request,
ServletResponse response, FilterChain chain)
throws IOException, ServletException {
if (isAllowed(property)) {
chain.doFilter(request, response);
} else {
if (response instanceof HttpServletResponse) {
((HttpServletResponse) response).sendError(denyStatus);
} else {
sendErrorWhenNotHttp(response);
}
}
}
// in java/org/apache/catalina/filters/RequestFilter.java
protected void processCometEvent(String property, CometEvent event,
CometFilterChain chain) throws IOException, ServletException {
HttpServletResponse response = event.getHttpServletResponse();
if (isAllowed(property)) {
chain.doFilterEvent(event);
} else {
response.sendError(denyStatus);
event.close();
}
}
// in java/org/apache/catalina/filters/RequestFilter.java
private void sendErrorWhenNotHttp(ServletResponse response)
throws IOException {
response.setContentType(PLAIN_TEXT_MIME_TYPE);
response.getWriter().write(sm.getString("http.403"));
response.getWriter().flush();
}
// in java/org/apache/catalina/filters/AddDefaultCharsetFilter.java
Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// Wrap the response
if (response instanceof HttpServletResponse) {
ResponseWrapper wrapped =
new ResponseWrapper((HttpServletResponse)response, encoding);
chain.doFilter(request, wrapped);
} else {
chain.doFilter(request, response);
}
}
// in java/org/apache/catalina/filters/RemoteHostFilter.java
Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
process(request.getRemoteHost(), request, response, chain);
}
// in java/org/apache/catalina/filters/RemoteHostFilter.java
Override
public void doFilterEvent(CometEvent event, CometFilterChain chain)
throws IOException, ServletException {
processCometEvent(event.getHttpServletRequest().getRemoteHost(),
event, chain);
}
// in java/org/apache/catalina/filters/ExpiresFilter.java
Override
public ServletOutputStream getOutputStream() throws IOException {
if (servletOutputStream == null) {
servletOutputStream = new XServletOutputStream(
super.getOutputStream(), request, this);
}
return servletOutputStream;
}
// in java/org/apache/catalina/filters/ExpiresFilter.java
Override
public PrintWriter getWriter() throws IOException {
if (printWriter == null) {
printWriter = new XPrintWriter(super.getWriter(), request, this);
}
return printWriter;
}
// in java/org/apache/catalina/filters/ExpiresFilter.java
Override
public void close() throws IOException {
fireOnBeforeWriteResponseBodyEvent();
servletOutputStream.close();
}
// in java/org/apache/catalina/filters/ExpiresFilter.java
Override
public void flush() throws IOException {
fireOnBeforeWriteResponseBodyEvent();
servletOutputStream.flush();
}
// in java/org/apache/catalina/filters/ExpiresFilter.java
Override
public void print(boolean b) throws IOException {
fireOnBeforeWriteResponseBodyEvent();
servletOutputStream.print(b);
}
// in java/org/apache/catalina/filters/ExpiresFilter.java
Override
public void print(char c) throws IOException {
fireOnBeforeWriteResponseBodyEvent();
servletOutputStream.print(c);
}
// in java/org/apache/catalina/filters/ExpiresFilter.java
Override
public void print(double d) throws IOException {
fireOnBeforeWriteResponseBodyEvent();
servletOutputStream.print(d);
}
// in java/org/apache/catalina/filters/ExpiresFilter.java
Override
public void print(float f) throws IOException {
fireOnBeforeWriteResponseBodyEvent();
servletOutputStream.print(f);
}
// in java/org/apache/catalina/filters/ExpiresFilter.java
Override
public void print(int i) throws IOException {
fireOnBeforeWriteResponseBodyEvent();
servletOutputStream.print(i);
}
// in java/org/apache/catalina/filters/ExpiresFilter.java
Override
public void print(long l) throws IOException {
fireOnBeforeWriteResponseBodyEvent();
servletOutputStream.print(l);
}
// in java/org/apache/catalina/filters/ExpiresFilter.java
Override
public void print(String s) throws IOException {
fireOnBeforeWriteResponseBodyEvent();
servletOutputStream.print(s);
}
// in java/org/apache/catalina/filters/ExpiresFilter.java
Override
public void println() throws IOException {
fireOnBeforeWriteResponseBodyEvent();
servletOutputStream.println();
}
// in java/org/apache/catalina/filters/ExpiresFilter.java
Override
public void println(boolean b) throws IOException {
fireOnBeforeWriteResponseBodyEvent();
servletOutputStream.println(b);
}
// in java/org/apache/catalina/filters/ExpiresFilter.java
Override
public void println(char c) throws IOException {
fireOnBeforeWriteResponseBodyEvent();
servletOutputStream.println(c);
}
// in java/org/apache/catalina/filters/ExpiresFilter.java
Override
public void println(double d) throws IOException {
fireOnBeforeWriteResponseBodyEvent();
servletOutputStream.println(d);
}
// in java/org/apache/catalina/filters/ExpiresFilter.java
Override
public void println(float f) throws IOException {
fireOnBeforeWriteResponseBodyEvent();
servletOutputStream.println(f);
}
// in java/org/apache/catalina/filters/ExpiresFilter.java
Override
public void println(int i) throws IOException {
fireOnBeforeWriteResponseBodyEvent();
servletOutputStream.println(i);
}
// in java/org/apache/catalina/filters/ExpiresFilter.java
Override
public void println(long l) throws IOException {
fireOnBeforeWriteResponseBodyEvent();
servletOutputStream.println(l);
}
// in java/org/apache/catalina/filters/ExpiresFilter.java
Override
public void println(String s) throws IOException {
fireOnBeforeWriteResponseBodyEvent();
servletOutputStream.println(s);
}
// in java/org/apache/catalina/filters/ExpiresFilter.java
Override
public void write(byte[] b) throws IOException {
fireOnBeforeWriteResponseBodyEvent();
servletOutputStream.write(b);
}
// in java/org/apache/catalina/filters/ExpiresFilter.java
Override
public void write(byte[] b, int off, int len) throws IOException {
fireOnBeforeWriteResponseBodyEvent();
servletOutputStream.write(b, off, len);
}
// in java/org/apache/catalina/filters/ExpiresFilter.java
Override
public void write(int b) throws IOException {
fireOnBeforeWriteResponseBodyEvent();
servletOutputStream.write(b);
}
// in java/org/apache/catalina/filters/ExpiresFilter.java
Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
if (request instanceof HttpServletRequest &&
response instanceof HttpServletResponse) {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
if (response.isCommitted()) {
if (log.isDebugEnabled()) {
log.debug(sm.getString(
"expiresFilter.responseAlreadyCommited",
httpRequest.getRequestURL()));
}
chain.doFilter(request, response);
} else {
XHttpServletResponse xResponse = new XHttpServletResponse(
httpRequest, httpResponse);
chain.doFilter(request, xResponse);
if (!xResponse.isWriteResponseBodyStarted()) {
// Empty response, manually trigger
// onBeforeWriteResponseBody()
onBeforeWriteResponseBody(httpRequest, xResponse);
}
}
} else {
chain.doFilter(request, response);
}
}
// in java/org/apache/catalina/filters/RemoteIpFilter.java
public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
if (internalProxies != null &&
internalProxies.matcher(request.getRemoteAddr()).matches()) {
String remoteIp = null;
// In java 6, proxiesHeaderValue should be declared as a java.util.Deque
LinkedList<String> proxiesHeaderValue = new LinkedList<String>();
StringBuilder concatRemoteIpHeaderValue = new StringBuilder();
for (Enumeration<String> e = request.getHeaders(remoteIpHeader); e.hasMoreElements();) {
if (concatRemoteIpHeaderValue.length() > 0) {
concatRemoteIpHeaderValue.append(", ");
}
concatRemoteIpHeaderValue.append(e.nextElement());
}
String[] remoteIpHeaderValue = commaDelimitedListToStringArray(concatRemoteIpHeaderValue.toString());
int idx;
// loop on remoteIpHeaderValue to find the first trusted remote ip and to build the proxies chain
for (idx = remoteIpHeaderValue.length - 1; idx >= 0; idx--) {
String currentRemoteIp = remoteIpHeaderValue[idx];
remoteIp = currentRemoteIp;
if (internalProxies.matcher(currentRemoteIp).matches()) {
// do nothing, internalProxies IPs are not appended to the
} else if (trustedProxies != null &&
trustedProxies.matcher(currentRemoteIp).matches()) {
proxiesHeaderValue.addFirst(currentRemoteIp);
} else {
idx--; // decrement idx because break statement doesn't do it
break;
}
}
// continue to loop on remoteIpHeaderValue to build the new value of the remoteIpHeader
LinkedList<String> newRemoteIpHeaderValue = new LinkedList<String>();
for (; idx >= 0; idx--) {
String currentRemoteIp = remoteIpHeaderValue[idx];
newRemoteIpHeaderValue.addFirst(currentRemoteIp);
}
XForwardedRequest xRequest = new XForwardedRequest(request);
if (remoteIp != null) {
xRequest.setRemoteAddr(remoteIp);
xRequest.setRemoteHost(remoteIp);
if (proxiesHeaderValue.size() == 0) {
xRequest.removeHeader(proxiesHeader);
} else {
String commaDelimitedListOfProxies = listToCommaDelimitedString(proxiesHeaderValue);
xRequest.setHeader(proxiesHeader, commaDelimitedListOfProxies);
}
if (newRemoteIpHeaderValue.size() == 0) {
xRequest.removeHeader(remoteIpHeader);
} else {
String commaDelimitedRemoteIpHeaderValue = listToCommaDelimitedString(newRemoteIpHeaderValue);
xRequest.setHeader(remoteIpHeader, commaDelimitedRemoteIpHeaderValue);
}
}
if (protocolHeader != null) {
String protocolHeaderValue = request.getHeader(protocolHeader);
if (protocolHeaderValue == null) {
// don't modify the secure,scheme and serverPort attributes of the request
} else if (protocolHeaderHttpsValue.equalsIgnoreCase(protocolHeaderValue)) {
xRequest.setSecure(true);
xRequest.setScheme("https");
setPorts(xRequest, httpsServerPort);
} else {
xRequest.setSecure(false);
xRequest.setScheme("http");
setPorts(xRequest, httpServerPort);
}
}
if (log.isDebugEnabled()) {
log.debug("Incoming request " + request.getRequestURI() + " with originalRemoteAddr '" + request.getRemoteAddr()
+ "', originalRemoteHost='" + request.getRemoteHost() + "', originalSecure='" + request.isSecure()
+ "', originalScheme='" + request.getScheme() + "', original[" + remoteIpHeader + "]='"
+ concatRemoteIpHeaderValue + "', original[" + protocolHeader + "]='"
+ (protocolHeader == null ? null : request.getHeader(protocolHeader)) + "' will be seen as newRemoteAddr='"
+ xRequest.getRemoteAddr() + "', newRemoteHost='" + xRequest.getRemoteHost() + "', newScheme='"
+ xRequest.getScheme() + "', newSecure='" + xRequest.isSecure() + "', new[" + remoteIpHeader + "]='"
+ xRequest.getHeader(remoteIpHeader) + "', new[" + proxiesHeader + "]='" + xRequest.getHeader(proxiesHeader) + "'");
}
if (requestAttributesEnabled) {
request.setAttribute(AccessLog.REMOTE_ADDR_ATTRIBUTE,
request.getRemoteAddr());
request.setAttribute(AccessLog.REMOTE_HOST_ATTRIBUTE,
request.getRemoteHost());
request.setAttribute(AccessLog.PROTOCOL_ATTRIBUTE,
request.getProtocol());
request.setAttribute(AccessLog.SERVER_PORT_ATTRIBUTE,
Integer.valueOf(request.getServerPort()));
}
chain.doFilter(xRequest, response);
} else {
if (log.isDebugEnabled()) {
log.debug("Skip RemoteIpFilter for request " + request.getRequestURI() + " with originalRemoteAddr '"
+ request.getRemoteAddr() + "'");
}
chain.doFilter(request, response);
}
}
// in java/org/apache/catalina/filters/RemoteIpFilter.java
Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if (request instanceof HttpServletRequest && response instanceof HttpServletResponse) {
doFilter((HttpServletRequest)request, (HttpServletResponse)response, chain);
} else {
chain.doFilter(request, response);
}
}
// in java/org/apache/catalina/filters/WebdavFixFilter.java
Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
if (!(request instanceof HttpServletRequest) ||
!(response instanceof HttpServletResponse)) {
chain.doFilter(request, response);
return;
}
HttpServletRequest httpRequest = ((HttpServletRequest) request);
HttpServletResponse httpResponse = ((HttpServletResponse) response);
String ua = httpRequest.getHeader("User-Agent");
if (ua == null || ua.length() == 0 ||
!ua.startsWith(UA_MINIDIR_START)) {
// No UA or starts with non MS value
// Hope everything just works...
chain.doFilter(request, response);
} else if (ua.startsWith(UA_MINIDIR_5_1_2600)) {
// XP 32-bit SP3 - needs redirect with explicit port
httpResponse.sendRedirect(buildRedirect(httpRequest));
} else if (ua.startsWith(UA_MINIDIR_5_2_3790)) {
// XP 64-bit SP2
if (!"".equals(httpRequest.getContextPath())) {
log(request,
"XP-x64-SP2 clients only work with the root context");
}
// Namespace issue maybe
// see http://greenbytes.de/tech/webdav/webdav-redirector-list.html
log(request, "XP-x64-SP2 is known not to work with WebDAV Servlet");
chain.doFilter(request, response);
} else {
// Don't know which MS client it is - try the redirect with an
// explicit port in the hope that it moves the client to a different
// WebDAV implementation that works
httpResponse.sendRedirect(buildRedirect(httpRequest));
}
}
// in java/org/apache/catalina/filters/RemoteAddrFilter.java
Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
process(request.getRemoteAddr(), request, response, chain);
}
// in java/org/apache/catalina/filters/RemoteAddrFilter.java
Override
public void doFilterEvent(CometEvent event, CometFilterChain chain)
throws IOException, ServletException {
processCometEvent(event.getHttpServletRequest().getRemoteAddr(),
event, chain);
}
// in java/org/apache/catalina/filters/CsrfPreventionFilter.java
Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
ServletResponse wResponse = null;
if (request instanceof HttpServletRequest &&
response instanceof HttpServletResponse) {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
boolean skipNonceCheck = false;
if (Constants.METHOD_GET.equals(req.getMethod())) {
String path = req.getServletPath();
if (req.getPathInfo() != null) {
path = path + req.getPathInfo();
}
if (entryPoints.contains(path)) {
skipNonceCheck = true;
}
}
@SuppressWarnings("unchecked")
LruCache<String> nonceCache =
(LruCache<String>) req.getSession(true).getAttribute(
Constants.CSRF_NONCE_SESSION_ATTR_NAME);
if (!skipNonceCheck) {
String previousNonce =
req.getParameter(Constants.CSRF_NONCE_REQUEST_PARAM);
if (nonceCache != null && !nonceCache.contains(previousNonce)) {
res.sendError(HttpServletResponse.SC_FORBIDDEN);
return;
}
}
if (nonceCache == null) {
nonceCache = new LruCache<String>(nonceCacheSize);
req.getSession().setAttribute(
Constants.CSRF_NONCE_SESSION_ATTR_NAME, nonceCache);
}
String newNonce = generateNonce();
nonceCache.add(newNonce);
wResponse = new CsrfResponseWrapper(res, newNonce);
} else {
wResponse = response;
}
chain.doFilter(request, wResponse);
}
// in java/org/apache/catalina/filters/FailedRequestFilter.java
Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
if (!isGoodRequest(request)) {
((HttpServletResponse) response)
.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
chain.doFilter(request, response);
}
// in java/org/apache/catalina/filters/FailedRequestFilter.java
Override
public void doFilterEvent(CometEvent event, CometFilterChain chain)
throws IOException, ServletException {
if (event.getEventType() == CometEvent.EventType.BEGIN
&& !isGoodRequest(event.getHttpServletRequest())) {
event.getHttpServletResponse().sendError(
HttpServletResponse.SC_BAD_REQUEST);
event.close();
return;
}
chain.doFilterEvent(event);
}
// in java/org/apache/catalina/ant/jmx/JMXAccessorTask.java
public static MBeanServerConnection createJMXConnection(String url,
String host, String port, String username, String password)
throws MalformedURLException, IOException {
String urlForJMX;
if (url != null)
urlForJMX = url;
else
urlForJMX = JMX_SERVICE_PREFIX + host + ":" + port
+ JMX_SERVICE_SUFFIX;
Map<String, String[]> environment = null;
if (username != null && password != null) {
String[] credentials = new String[2];
credentials[0] = username;
credentials[1] = password;
environment = new HashMap<String, String[]>();
environment.put(JMXConnector.CREDENTIALS, credentials);
}
return JMXConnectorFactory.connect(new JMXServiceURL(urlForJMX),
environment).getMBeanServerConnection();
}
// in java/org/apache/catalina/ant/jmx/JMXAccessorTask.java
protected MBeanServerConnection getJMXConnection()
throws MalformedURLException, IOException {
MBeanServerConnection jmxServerConnection = null;
if (isUseRef()) {
Object pref = null ;
if(getProject() != null) {
pref = getProject().getReference(getRef());
if (pref != null) {
try {
jmxServerConnection = (MBeanServerConnection) pref;
} catch (ClassCastException cce) {
getProject().log(
"Wrong object reference " + getRef() + " - "
+ pref.getClass());
return null;
}
}
}
if (jmxServerConnection == null) {
jmxServerConnection = accessJMXConnection(getProject(),
getUrl(), getHost(), getPort(), getUsername(),
getPassword(), getRef());
}
} else {
jmxServerConnection = accessJMXConnection(getProject(), getUrl(),
getHost(), getPort(), getUsername(), getPassword(), null);
}
return jmxServerConnection;
}
// in java/org/apache/catalina/ant/jmx/JMXAccessorEqualsCondition.java
protected MBeanServerConnection getJMXConnection()
throws MalformedURLException, IOException {
return JMXAccessorTask.accessJMXConnection(
getProject(),
getUrl(), getHost(),
getPort(), getUsername(), getPassword(), ref);
}
// in java/org/apache/catalina/ant/jmx/JMXAccessorCondition.java
protected MBeanServerConnection getJMXConnection()
throws MalformedURLException, IOException {
return JMXAccessorTask.accessJMXConnection(
getProject(),
getUrl(), getHost(),
getPort(), getUsername(), getPassword(), ref);
}
// in java/org/apache/catalina/websocket/WebSocketServlet.java
Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// Information required to send the server handshake message
String key;
String subProtocol = null;
List<String> extensions = Collections.emptyList();
if (!headerContainsToken(req, "upgrade", "websocket")) {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
if (!headerContainsToken(req, "connection", "upgrade")) {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
if (!headerContainsToken(req, "sec-websocket-version", "13")) {
resp.setStatus(426);
resp.setHeader("Sec-WebSocket-Version", "13");
return;
}
key = req.getHeader("Sec-WebSocket-Key");
if (key == null) {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
String origin = req.getHeader("Origin");
if (!verifyOrigin(origin)) {
resp.sendError(HttpServletResponse.SC_FORBIDDEN);
return;
}
List<String> subProtocols = getTokensFromHeader(req,
"Sec-WebSocket-Protocol-Client");
if (!subProtocols.isEmpty()) {
subProtocol = selectSubProtocol(subProtocols);
}
// TODO Read client handshake - Sec-WebSocket-Extensions
// TODO Extensions require the ability to specify something (API TBD)
// that can be passed to the Tomcat internals and process extension
// data present when the frame is fragmented.
// If we got this far, all is good. Accept the connection.
resp.setHeader("Upgrade", "websocket");
resp.setHeader("Connection", "upgrade");
resp.setHeader("Sec-WebSocket-Accept", getWebSocketAccept(key));
if (subProtocol != null) {
resp.setHeader("Sec-WebSocket-Protocol", subProtocol);
}
if (!extensions.isEmpty()) {
// TODO
}
// Small hack until the Servlet API provides a way to do this.
StreamInbound inbound = createWebSocketInbound(subProtocol);
((RequestFacade) req).doUpgrade(inbound);
}
// in java/org/apache/catalina/websocket/MessageInbound.java
Override
protected final void onBinaryData(InputStream is) throws IOException {
int read = 0;
while (read > -1) {
bb.position(bb.position() + read);
if (bb.remaining() == 0) {
resizeByteBuffer();
}
read = is.read(bb.array(), bb.position(), bb.remaining());
}
bb.flip();
onBinaryMessage(bb);
bb.clear();
}
// in java/org/apache/catalina/websocket/MessageInbound.java
Override
protected final void onTextData(Reader r) throws IOException {
int read = 0;
while (read > -1) {
cb.position(cb.position() + read);
if (cb.remaining() == 0) {
resizeCharBuffer();
}
read = r.read(cb.array(), cb.position(), cb.remaining());
}
cb.flip();
onTextMessage(cb);
cb.clear();
}
// in java/org/apache/catalina/websocket/MessageInbound.java
private void resizeByteBuffer() throws IOException {
int maxSize = getByteBufferMaxSize();
if (bb.limit() >= maxSize) {
throw new IOException(sm.getString("message.bufferTooSmall"));
}
long newSize = bb.limit() * 2;
if (newSize > maxSize) {
newSize = maxSize;
}
// Cast is safe. newSize < maxSize and maxSize is an int
ByteBuffer newBuffer = ByteBuffer.allocate((int) newSize);
bb.rewind();
newBuffer.put(bb);
bb = newBuffer;
}
// in java/org/apache/catalina/websocket/MessageInbound.java
private void resizeCharBuffer() throws IOException {
int maxSize = getCharBufferMaxSize();
if (cb.limit() >= maxSize) {
throw new IOException(sm.getString("message.bufferTooSmall"));
}
long newSize = cb.limit() * 2;
if (newSize > maxSize) {
newSize = maxSize;
}
// Cast is safe. newSize < maxSize and maxSize is an int
CharBuffer newBuffer = CharBuffer.allocate((int) newSize);
cb.rewind();
newBuffer.put(cb);
cb = newBuffer;
}
// in java/org/apache/catalina/websocket/StreamInbound.java
Override
public final SocketState onData() throws IOException {
// Must be start the start of a message (which may consist of multiple
// frames)
WsInputStream wsIs = new WsInputStream(processor, getWsOutbound());
try {
WsFrame frame = wsIs.nextFrame(true);
while (frame != null) {
// TODO User defined extensions may define values for rsv
if (frame.getRsv() > 0) {
closeOutboundConnection(
Constants.STATUS_PROTOCOL_ERROR, null);
return SocketState.CLOSED;
}
byte opCode = frame.getOpCode();
if (opCode == Constants.OPCODE_BINARY) {
onBinaryData(wsIs);
} else if (opCode == Constants.OPCODE_TEXT) {
InputStreamReader r =
new InputStreamReader(wsIs, new Utf8Decoder());
onTextData(r);
} else if (opCode == Constants.OPCODE_CLOSE){
closeOutboundConnection(frame);
return SocketState.CLOSED;
} else if (opCode == Constants.OPCODE_PING) {
getWsOutbound().pong(frame.getPayLoad());
} else if (opCode == Constants.OPCODE_PONG) {
// NO-OP
} else {
// Unknown OpCode
closeOutboundConnection(
Constants.STATUS_PROTOCOL_ERROR, null);
return SocketState.CLOSED;
}
frame = wsIs.nextFrame(false);
}
} catch (MalformedInputException mie) {
// Invalid UTF-8
closeOutboundConnection(Constants.STATUS_BAD_DATA, null);
return SocketState.CLOSED;
} catch (UnmappableCharacterException uce) {
// Invalid UTF-8
closeOutboundConnection(Constants.STATUS_BAD_DATA, null);
return SocketState.CLOSED;
} catch (IOException ioe) {
// Given something must have gone to reach this point, this
// might not work but try it anyway.
closeOutboundConnection(Constants.STATUS_PROTOCOL_ERROR, null);
return SocketState.CLOSED;
}
return SocketState.UPGRADED;
}
// in java/org/apache/catalina/websocket/StreamInbound.java
private void closeOutboundConnection(int status, ByteBuffer data) throws IOException {
try {
getWsOutbound().close(status, data);
} finally {
onClose(status);
}
}
// in java/org/apache/catalina/websocket/StreamInbound.java
private void closeOutboundConnection(WsFrame frame) throws IOException {
try {
getWsOutbound().close(frame);
} finally {
onClose(Constants.OPCODE_CLOSE);
}
}
// in java/org/apache/catalina/websocket/WsInputStream.java
public WsFrame nextFrame(boolean block) throws IOException {
frame = WsFrame.nextFrame(processor, block);
if (frame != null) {
readThisFragment = 0;
remaining = frame.getPayLoadLength();
}
return frame;
}
// in java/org/apache/catalina/websocket/WsInputStream.java
Override
public int read() throws IOException {
makePayloadDataAvailable();
if (remaining == 0) {
return -1;
}
remaining--;
readThisFragment++;
int masked = processor.read();
if(masked == -1) {
return -1;
}
return masked ^
(frame.getMask()[(int) ((readThisFragment - 1) % 4)] & 0xFF);
}
// in java/org/apache/catalina/websocket/WsInputStream.java
Override
public int read(byte b[], int off, int len) throws IOException {
makePayloadDataAvailable();
if (remaining == 0) {
return -1;
}
if (len > remaining) {
len = (int) remaining;
}
int result = processor.read(true, b, off, len);
if(result == -1) {
return -1;
}
for (int i = off; i < off + result; i++) {
b[i] = (byte) (b[i] ^
frame.getMask()[(int) ((readThisFragment + i - off) % 4)]);
}
remaining -= result;
readThisFragment += result;
return result;
}
// in java/org/apache/catalina/websocket/WsInputStream.java
private void makePayloadDataAvailable() throws IOException {
if (error != null) {
throw new IOException(error);
}
while (remaining == 0 && !frame.getFin()) {
// Need more data - process next frame
nextFrame(true);
while (frame.isControl()) {
if (frame.getOpCode() == Constants.OPCODE_PING) {
outbound.pong(frame.getPayLoad());
} else if (frame.getOpCode() == Constants.OPCODE_PONG) {
// NO-OP. Swallow it.
} else if (frame.getOpCode() == Constants.OPCODE_CLOSE) {
outbound.close(frame);
} else{
throw new IOException(sm.getString("is.unknownOpCode",
Byte.valueOf(frame.getOpCode())));
}
nextFrame(true);
}
if (frame.getOpCode() != Constants.OPCODE_CONTINUATION) {
error = sm.getString("is.notContinuation",
Byte.valueOf(frame.getOpCode()));
throw new IOException(error);
}
}
}
// in java/org/apache/catalina/websocket/WsFrame.java
private int blockingRead(UpgradeProcessor<?> processor)
throws IOException {
int result = processor.read();
if (result == -1) {
throw new IOException(sm.getString("frame.eos"));
}
return result;
}
// in java/org/apache/catalina/websocket/WsFrame.java
private void blockingRead(UpgradeProcessor<?> processor, byte[] bytes)
throws IOException {
int read = 0;
int last = 0;
while (read < bytes.length) {
last = processor.read(true, bytes, read, bytes.length - read);
if (last == -1) {
throw new IOException(sm.getString("frame.eos"));
}
read += last;
}
}
// in java/org/apache/catalina/websocket/WsFrame.java
private void blockingRead(UpgradeProcessor<?> processor, ByteBuffer bb)
throws IOException {
int last = 0;
while (bb.hasRemaining()) {
last = processor.read();
if (last == -1) {
throw new IOException(sm.getString("frame.eos"));
}
bb.put((byte) (last ^ mask[bb.position() % 4]));
}
bb.flip();
}
// in java/org/apache/catalina/websocket/WsFrame.java
public static WsFrame nextFrame(UpgradeProcessor<?> processor,
boolean block) throws IOException {
byte[] first = new byte[1];
int read = processor.read(block, first, 0, 1);
if (read == 1) {
return new WsFrame(first[0], processor);
} else if (read == 0) {
return null;
} else if (read == -1) {
throw new EOFException(sm.getString("frame.readEos"));
} else {
throw new IOException(
sm.getString("frame.readFailed", Integer.valueOf(read)));
}
}
// in java/org/apache/catalina/websocket/WsOutbound.java
public synchronized void writeBinaryData(int b) throws IOException {
if (closed) {
throw new IOException(sm.getString("outbound.closed"));
}
if (bb.position() == bb.capacity()) {
doFlush(false);
}
if (text == null) {
text = Boolean.FALSE;
} else if (text == Boolean.TRUE) {
// Flush the character data
flush();
text = Boolean.FALSE;
}
bb.put((byte) (b & 0xFF));
}
// in java/org/apache/catalina/websocket/WsOutbound.java
public synchronized void writeTextData(char c) throws IOException {
if (closed) {
throw new IOException(sm.getString("outbound.closed"));
}
if (cb.position() == cb.capacity()) {
doFlush(false);
}
if (text == null) {
text = Boolean.TRUE;
} else if (text == Boolean.FALSE) {
// Flush the binary data
flush();
text = Boolean.TRUE;
}
cb.append(c);
}
// in java/org/apache/catalina/websocket/WsOutbound.java
public synchronized void writeBinaryMessage(ByteBuffer msgBb)
throws IOException {
if (closed) {
throw new IOException(sm.getString("outbound.closed"));
}
if (text != null) {
// Empty the buffer
flush();
}
text = Boolean.FALSE;
doWriteBytes(msgBb, true);
}
// in java/org/apache/catalina/websocket/WsOutbound.java
public synchronized void writeTextMessage(CharBuffer msgCb)
throws IOException {
if (closed) {
throw new IOException(sm.getString("outbound.closed"));
}
if (text != null) {
// Empty the buffer
flush();
}
text = Boolean.TRUE;
doWriteText(msgCb, true);
}
// in java/org/apache/catalina/websocket/WsOutbound.java
public synchronized void flush() throws IOException {
if (closed) {
throw new IOException(sm.getString("outbound.closed"));
}
doFlush(true);
}
// in java/org/apache/catalina/websocket/WsOutbound.java
private void doFlush(boolean finalFragment) throws IOException {
if (text == null) {
// No data
return;
}
if (text.booleanValue()) {
cb.flip();
doWriteText(cb, finalFragment);
} else {
bb.flip();
doWriteBytes(bb, finalFragment);
}
}
// in java/org/apache/catalina/websocket/WsOutbound.java
protected void close(WsFrame frame) throws IOException {
if (frame.getPayLoadLength() > 0) {
// Must be status (2 bytes) plus optional message
if (frame.getPayLoadLength() == 1) {
throw new IOException();
}
int status = (frame.getPayLoad().get() & 0xFF) << 8;
status += frame.getPayLoad().get() & 0xFF;
if (validateCloseStatus(status)) {
// Echo the status back to the client
close(status, frame.getPayLoad());
} else {
// Invalid close code
close(Constants.STATUS_PROTOCOL_ERROR, null);
}
} else {
// No status
close(0, null);
}
}
// in java/org/apache/catalina/websocket/WsOutbound.java
public synchronized void close(int status, ByteBuffer data)
throws IOException {
if (closed) {
return;
}
closed = true;
upgradeOutbound.write(0x88);
if (status == 0) {
upgradeOutbound.write(0);
} else if (data == null || data.position() == data.limit()) {
upgradeOutbound.write(2);
upgradeOutbound.write(status >>> 8);
upgradeOutbound.write(status);
} else {
upgradeOutbound.write(2 + data.limit() - data.position());
upgradeOutbound.write(status >>> 8);
upgradeOutbound.write(status);
upgradeOutbound.write(data.array(), data.position(),
data.limit() - data.position());
}
upgradeOutbound.flush();
bb = null;
cb = null;
upgradeOutbound = null;
}
// in java/org/apache/catalina/websocket/WsOutbound.java
public synchronized void pong(ByteBuffer data) throws IOException {
if (closed) {
throw new IOException(sm.getString("outbound.closed"));
}
doFlush(true);
upgradeOutbound.write(0x8A);
if (data == null) {
upgradeOutbound.write(0);
} else {
upgradeOutbound.write(data.limit() - data.position());
upgradeOutbound.write(data.array(), data.position(),
data.limit() - data.position());
}
upgradeOutbound.flush();
}
// in java/org/apache/catalina/websocket/WsOutbound.java
private void doWriteBytes(ByteBuffer buffer, boolean finalFragment)
throws IOException {
// Work out the first byte
int first = 0x00;
if (finalFragment) {
first = first + 0x80;
}
if (firstFrame) {
if (text.booleanValue()) {
first = first + 0x1;
} else {
first = first + 0x2;
}
}
// Continuation frame is OpCode 0
upgradeOutbound.write(first);
if (buffer.limit() < 126) {
upgradeOutbound.write(buffer.limit());
} else if (buffer.limit() < 65536) {
upgradeOutbound.write(126);
upgradeOutbound.write(buffer.limit() >>> 8);
upgradeOutbound.write(buffer.limit() & 0xFF);
} else {
// Will never be more than 2^31-1
upgradeOutbound.write(127);
upgradeOutbound.write(0);
upgradeOutbound.write(0);
upgradeOutbound.write(0);
upgradeOutbound.write(0);
upgradeOutbound.write(buffer.limit() >>> 24);
upgradeOutbound.write(buffer.limit() >>> 16);
upgradeOutbound.write(buffer.limit() >>> 8);
upgradeOutbound.write(buffer.limit() & 0xFF);
}
// Write the content
upgradeOutbound.write(buffer.array(), 0, buffer.limit());
upgradeOutbound.flush();
// Reset
if (finalFragment) {
text = null;
firstFrame = true;
} else {
firstFrame = false;
}
bb.clear();
}
// in java/org/apache/catalina/websocket/WsOutbound.java
private void doWriteText(CharBuffer buffer, boolean finalFragment)
throws IOException {
CharsetEncoder encoder = B2CConverter.UTF_8.newEncoder();
do {
CoderResult cr = encoder.encode(buffer, bb, true);
if (cr.isError()) {
cr.throwException();
}
bb.flip();
if (buffer.hasRemaining()) {
doWriteBytes(bb, false);
} else {
doWriteBytes(bb, finalFragment);
}
} while (buffer.hasRemaining());
// Reset - bb will be cleared in doWriteBytes()
cb.clear();
}
// in java/org/apache/catalina/manager/HTMLManagerServlet.java
Override
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
StringManager smClient = getStringManager(request);
// Identify the request parameters that we need
// By obtaining the command from the pathInfo, per-command security can
// be configured in web.xml
String command = request.getPathInfo();
String path = request.getParameter("path");
ContextName cn = null;
if (path != null) {
cn = new ContextName(path, request.getParameter("version"));
}
// Prepare our output writer to generate the response message
response.setContentType("text/html; charset=" + Constants.CHARSET);
String message = "";
// Process the requested command
if (command == null || command.equals("/")) {
// No command == list
} else if (command.equals("/list")) {
// List always displayed - nothing to do here
} else if (command.equals("/sessions")) {
try {
doSessions(cn, request, response, smClient);
return;
} catch (Exception e) {
log("HTMLManagerServlet.sessions[" + cn + "]", e);
message = smClient.getString("managerServlet.exception",
e.toString());
}
} else if (command.equals("/upload") || command.equals("/deploy") ||
command.equals("/reload") || command.equals("/undeploy") ||
command.equals("/expire") || command.equals("/start") ||
command.equals("/stop")) {
message =
smClient.getString("managerServlet.postCommand", command);
} else {
message =
smClient.getString("managerServlet.unknownCommand", command);
}
list(request, response, message, smClient);
}
// in java/org/apache/catalina/manager/HTMLManagerServlet.java
Override
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
StringManager smClient = getStringManager(request);
// Identify the request parameters that we need
// By obtaining the command from the pathInfo, per-command security can
// be configured in web.xml
String command = request.getPathInfo();
String path = request.getParameter("path");
ContextName cn = null;
if (path != null) {
cn = new ContextName(path, request.getParameter("version"));
}
String deployPath = request.getParameter("deployPath");
ContextName deployCn = null;
if (deployPath != null) {
deployCn = new ContextName(deployPath,
request.getParameter("deployVersion"));
}
String deployConfig = request.getParameter("deployConfig");
String deployWar = request.getParameter("deployWar");
// Prepare our output writer to generate the response message
response.setContentType("text/html; charset=" + Constants.CHARSET);
String message = "";
if (command == null || command.length() == 0) {
// No command == list
// List always displayed -> do nothing
} else if (command.equals("/upload")) {
message = upload(request, smClient);
} else if (command.equals("/deploy")) {
message = deployInternal(deployConfig, deployCn, deployWar,
smClient);
} else if (command.equals("/reload")) {
message = reload(cn, smClient);
} else if (command.equals("/undeploy")) {
message = undeploy(cn, smClient);
} else if (command.equals("/expire")) {
message = expireSessions(cn, request, smClient);
} else if (command.equals("/start")) {
message = start(cn, smClient);
} else if (command.equals("/stop")) {
message = stop(cn, smClient);
} else if (command.equals("/findleaks")) {
message = findleaks(smClient);
} else {
// Try GET
doGet(request,response);
return;
}
list(request, response, message, smClient);
}
// in java/org/apache/catalina/manager/HTMLManagerServlet.java
protected String upload(HttpServletRequest request, StringManager smClient)
throws IOException, ServletException {
String message = "";
Part warPart = null;
String filename = null;
Collection<Part> parts = request.getParts();
Iterator<Part> iter = parts.iterator();
try {
while (iter.hasNext()) {
Part part = iter.next();
if (part.getName().equals("deployWar") && warPart == null) {
warPart = part;
} else {
part.delete();
}
}
while (true) {
if (warPart == null) {
message = smClient.getString(
"htmlManagerServlet.deployUploadNoFile");
break;
}
filename =
extractFilename(warPart.getHeader("Content-Disposition"));
if (!filename.toLowerCase(Locale.ENGLISH).endsWith(".war")) {
message = smClient.getString(
"htmlManagerServlet.deployUploadNotWar", filename);
break;
}
// Get the filename if uploaded name includes a path
if (filename.lastIndexOf('\\') >= 0) {
filename =
filename.substring(filename.lastIndexOf('\\') + 1);
}
if (filename.lastIndexOf('/') >= 0) {
filename =
filename.substring(filename.lastIndexOf('/') + 1);
}
// Identify the appBase of the owning Host of this Context
// (if any)
File file = new File(host.getAppBaseFile(), filename);
if (file.exists()) {
message = smClient.getString(
"htmlManagerServlet.deployUploadWarExists",
filename);
break;
}
ContextName cn = new ContextName(filename);
String name = cn.getName();
if ((host.findChild(name) != null) && !isDeployed(name)) {
message = smClient.getString(
"htmlManagerServlet.deployUploadInServerXml",
filename);
break;
}
if (!isServiced(name)) {
addServiced(name);
try {
warPart.write(file.getAbsolutePath());
// Perform new deployment
check(name);
} finally {
removeServiced(name);
}
}
break;
}
} catch(Exception e) {
message = smClient.getString
("htmlManagerServlet.deployUploadFail", e.getMessage());
log(message, e);
} finally {
if (warPart != null) {
warPart.delete();
}
warPart = null;
}
return message;
}
// in java/org/apache/catalina/manager/HTMLManagerServlet.java
protected void list(HttpServletRequest request,
HttpServletResponse response,
String message,
StringManager smClient) throws IOException {
if (debug >= 1)
log("list: Listing contexts for virtual host '" +
host.getName() + "'");
PrintWriter writer = response.getWriter();
// HTML Header Section
writer.print(Constants.HTML_HEADER_SECTION);
// Body Header Section
Object[] args = new Object[2];
args[0] = request.getContextPath();
args[1] = smClient.getString("htmlManagerServlet.title");
writer.print(MessageFormat.format
(Constants.BODY_HEADER_SECTION, args));
// Message Section
args = new Object[3];
args[0] = smClient.getString("htmlManagerServlet.messageLabel");
if (message == null || message.length() == 0) {
args[1] = "OK";
} else {
args[1] = RequestUtil.filter(message);
}
writer.print(MessageFormat.format(Constants.MESSAGE_SECTION, args));
// Manager Section
args = new Object[9];
args[0] = smClient.getString("htmlManagerServlet.manager");
args[1] = response.encodeURL(request.getContextPath() + "/html/list");
args[2] = smClient.getString("htmlManagerServlet.list");
args[3] = response.encodeURL
(request.getContextPath() + "/" +
smClient.getString("htmlManagerServlet.helpHtmlManagerFile"));
args[4] = smClient.getString("htmlManagerServlet.helpHtmlManager");
args[5] = response.encodeURL
(request.getContextPath() + "/" +
smClient.getString("htmlManagerServlet.helpManagerFile"));
args[6] = smClient.getString("htmlManagerServlet.helpManager");
args[7] = response.encodeURL
(request.getContextPath() + "/status");
args[8] = smClient.getString("statusServlet.title");
writer.print(MessageFormat.format(Constants.MANAGER_SECTION, args));
// Apps Header Section
args = new Object[7];
args[0] = smClient.getString("htmlManagerServlet.appsTitle");
args[1] = smClient.getString("htmlManagerServlet.appsPath");
args[2] = smClient.getString("htmlManagerServlet.appsVersion");
args[3] = smClient.getString("htmlManagerServlet.appsName");
args[4] = smClient.getString("htmlManagerServlet.appsAvailable");
args[5] = smClient.getString("htmlManagerServlet.appsSessions");
args[6] = smClient.getString("htmlManagerServlet.appsTasks");
writer.print(MessageFormat.format(APPS_HEADER_SECTION, args));
// Apps Row Section
// Create sorted map of deployed applications by context name.
Container children[] = host.findChildren();
String contextNames[] = new String[children.length];
for (int i = 0; i < children.length; i++)
contextNames[i] = children[i].getName();
Arrays.sort(contextNames);
String appsStart = smClient.getString("htmlManagerServlet.appsStart");
String appsStop = smClient.getString("htmlManagerServlet.appsStop");
String appsReload = smClient.getString("htmlManagerServlet.appsReload");
String appsUndeploy =
smClient.getString("htmlManagerServlet.appsUndeploy");
String appsExpire = smClient.getString("htmlManagerServlet.appsExpire");
String noVersion = "<i>" +
smClient.getString("htmlManagerServlet.noVersion") + "</i>";
boolean isHighlighted = true;
boolean isDeployed = true;
String highlightColor = null;
for (String contextName : contextNames) {
Context ctxt = (Context) host.findChild(contextName);
if (ctxt != null) {
// Bugzilla 34818, alternating row colors
isHighlighted = !isHighlighted;
if(isHighlighted) {
highlightColor = "#C3F3C3";
} else {
highlightColor = "#FFFFFF";
}
String contextPath = ctxt.getPath();
String displayPath = contextPath;
if (displayPath.equals("")) {
displayPath = "/";
}
StringBuilder tmp = new StringBuilder();
tmp.append("path=");
tmp.append(URL_ENCODER.encode(displayPath));
if (ctxt.getWebappVersion().length() > 0) {
tmp.append("&version=");
tmp.append(URL_ENCODER.encode(ctxt.getWebappVersion()));
}
String pathVersion = tmp.toString();
try {
isDeployed = isDeployed(contextName);
} catch (Exception e) {
// Assume false on failure for safety
isDeployed = false;
}
args = new Object[7];
args[0] = "<a href=\"" + URL_ENCODER.encode(displayPath)
+ "\">" + RequestUtil.filter(displayPath) + "</a>";
if ("".equals(ctxt.getWebappVersion())) {
args[1] = noVersion;
} else {
args[1] = RequestUtil.filter(ctxt.getWebappVersion());
}
if (ctxt.getDisplayName() == null) {
args[2] = " ";
} else {
args[2] = RequestUtil.filter(ctxt.getDisplayName());
}
args[3] = Boolean.valueOf(ctxt.getAvailable());
args[4] = RequestUtil.filter(response.encodeURL(request.getContextPath() +
"/html/sessions?" + pathVersion));
Manager manager = ctxt.getManager();
if (manager instanceof DistributedManager && showProxySessions) {
args[5] = Integer.valueOf(
((DistributedManager)manager).getActiveSessionsFull());
} else if (ctxt.getManager() != null){
args[5] = Integer.valueOf(manager.getActiveSessions());
} else {
args[5] = Integer.valueOf(0);
}
args[6] = highlightColor;
writer.print
(MessageFormat.format(APPS_ROW_DETAILS_SECTION, args));
args = new Object[14];
args[0] = RequestUtil.filter(response.encodeURL(request
.getContextPath() + "/html/start?" + pathVersion));
args[1] = appsStart;
args[2] = RequestUtil.filter(response.encodeURL(request
.getContextPath() + "/html/stop?" + pathVersion));
args[3] = appsStop;
args[4] = RequestUtil.filter(response.encodeURL(request
.getContextPath() + "/html/reload?" + pathVersion));
args[5] = appsReload;
args[6] = RequestUtil.filter(response.encodeURL(request
.getContextPath() + "/html/undeploy?" + pathVersion));
args[7] = appsUndeploy;
args[8] = RequestUtil.filter(response.encodeURL(request
.getContextPath() + "/html/expire?" + pathVersion));
args[9] = appsExpire;
args[10] = smClient.getString(
"htmlManagerServlet.expire.explain");
if (manager == null) {
args[11] = smClient.getString(
"htmlManagerServlet.noManager");
} else {
args[11] = Integer.valueOf(
ctxt.getManager().getMaxInactiveInterval()/60);
}
args[12] = smClient.getString("htmlManagerServlet.expire.unit");
args[13] = highlightColor;
if (ctxt.getName().equals(this.context.getName())) {
writer.print(MessageFormat.format(
MANAGER_APP_ROW_BUTTON_SECTION, args));
} else if (ctxt.getAvailable() && isDeployed) {
writer.print(MessageFormat.format(
STARTED_DEPLOYED_APPS_ROW_BUTTON_SECTION, args));
} else if (ctxt.getAvailable() && !isDeployed) {
writer.print(MessageFormat.format(
STARTED_NONDEPLOYED_APPS_ROW_BUTTON_SECTION, args));
} else if (!ctxt.getAvailable() && isDeployed) {
writer.print(MessageFormat.format(
STOPPED_DEPLOYED_APPS_ROW_BUTTON_SECTION, args));
} else {
writer.print(MessageFormat.format(
STOPPED_NONDEPLOYED_APPS_ROW_BUTTON_SECTION, args));
}
}
}
// Deploy Section
args = new Object[7];
args[0] = smClient.getString("htmlManagerServlet.deployTitle");
args[1] = smClient.getString("htmlManagerServlet.deployServer");
args[2] = response.encodeURL(request.getContextPath() + "/html/deploy");
args[3] = smClient.getString("htmlManagerServlet.deployPath");
args[4] = smClient.getString("htmlManagerServlet.deployConfig");
args[5] = smClient.getString("htmlManagerServlet.deployWar");
args[6] = smClient.getString("htmlManagerServlet.deployButton");
writer.print(MessageFormat.format(DEPLOY_SECTION, args));
args = new Object[4];
args[0] = smClient.getString("htmlManagerServlet.deployUpload");
args[1] = response.encodeURL(request.getContextPath() + "/html/upload");
args[2] = smClient.getString("htmlManagerServlet.deployUploadFile");
args[3] = smClient.getString("htmlManagerServlet.deployButton");
writer.print(MessageFormat.format(UPLOAD_SECTION, args));
// Diagnostics section
args = new Object[5];
args[0] = smClient.getString("htmlManagerServlet.diagnosticsTitle");
args[1] = smClient.getString("htmlManagerServlet.diagnosticsLeak");
args[2] = response.encodeURL(
request.getContextPath() + "/html/findleaks");
args[3] = smClient.getString("htmlManagerServlet.diagnosticsLeakWarning");
args[4] = smClient.getString("htmlManagerServlet.diagnosticsLeakButton");
writer.print(MessageFormat.format(DIAGNOSTICS_SECTION, args));
// Server Header Section
args = new Object[9];
args[0] = smClient.getString("htmlManagerServlet.serverTitle");
args[1] = smClient.getString("htmlManagerServlet.serverVersion");
args[2] = smClient.getString("htmlManagerServlet.serverJVMVersion");
args[3] = smClient.getString("htmlManagerServlet.serverJVMVendor");
args[4] = smClient.getString("htmlManagerServlet.serverOSName");
args[5] = smClient.getString("htmlManagerServlet.serverOSVersion");
args[6] = smClient.getString("htmlManagerServlet.serverOSArch");
args[7] = sm.getString("htmlManagerServlet.serverHostname");
args[8] = sm.getString("htmlManagerServlet.serverIPAddress");
writer.print(MessageFormat.format
(Constants.SERVER_HEADER_SECTION, args));
// Server Row Section
args = new Object[8];
args[0] = ServerInfo.getServerInfo();
args[1] = System.getProperty("java.runtime.version");
args[2] = System.getProperty("java.vm.vendor");
args[3] = System.getProperty("os.name");
args[4] = System.getProperty("os.version");
args[5] = System.getProperty("os.arch");
try {
InetAddress address = InetAddress.getLocalHost();
args[6] = address.getHostName();
args[7] = address.getHostAddress();
} catch (UnknownHostException e) {
args[6] = "-";
args[7] = "-";
}
writer.print(MessageFormat.format(Constants.SERVER_ROW_SECTION, args));
// HTML Tail Section
writer.print(Constants.HTML_TAIL_SECTION);
// Finish up the response
writer.flush();
writer.close();
}
// in java/org/apache/catalina/manager/HTMLManagerServlet.java
protected void doSessions(ContextName cn, HttpServletRequest req,
HttpServletResponse resp, StringManager smClient)
throws ServletException, IOException {
req.setAttribute("path", cn.getPath());
req.setAttribute("version", cn.getVersion());
String action = req.getParameter("action");
if (debug >= 1) {
log("sessions: Session action '" + action +
"' for web application '" + cn.getDisplayName() + "'");
}
if ("sessionDetail".equals(action)) {
String sessionId = req.getParameter("sessionId");
displaySessionDetailPage(req, resp, cn, sessionId, smClient);
return;
} else if ("invalidateSessions".equals(action)) {
String[] sessionIds = req.getParameterValues("sessionIds");
int i = invalidateSessions(cn, sessionIds, smClient);
req.setAttribute(APPLICATION_MESSAGE, "" + i + " sessions invalidated.");
} else if ("removeSessionAttribute".equals(action)) {
String sessionId = req.getParameter("sessionId");
String name = req.getParameter("attributeName");
boolean removed =
removeSessionAttribute(cn, sessionId, name, smClient);
String outMessage = removed ? "Session attribute '" + name + "' removed." : "Session did not contain any attribute named '" + name + "'";
req.setAttribute(APPLICATION_MESSAGE, outMessage);
displaySessionDetailPage(req, resp, cn, sessionId, smClient);
return;
} // else
displaySessionsListPage(cn, req, resp, smClient);
}
// in java/org/apache/catalina/manager/HTMLManagerServlet.java
protected void displaySessionsListPage(ContextName cn,
HttpServletRequest req, HttpServletResponse resp,
StringManager smClient)
throws ServletException, IOException {
List<Session> sessions = getSessionsForName(cn, smClient);
String sortBy = req.getParameter("sort");
String orderBy = null;
if (null != sortBy && !"".equals(sortBy.trim())) {
Comparator<Session> comparator = getComparator(sortBy);
if (comparator != null) {
orderBy = req.getParameter("order");
if ("DESC".equalsIgnoreCase(orderBy)) {
comparator = new ReverseComparator(comparator);
orderBy = "ASC";
} else {
orderBy = "DESC";
}
try {
Collections.sort(sessions, comparator);
} catch (IllegalStateException ise) {
// at least 1 of the sessions is invalidated
req.setAttribute(APPLICATION_ERROR, "Can't sort session list: one session is invalidated");
}
} else {
log("WARNING: unknown sort order: " + sortBy);
}
}
// keep sort order
req.setAttribute("sort", sortBy);
req.setAttribute("order", orderBy);
req.setAttribute("activeSessions", sessions);
//strong>NOTE</strong> - This header will be overridden
// automatically if a <code>RequestDispatcher.forward()</code> call is
// ultimately invoked.
resp.setHeader("Pragma", "No-cache"); // HTTP 1.0
resp.setHeader("Cache-Control", "no-cache,no-store,max-age=0"); // HTTP 1.1
resp.setDateHeader("Expires", 0); // 0 means now
getServletContext().getRequestDispatcher(sessionsListJspPath).include(req, resp);
}
// in java/org/apache/catalina/manager/HTMLManagerServlet.java
protected void displaySessionDetailPage(HttpServletRequest req,
HttpServletResponse resp, ContextName cn, String sessionId,
StringManager smClient) throws ServletException, IOException {
Session session = getSessionForNameAndId(cn, sessionId, smClient);
//strong>NOTE</strong> - This header will be overridden
// automatically if a <code>RequestDispatcher.forward()</code> call is
// ultimately invoked.
resp.setHeader("Pragma", "No-cache"); // HTTP 1.0
resp.setHeader("Cache-Control", "no-cache,no-store,max-age=0"); // HTTP 1.1
resp.setDateHeader("Expires", 0); // 0 means now
req.setAttribute("currentSession", session);
getServletContext().getRequestDispatcher(resp.encodeURL(sessionDetailJspPath)).include(req, resp);
}
// in java/org/apache/catalina/manager/HTMLManagerServlet.java
protected int invalidateSessions(ContextName cn, String[] sessionIds,
StringManager smClient) throws IOException {
if (null == sessionIds) {
return 0;
}
int nbAffectedSessions = 0;
for (int i = 0; i < sessionIds.length; ++i) {
String sessionId = sessionIds[i];
HttpSession session =
getSessionForNameAndId(cn, sessionId, smClient).getSession();
if (null == session) {
// Shouldn't happen, but let's play nice...
if (debug >= 1) {
log("WARNING: can't invalidate null session " + sessionId);
}
continue;
}
try {
session.invalidate();
++nbAffectedSessions;
if (debug >= 1) {
log("Invalidating session id " + sessionId);
}
} catch (IllegalStateException ise) {
if (debug >= 1) {
log("Can't invalidate already invalidated session id " + sessionId);
}
}
}
return nbAffectedSessions;
}
// in java/org/apache/catalina/manager/HTMLManagerServlet.java
protected boolean removeSessionAttribute(ContextName cn, String sessionId,
String attributeName, StringManager smClient) throws IOException {
HttpSession session =
getSessionForNameAndId(cn, sessionId, smClient).getSession();
if (null == session) {
// Shouldn't happen, but let's play nice...
if (debug >= 1) {
log("WARNING: can't remove attribute '" + attributeName + "' for null session " + sessionId);
}
return false;
}
boolean wasPresent = (null != session.getAttribute(attributeName));
try {
session.removeAttribute(attributeName);
} catch (IllegalStateException ise) {
if (debug >= 1) {
log("Can't remote attribute '" + attributeName + "' for invalidated session id " + sessionId);
}
}
return wasPresent;
}
// in java/org/apache/catalina/manager/JMXProxyServlet.java
Override
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException
{
response.setContentType("text/plain");
PrintWriter writer = response.getWriter();
if( mBeanServer==null ) {
writer.println("Error - No mbean server");
return;
}
String qry=request.getParameter("set");
if( qry!= null ) {
String name=request.getParameter("att");
String val=request.getParameter("val");
setAttribute( writer, qry, name, val );
return;
}
qry=request.getParameter("get");
if( qry!= null ) {
String name=request.getParameter("att");
getAttribute( writer, qry, name, request.getParameter("key") );
return;
}
qry = request.getParameter("invoke");
if(qry != null) {
String opName=request.getParameter("op");
String ps = request.getParameter("ps");
String[] valuesStr;
if (ps == null) {
valuesStr = new String[0];
} else {
valuesStr = ps.split(",");
}
invokeOperation( writer, qry, opName,valuesStr );
return;
}
qry=request.getParameter("qry");
if( qry == null ) {
qry = "*:*";
}
listBeans( writer, qry );
}
// in java/org/apache/catalina/manager/host/HostManagerServlet.java
Override
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
StringManager smClient = getStringManager(request);
// Identify the request parameters that we need
String command = request.getPathInfo();
if (command == null)
command = request.getServletPath();
String name = request.getParameter("name");
// Prepare our output writer to generate the response message
response.setContentType("text/plain; charset=" + Constants.CHARSET);
PrintWriter writer = response.getWriter();
// Process the requested command
if (command == null) {
writer.println(sm.getString("hostManagerServlet.noCommand"));
} else if (command.equals("/add")) {
add(request, writer, name, false, smClient);
} else if (command.equals("/remove")) {
remove(writer, name, smClient);
} else if (command.equals("/list")) {
list(writer, smClient);
} else if (command.equals("/start")) {
start(writer, name, smClient);
} else if (command.equals("/stop")) {
stop(writer, name, smClient);
} else {
writer.println(sm.getString("hostManagerServlet.unknownCommand",
command));
}
// Finish up the response
writer.flush();
writer.close();
}
// in java/org/apache/catalina/manager/host/HTMLHostManagerServlet.java
Override
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
StringManager smClient = getStringManager(request);
// Identify the request parameters that we need
String command = request.getPathInfo();
// Prepare our output writer to generate the response message
response.setContentType("text/html; charset=" + Constants.CHARSET);
String message = "";
// Process the requested command
if (command == null) {
// No command == list
} else if (command.equals("/list")) {
// Nothing to do - always generate list
} else if (command.equals("/add") || command.equals("/remove") ||
command.equals("/start") || command.equals("/stop")) {
message = smClient.getString(
"hostManagerServlet.postCommand", command);
} else {
message = smClient.getString(
"hostManagerServlet.unknownCommand", command);
}
list(request, response, message, smClient);
}
// in java/org/apache/catalina/manager/host/HTMLHostManagerServlet.java
Override
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
StringManager smClient = getStringManager(request);
// Identify the request parameters that we need
String command = request.getPathInfo();
String name = request.getParameter("name");
// Prepare our output writer to generate the response message
response.setContentType("text/html; charset=" + Constants.CHARSET);
String message = "";
// Process the requested command
if (command == null) {
// No command == list
} else if (command.equals("/add")) {
message = add(request, name, smClient);
} else if (command.equals("/remove")) {
message = remove(name, smClient);
} else if (command.equals("/start")) {
message = start(name, smClient);
} else if (command.equals("/stop")) {
message = stop(name, smClient);
} else {
//Try GET
doGet(request, response);
}
list(request, response, message, smClient);
}
// in java/org/apache/catalina/manager/host/HTMLHostManagerServlet.java
public void list(HttpServletRequest request,
HttpServletResponse response,
String message,
StringManager smClient) throws IOException {
if (debug >= 1) {
log(sm.getString("hostManagerServlet.list", engine.getName()));
}
PrintWriter writer = response.getWriter();
// HTML Header Section
writer.print(org.apache.catalina.manager.Constants.HTML_HEADER_SECTION);
// Body Header Section
Object[] args = new Object[2];
args[0] = request.getContextPath();
args[1] = smClient.getString("htmlHostManagerServlet.title");
writer.print(MessageFormat.format
(Constants.BODY_HEADER_SECTION, args));
// Message Section
args = new Object[3];
args[0] = smClient.getString("htmlHostManagerServlet.messageLabel");
if (message == null || message.length() == 0) {
args[1] = "OK";
} else {
args[1] = RequestUtil.filter(message);
}
writer.print(MessageFormat.format(Constants.MESSAGE_SECTION, args));
// Manager Section
args = new Object[9];
args[0] = smClient.getString("htmlHostManagerServlet.manager");
args[1] = response.encodeURL(request.getContextPath() + "/html/list");
args[2] = smClient.getString("htmlHostManagerServlet.list");
args[3] = response.encodeURL
(request.getContextPath() + "/" +
smClient.getString("htmlHostManagerServlet.helpHtmlManagerFile"));
args[4] = smClient.getString("htmlHostManagerServlet.helpHtmlManager");
args[5] = response.encodeURL
(request.getContextPath() + "/" +
smClient.getString("htmlHostManagerServlet.helpManagerFile"));
args[6] = smClient.getString("htmlHostManagerServlet.helpManager");
args[7] = response.encodeURL("/manager/status");
args[8] = smClient.getString("statusServlet.title");
writer.print(MessageFormat.format(Constants.MANAGER_SECTION, args));
// Hosts Header Section
args = new Object[3];
args[0] = smClient.getString("htmlHostManagerServlet.hostName");
args[1] = smClient.getString("htmlHostManagerServlet.hostAliases");
args[2] = smClient.getString("htmlHostManagerServlet.hostTasks");
writer.print(MessageFormat.format(HOSTS_HEADER_SECTION, args));
// Hosts Row Section
// Create sorted map of host names.
Container[] children = engine.findChildren();
String hostNames[] = new String[children.length];
for (int i = 0; i < children.length; i++)
hostNames[i] = children[i].getName();
TreeMap<String,String> sortedHostNamesMap =
new TreeMap<String,String>();
for (int i = 0; i < hostNames.length; i++) {
String displayPath = hostNames[i];
sortedHostNamesMap.put(displayPath, hostNames[i]);
}
String hostsStart =
smClient.getString("htmlHostManagerServlet.hostsStart");
String hostsStop =
smClient.getString("htmlHostManagerServlet.hostsStop");
String hostsRemove =
smClient.getString("htmlHostManagerServlet.hostsRemove");
Iterator<Map.Entry<String,String>> iterator =
sortedHostNamesMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String,String> entry = iterator.next();
String hostName = entry.getKey();
Host host = (Host) engine.findChild(hostName);
if (host != null ) {
args = new Object[2];
args[0] = RequestUtil.filter(hostName);
String[] aliases = host.findAliases();
StringBuilder buf = new StringBuilder();
if (aliases.length > 0) {
buf.append(aliases[0]);
for (int j = 1; j < aliases.length; j++) {
buf.append(", ").append(aliases[j]);
}
}
if (buf.length() == 0) {
buf.append(" ");
args[1] = buf.toString();
} else {
args[1] = RequestUtil.filter(buf.toString());
}
writer.print
(MessageFormat.format(HOSTS_ROW_DETAILS_SECTION, args));
args = new Object[4];
if (host.getState().isAvailable()) {
args[0] = response.encodeURL
(request.getContextPath() +
"/html/stop?name=" +
URLEncoder.encode(hostName, "UTF-8"));
args[1] = hostsStop;
} else {
args[0] = response.encodeURL
(request.getContextPath() +
"/html/start?name=" +
URLEncoder.encode(hostName, "UTF-8"));
args[1] = hostsStart;
}
args[2] = response.encodeURL
(request.getContextPath() +
"/html/remove?name=" +
URLEncoder.encode(hostName, "UTF-8"));
args[3] = hostsRemove;
if (host == this.installedHost) {
writer.print(MessageFormat.format(
MANAGER_HOST_ROW_BUTTON_SECTION, args));
} else {
writer.print(MessageFormat.format(
HOSTS_ROW_BUTTON_SECTION, args));
}
}
}
// Add Section
args = new Object[6];
args[0] = smClient.getString("htmlHostManagerServlet.addTitle");
args[1] = smClient.getString("htmlHostManagerServlet.addHost");
args[2] = response.encodeURL(request.getContextPath() + "/html/add");
args[3] = smClient.getString("htmlHostManagerServlet.addName");
args[4] = smClient.getString("htmlHostManagerServlet.addAliases");
args[5] = smClient.getString("htmlHostManagerServlet.addAppBase");
writer.print(MessageFormat.format(ADD_SECTION_START, args));
args = new Object[3];
args[0] = smClient.getString("htmlHostManagerServlet.addAutoDeploy");
args[1] = "autoDeploy";
args[2] = "checked";
writer.print(MessageFormat.format(ADD_SECTION_BOOLEAN, args));
args[0] = smClient.getString(
"htmlHostManagerServlet.addDeployOnStartup");
args[1] = "deployOnStartup";
args[2] = "checked";
writer.print(MessageFormat.format(ADD_SECTION_BOOLEAN, args));
args[0] = smClient.getString("htmlHostManagerServlet.addDeployXML");
args[1] = "deployXML";
args[2] = "checked";
writer.print(MessageFormat.format(ADD_SECTION_BOOLEAN, args));
args[0] = smClient.getString("htmlHostManagerServlet.addUnpackWARs");
args[1] = "unpackWARs";
args[2] = "checked";
writer.print(MessageFormat.format(ADD_SECTION_BOOLEAN, args));
args[0] = smClient.getString("htmlHostManagerServlet.addManager");
args[1] = "manager";
args[2] = "checked";
writer.print(MessageFormat.format(ADD_SECTION_BOOLEAN, args));
args = new Object[1];
args[0] = smClient.getString("htmlHostManagerServlet.addButton");
writer.print(MessageFormat.format(ADD_SECTION_END, args));
// Server Header Section
args = new Object[7];
args[0] = smClient.getString("htmlHostManagerServlet.serverTitle");
args[1] = smClient.getString("htmlHostManagerServlet.serverVersion");
args[2] = smClient.getString("htmlHostManagerServlet.serverJVMVersion");
args[3] = smClient.getString("htmlHostManagerServlet.serverJVMVendor");
args[4] = smClient.getString("htmlHostManagerServlet.serverOSName");
args[5] = smClient.getString("htmlHostManagerServlet.serverOSVersion");
args[6] = smClient.getString("htmlHostManagerServlet.serverOSArch");
writer.print(MessageFormat.format
(Constants.SERVER_HEADER_SECTION, args));
// Server Row Section
args = new Object[6];
args[0] = ServerInfo.getServerInfo();
args[1] = System.getProperty("java.runtime.version");
args[2] = System.getProperty("java.vm.vendor");
args[3] = System.getProperty("os.name");
args[4] = System.getProperty("os.version");
args[5] = System.getProperty("os.arch");
writer.print(MessageFormat.format(Constants.SERVER_ROW_SECTION, args));
// HTML Tail Section
writer.print(Constants.HTML_TAIL_SECTION);
// Finish up the response
writer.flush();
writer.close();
}
// in java/org/apache/catalina/manager/StatusManagerServlet.java
Override
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
// mode is flag for HTML or XML output
int mode = 0;
// if ?XML=true, set the mode to XML
if (request.getParameter("XML") != null
&& request.getParameter("XML").equals("true")) {
mode = 1;
}
StatusTransformer.setContentType(response, mode);
PrintWriter writer = response.getWriter();
boolean completeStatus = false;
if ((request.getPathInfo() != null)
&& (request.getPathInfo().equals("/all"))) {
completeStatus = true;
}
// use StatusTransformer to output status
Object[] args = new Object[1];
args[0] = request.getContextPath();
StatusTransformer.writeHeader(writer,args,mode);
// Body Header Section
args = new Object[2];
args[0] = request.getContextPath();
if (completeStatus) {
args[1] = sm.getString("statusServlet.complete");
} else {
args[1] = sm.getString("statusServlet.title");
}
// use StatusTransformer to output status
StatusTransformer.writeBody(writer,args,mode);
// Manager Section
args = new Object[9];
args[0] = sm.getString("htmlManagerServlet.manager");
args[1] = response.encodeURL(request.getContextPath() + "/html/list");
args[2] = sm.getString("htmlManagerServlet.list");
args[3] = response.encodeURL
(request.getContextPath() + "/" +
sm.getString("htmlManagerServlet.helpHtmlManagerFile"));
args[4] = sm.getString("htmlManagerServlet.helpHtmlManager");
args[5] = response.encodeURL
(request.getContextPath() + "/" +
sm.getString("htmlManagerServlet.helpManagerFile"));
args[6] = sm.getString("htmlManagerServlet.helpManager");
if (completeStatus) {
args[7] = response.encodeURL
(request.getContextPath() + "/status");
args[8] = sm.getString("statusServlet.title");
} else {
args[7] = response.encodeURL
(request.getContextPath() + "/status/all");
args[8] = sm.getString("statusServlet.complete");
}
// use StatusTransformer to output status
StatusTransformer.writeManager(writer,args,mode);
// Server Header Section
args = new Object[9];
args[0] = sm.getString("htmlManagerServlet.serverTitle");
args[1] = sm.getString("htmlManagerServlet.serverVersion");
args[2] = sm.getString("htmlManagerServlet.serverJVMVersion");
args[3] = sm.getString("htmlManagerServlet.serverJVMVendor");
args[4] = sm.getString("htmlManagerServlet.serverOSName");
args[5] = sm.getString("htmlManagerServlet.serverOSVersion");
args[6] = sm.getString("htmlManagerServlet.serverOSArch");
args[7] = sm.getString("htmlManagerServlet.serverHostname");
args[8] = sm.getString("htmlManagerServlet.serverIPAddress");
// use StatusTransformer to output status
StatusTransformer.writePageHeading(writer,args,mode);
// Server Row Section
args = new Object[8];
args[0] = ServerInfo.getServerInfo();
args[1] = System.getProperty("java.runtime.version");
args[2] = System.getProperty("java.vm.vendor");
args[3] = System.getProperty("os.name");
args[4] = System.getProperty("os.version");
args[5] = System.getProperty("os.arch");
try {
InetAddress address = InetAddress.getLocalHost();
args[6] = address.getHostName();
args[7] = address.getHostAddress();
} catch (UnknownHostException e) {
args[6] = "-";
args[7] = "-";
}
// use StatusTransformer to output status
StatusTransformer.writeServerInfo(writer, args, mode);
try {
// Display operating system statistics using APR if available
StatusTransformer.writeOSState(writer,mode);
// Display virtual machine statistics
StatusTransformer.writeVMState(writer,mode);
Enumeration<ObjectName> enumeration = threadPools.elements();
while (enumeration.hasMoreElements()) {
ObjectName objectName = enumeration.nextElement();
String name = objectName.getKeyProperty("name");
// use StatusTransformer to output status
StatusTransformer.writeConnectorState
(writer, objectName,
name, mBeanServer, globalRequestProcessors,
requestProcessors, mode);
}
if ((request.getPathInfo() != null)
&& (request.getPathInfo().equals("/all"))) {
// Note: Retrieving the full status is much slower
// use StatusTransformer to output status
StatusTransformer.writeDetailedState
(writer, mBeanServer, mode);
}
} catch (Exception e) {
throw new ServletException(e);
}
// use StatusTransformer to output status
StatusTransformer.writeFooter(writer, mode);
}
// in java/org/apache/catalina/manager/ManagerServlet.java
Override
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
StringManager smClient = getStringManager(request);
// Identify the request parameters that we need
String command = request.getPathInfo();
if (command == null)
command = request.getServletPath();
String config = request.getParameter("config");
String path = request.getParameter("path");
ContextName cn = null;
if (path != null) {
cn = new ContextName(path, request.getParameter("version"));
}
String type = request.getParameter("type");
String war = request.getParameter("war");
String tag = request.getParameter("tag");
boolean update = false;
if ((request.getParameter("update") != null)
&& (request.getParameter("update").equals("true"))) {
update = true;
}
boolean statusLine = false;
if ("true".equals(request.getParameter("statusLine"))) {
statusLine = true;
}
// Prepare our output writer to generate the response message
response.setContentType("text/plain; charset=" + Constants.CHARSET);
PrintWriter writer = response.getWriter();
// Process the requested command (note - "/deploy" is not listed here)
if (command == null) {
writer.println(smClient.getString("managerServlet.noCommand"));
} else if (command.equals("/deploy")) {
if (war != null || config != null) {
deploy(writer, config, cn, war, update, smClient);
} else {
deploy(writer, cn, tag, smClient);
}
} else if (command.equals("/list")) {
list(writer, smClient);
} else if (command.equals("/reload")) {
reload(writer, cn, smClient);
} else if (command.equals("/resources")) {
resources(writer, type, smClient);
} else if (command.equals("/save")) {
save(writer, path, smClient);
} else if (command.equals("/serverinfo")) {
serverinfo(writer, smClient);
} else if (command.equals("/sessions")) {
expireSessions(writer, cn, request, smClient);
} else if (command.equals("/expire")) {
expireSessions(writer, cn, request, smClient);
} else if (command.equals("/start")) {
start(writer, cn, smClient);
} else if (command.equals("/stop")) {
stop(writer, cn, smClient);
} else if (command.equals("/undeploy")) {
undeploy(writer, cn, smClient);
} else if (command.equals("/findleaks")) {
findleaks(statusLine, writer, smClient);
} else {
writer.println(smClient.getString("managerServlet.unknownCommand",
command));
}
// Finish up the response
writer.flush();
writer.close();
}
// in java/org/apache/catalina/manager/ManagerServlet.java
Override
public void doPut(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
StringManager smClient = getStringManager(request);
// Identify the request parameters that we need
String command = request.getPathInfo();
if (command == null)
command = request.getServletPath();
String path = request.getParameter("path");
ContextName cn = null;
if (path != null) {
cn = new ContextName(path, request.getParameter("version"));
}
String tag = request.getParameter("tag");
boolean update = false;
if ((request.getParameter("update") != null)
&& (request.getParameter("update").equals("true"))) {
update = true;
}
// Prepare our output writer to generate the response message
response.setContentType("text/plain;charset="+Constants.CHARSET);
PrintWriter writer = response.getWriter();
// Process the requested command
if (command == null) {
writer.println(smClient.getString("managerServlet.noCommand"));
} else if (command.equals("/deploy")) {
deploy(writer, cn, tag, update, request, smClient);
} else {
writer.println(smClient.getString("managerServlet.unknownCommand",
command));
}
// Finish up the response
writer.flush();
writer.close();
}
// in java/org/apache/catalina/manager/ManagerServlet.java
protected void uploadWar(PrintWriter writer, HttpServletRequest request,
File war, StringManager smClient) throws IOException {
if (war.exists() && !war.delete()) {
String msg = smClient.getString("managerServlet.deleteFail", war);
throw new IOException(msg);
}
ServletInputStream istream = null;
BufferedOutputStream ostream = null;
try {
istream = request.getInputStream();
ostream =
new BufferedOutputStream(new FileOutputStream(war), 1024);
byte buffer[] = new byte[1024];
while (true) {
int n = istream.read(buffer);
if (n < 0) {
break;
}
ostream.write(buffer, 0, n);
}
ostream.flush();
ostream.close();
ostream = null;
istream.close();
istream = null;
} catch (IOException e) {
if (war.exists() && !war.delete()) {
writer.println(
smClient.getString("managerServlet.deleteFail", war));
}
throw e;
} finally {
if (ostream != null) {
try {
ostream.close();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
}
ostream = null;
}
if (istream != null) {
try {
istream.close();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
}
istream = null;
}
}
}
// in java/org/apache/catalina/tribes/group/RpcMessage.java
Override
public void readExternal(ObjectInput in) throws IOException,ClassNotFoundException {
reply = in.readBoolean();
int length = in.readInt();
uuid = new byte[length];
in.readFully(uuid);
length = in.readInt();
rpcId = new byte[length];
in.readFully(rpcId);
message = (Serializable)in.readObject();
}
// in java/org/apache/catalina/tribes/group/RpcMessage.java
Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeBoolean(reply);
out.writeInt(uuid.length);
out.write(uuid, 0, uuid.length);
out.writeInt(rpcId.length);
out.write(rpcId, 0, rpcId.length);
out.writeObject(message);
}
// in java/org/apache/catalina/tribes/group/RpcMessage.java
Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
reply = true;
int length = in.readInt();
uuid = new byte[length];
in.readFully(uuid);
length = in.readInt();
rpcId = new byte[length];
in.readFully(rpcId);
}
// in java/org/apache/catalina/tribes/group/RpcMessage.java
Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeInt(uuid.length);
out.write(uuid, 0, uuid.length);
out.writeInt(rpcId.length);
out.write(rpcId, 0, rpcId.length);
}
// in java/org/apache/catalina/tribes/group/interceptors/GzipInterceptor.java
public static byte[] compress(byte[] data) throws IOException {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
GZIPOutputStream gout = new GZIPOutputStream(bout);
gout.write(data);
gout.flush();
gout.close();
return bout.toByteArray();
}
// in java/org/apache/catalina/tribes/group/interceptors/GzipInterceptor.java
public static byte[] decompress(byte[] data) throws IOException {
ByteArrayOutputStream bout =
new ByteArrayOutputStream(DEFAULT_BUFFER_SIZE);
ByteArrayInputStream bin = new ByteArrayInputStream(data);
GZIPInputStream gin = new GZIPInputStream(bin);
byte[] tmp = new byte[DEFAULT_BUFFER_SIZE];
int length = gin.read(tmp);
while (length > -1) {
bout.write(tmp, 0, length);
length = gin.read(tmp);
}
return bout.toByteArray();
}
// in java/org/apache/catalina/tribes/ByteMessage.java
Override
public void readExternal(ObjectInput in ) throws IOException {
int length = in.readInt();
message = new byte[length];
in.readFully(message);
}
// in java/org/apache/catalina/tribes/ByteMessage.java
Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeInt(message!=null?message.length:0);
if ( message!=null ) out.write(message,0,message.length);
}
// in java/org/apache/catalina/tribes/io/ObjectReader.java
public int append(ByteBuffer data, int len, boolean count) throws java.io.IOException {
buffer.append(data,len);
int pkgCnt = -1;
if ( count ) pkgCnt = buffer.countPackages();
return pkgCnt;
}
// in java/org/apache/catalina/tribes/io/ObjectReader.java
public ChannelMessage[] execute() throws java.io.IOException {
int pkgCnt = buffer.countPackages();
ChannelMessage[] result = new ChannelMessage[pkgCnt];
for (int i=0; i<pkgCnt; i++) {
ChannelMessage data = buffer.extractPackage(true);
result[i] = data;
}
return result;
}
// in java/org/apache/catalina/tribes/io/XByteBuffer.java
public static Serializable deserialize(byte[] data)
throws IOException, ClassNotFoundException, ClassCastException {
return deserialize(data,0,data.length);
}
// in java/org/apache/catalina/tribes/io/XByteBuffer.java
public static Serializable deserialize(byte[] data, int offset, int length)
throws IOException, ClassNotFoundException, ClassCastException {
return deserialize(data,offset,length,null);
}
// in java/org/apache/catalina/tribes/io/XByteBuffer.java
public static Serializable deserialize(byte[] data, int offset, int length, ClassLoader[] cls)
throws IOException, ClassNotFoundException, ClassCastException {
invokecount.addAndGet(1);
Object message = null;
if ( cls == null ) cls = new ClassLoader[0];
if (data != null && length > 0) {
InputStream instream = new ByteArrayInputStream(data,offset,length);
ObjectInputStream stream = null;
stream = (cls.length>0)? new ReplicationStream(instream,cls):new ObjectInputStream(instream);
message = stream.readObject();
instream.close();
stream.close();
}
if ( message == null ) {
return null;
} else if (message instanceof Serializable)
return (Serializable) message;
else {
throw new ClassCastException("Message has the wrong class. It should implement Serializable, instead it is:"+message.getClass().getName());
}
}
// in java/org/apache/catalina/tribes/io/XByteBuffer.java
public static byte[] serialize(Serializable msg) throws IOException {
ByteArrayOutputStream outs = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(outs);
out.writeObject(msg);
out.flush();
byte[] data = outs.toByteArray();
return data;
}
// in java/org/apache/catalina/tribes/io/ReplicationStream.java
Override
public Class<?> resolveClass(ObjectStreamClass classDesc)
throws ClassNotFoundException, IOException {
String name = classDesc.getName();
try {
return resolveClass(name);
} catch (ClassNotFoundException e) {
return super.resolveClass(classDesc);
}
}
// in java/org/apache/catalina/tribes/io/ReplicationStream.java
Override
protected Class<?> resolveProxyClass(String[] interfaces)
throws IOException, ClassNotFoundException {
ClassLoader latestLoader = (classLoaders!=null && classLoaders.length==0)?null:classLoaders[0];
ClassLoader nonPublicLoader = null;
boolean hasNonPublicInterface = false;
// define proxy in class loader of non-public interface(s), if any
Class<?>[] classObjs = new Class[interfaces.length];
for (int i = 0; i < interfaces.length; i++) {
Class<?> cl = this.resolveClass(interfaces[i]);
if (latestLoader==null) latestLoader = cl.getClassLoader();
if ((cl.getModifiers() & Modifier.PUBLIC) == 0) {
if (hasNonPublicInterface) {
if (nonPublicLoader != cl.getClassLoader()) {
throw new IllegalAccessError(
"conflicting non-public interface class loaders");
}
} else {
nonPublicLoader = cl.getClassLoader();
hasNonPublicInterface = true;
}
}
classObjs[i] = cl;
}
try {
return Proxy.getProxyClass(hasNonPublicInterface ? nonPublicLoader
: latestLoader, classObjs);
} catch (IllegalArgumentException e) {
throw new ClassNotFoundException(null, e);
}
}
// in java/org/apache/catalina/tribes/io/ReplicationStream.java
Override
public void close() throws IOException {
this.classLoaders = null;
super.close();
}
// in java/org/apache/catalina/tribes/io/DirectByteArrayOutputStream.java
Override
public void write(int b) throws IOException {
buffer.append((byte)b);
}
// in java/org/apache/catalina/tribes/transport/bio/BioSender.java
Override
public void connect() throws IOException {
openSocket();
}
// in java/org/apache/catalina/tribes/transport/bio/BioSender.java
public void sendMessage(byte[] data, boolean waitForAck) throws IOException {
IOException exception = null;
setAttempt(0);
try {
// first try with existing connection
pushMessage(data,false,waitForAck);
} catch (IOException x) {
SenderState.getSenderState(getDestination()).setSuspect();
exception = x;
if (log.isTraceEnabled()) log.trace(sm.getString("IDataSender.send.again", getAddress().getHostAddress(),new Integer(getPort())),x);
while ( getAttempt()<getMaxRetryAttempts() ) {
try {
setAttempt(getAttempt()+1);
// second try with fresh connection
pushMessage(data, true,waitForAck);
exception = null;
} catch (IOException xx) {
exception = xx;
closeSocket();
}
}
} finally {
setRequestCount(getRequestCount()+1);
keepalive();
if ( exception != null ) throw exception;
}
}
// in java/org/apache/catalina/tribes/transport/bio/BioSender.java
protected void openSocket() throws IOException {
if(isConnected()) return ;
try {
socket = new Socket();
InetSocketAddress sockaddr = new InetSocketAddress(getAddress(), getPort());
socket.connect(sockaddr,(int)getTimeout());
socket.setSendBufferSize(getTxBufSize());
socket.setReceiveBufferSize(getRxBufSize());
socket.setSoTimeout( (int) getTimeout());
socket.setTcpNoDelay(getTcpNoDelay());
socket.setKeepAlive(getSoKeepAlive());
socket.setReuseAddress(getSoReuseAddress());
socket.setOOBInline(getOoBInline());
socket.setSoLinger(getSoLingerOn(),getSoLingerTime());
socket.setTrafficClass(getSoTrafficClass());
setConnected(true);
soOut = socket.getOutputStream();
soIn = socket.getInputStream();
setRequestCount(0);
setConnectTime(System.currentTimeMillis());
if (log.isDebugEnabled())
log.debug(sm.getString("IDataSender.openSocket", getAddress().getHostAddress(), new Integer(getPort()), new Long(0)));
} catch (IOException ex1) {
SenderState.getSenderState(getDestination()).setSuspect();
if (log.isDebugEnabled())
log.debug(sm.getString("IDataSender.openSocket.failure",getAddress().getHostAddress(), new Integer(getPort()),new Long(0)), ex1);
throw (ex1);
}
}
// in java/org/apache/catalina/tribes/transport/bio/BioSender.java
protected void pushMessage(byte[] data, boolean reconnect, boolean waitForAck) throws IOException {
keepalive();
if ( reconnect ) closeSocket();
if (!isConnected()) openSocket();
soOut.write(data);
soOut.flush();
if (waitForAck) waitForAck();
SenderState.getSenderState(getDestination()).setReady();
}
// in java/org/apache/catalina/tribes/transport/bio/BioSender.java
protected void waitForAck() throws java.io.IOException {
try {
boolean ackReceived = false;
boolean failAckReceived = false;
ackbuf.clear();
int bytesRead = 0;
int i = soIn.read();
while ((i != -1) && (bytesRead < Constants.ACK_COMMAND.length)) {
bytesRead++;
byte d = (byte)i;
ackbuf.append(d);
if (ackbuf.doesPackageExist() ) {
byte[] ackcmd = ackbuf.extractDataPackage(true).getBytes();
ackReceived = Arrays.equals(ackcmd,org.apache.catalina.tribes.transport.Constants.ACK_DATA);
failAckReceived = Arrays.equals(ackcmd,org.apache.catalina.tribes.transport.Constants.FAIL_ACK_DATA);
ackReceived = ackReceived || failAckReceived;
break;
}
i = soIn.read();
}
if (!ackReceived) {
if (i == -1) throw new IOException(sm.getString("IDataSender.ack.eof",getAddress(), new Integer(socket.getLocalPort())));
else throw new IOException(sm.getString("IDataSender.ack.wrong",getAddress(), new Integer(socket.getLocalPort())));
} else if ( failAckReceived && getThrowOnFailedAck()) {
throw new RemoteProcessException("Received a failed ack:org.apache.catalina.tribes.transport.Constants.FAIL_ACK_DATA");
}
} catch (IOException x) {
String errmsg = sm.getString("IDataSender.ack.missing", getAddress(),new Integer(socket.getLocalPort()), new Long(getTimeout()));
if ( SenderState.getSenderState(getDestination()).isReady() ) {
SenderState.getSenderState(getDestination()).setSuspect();
if ( log.isWarnEnabled() ) log.warn(errmsg, x);
} else {
if ( log.isDebugEnabled() )log.debug(errmsg, x);
}
throw x;
} finally {
ackbuf.clear();
}
}
// in java/org/apache/catalina/tribes/transport/bio/BioReceiver.java
Override
public void start() throws IOException {
super.start();
try {
setPool(new RxTaskPool(getMaxThreads(),getMinThreads(),this));
} catch (Exception x) {
log.fatal("ThreadPool can initilzed. Listener not started", x);
if ( x instanceof IOException ) throw (IOException)x;
else throw new IOException(x.getMessage());
}
try {
getBind();
bind();
Thread t = new Thread(this, "BioReceiver");
t.setDaemon(true);
t.start();
} catch (Exception x) {
log.fatal("Unable to start cluster receiver", x);
if ( x instanceof IOException ) throw (IOException)x;
else throw new IOException(x.getMessage());
}
}
// in java/org/apache/catalina/tribes/transport/bio/BioReceiver.java
protected void bind() throws IOException {
// allocate an unbound server socket channel
serverSocket = new ServerSocket();
// set the port the server channel will listen to
//serverSocket.bind(new InetSocketAddress(getBind(), getTcpListenPort()));
bind(serverSocket,getPort(),getAutoBind());
}
// in java/org/apache/catalina/tribes/transport/bio/MultipointBioSender.java
Override
public void connect() throws IOException {
//do nothing, we connect on demand
setConnected(true);
}
// in java/org/apache/catalina/tribes/transport/ReceiverBase.java
Override
public void start() throws IOException {
if ( executor == null ) {
//executor = new ThreadPoolExecutor(minThreads,maxThreads,60,TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>());
TaskThreadFactory tf = new TaskThreadFactory("Tribes-Task-Receiver-");
executor = ExecutorFactory.newThreadPool(minThreads, maxThreads, maxIdleTime, TimeUnit.MILLISECONDS, tf);
}
}
// in java/org/apache/catalina/tribes/transport/ReceiverBase.java
protected void bind(ServerSocket socket, int portstart, int retries) throws IOException {
synchronized (bindLock) {
InetSocketAddress addr = null;
int port = portstart;
while (retries > 0) {
try {
addr = new InetSocketAddress(getBind(), port);
socket.bind(addr);
setPort(port);
log.info("Receiver Server Socket bound to:"+addr);
retries = 0;
} catch ( IOException x) {
retries--;
if ( retries <= 0 ) {
log.info("Unable to bind server socket to:" + addr +
" throwing error.");
throw x;
}
port++;
}
}
}
}
// in java/org/apache/catalina/tribes/transport/ReceiverBase.java
protected int bindUdp(DatagramSocket socket, int portstart, int retries) throws IOException {
InetSocketAddress addr = null;
while ( retries > 0 ) {
try {
addr = new InetSocketAddress(getBind(), portstart);
socket.bind(addr);
setUdpPort(portstart);
log.info("UDP Receiver Server Socket bound to:"+addr);
return 0;
}catch ( IOException x) {
retries--;
if ( retries <= 0 ) {
log.info("Unable to bind UDP socket to:"+addr+" throwing error.");
throw x;
}
portstart++;
try {
Thread.sleep(25);
} catch (InterruptedException ti) {
Thread.currentThread().interrupt();
}
retries = bindUdp(socket,portstart,retries);
}
}
return retries;
}
// in java/org/apache/catalina/tribes/transport/nio/NioSender.java
public boolean process(SelectionKey key, boolean waitForAck) throws IOException {
int ops = key.readyOps();
key.interestOps(key.interestOps() & ~ops);
//in case disconnect has been called
if ((!isConnected()) && (!connecting)) throw new IOException("Sender has been disconnected, can't selection key.");
if ( !key.isValid() ) throw new IOException("Key is not valid, it must have been cancelled.");
if ( key.isConnectable() ) {
if ( socketChannel.finishConnect() ) {
completeConnect();
if ( current != null ) key.interestOps(key.interestOps() | SelectionKey.OP_WRITE);
return false;
} else {
//wait for the connection to finish
key.interestOps(key.interestOps() | SelectionKey.OP_CONNECT);
return false;
}//end if
} else if ( key.isWritable() ) {
boolean writecomplete = write();
if ( writecomplete ) {
//we are completed, should we read an ack?
if ( waitForAck ) {
//register to read the ack
key.interestOps(key.interestOps() | SelectionKey.OP_READ);
} else {
//if not, we are ready, setMessage will reregister us for another write interest
//do a health check, we have no way of verify a disconnected
//socket since we don't register for OP_READ on waitForAck=false
read();//this causes overhead
setRequestCount(getRequestCount()+1);
return true;
}
} else {
//we are not complete, lets write some more
key.interestOps(key.interestOps()|SelectionKey.OP_WRITE);
}//end if
} else if ( key.isReadable() ) {
boolean readcomplete = read();
if ( readcomplete ) {
setRequestCount(getRequestCount()+1);
return true;
} else {
key.interestOps(key.interestOps() | SelectionKey.OP_READ);
}//end if
} else {
//unknown state, should never happen
log.warn("Data is in unknown state. readyOps="+ops);
throw new IOException("Data is in unknown state. readyOps="+ops);
}//end if
return false;
}
// in java/org/apache/catalina/tribes/transport/nio/NioSender.java
protected boolean read() throws IOException {
//if there is no message here, we are done
if ( current == null ) return true;
int read = isUdpBased()?dataChannel.read(readbuf) : socketChannel.read(readbuf);
//end of stream
if ( read == -1 ) throw new IOException("Unable to receive an ack message. EOF on socket channel has been reached.");
//no data read
else if ( read == 0 ) return false;
readbuf.flip();
ackbuf.append(readbuf,read);
readbuf.clear();
if (ackbuf.doesPackageExist() ) {
byte[] ackcmd = ackbuf.extractDataPackage(true).getBytes();
boolean ack = Arrays.equals(ackcmd,org.apache.catalina.tribes.transport.Constants.ACK_DATA);
boolean fack = Arrays.equals(ackcmd,org.apache.catalina.tribes.transport.Constants.FAIL_ACK_DATA);
if ( fack && getThrowOnFailedAck() ) throw new RemoteProcessException("Received a failed ack:org.apache.catalina.tribes.transport.Constants.FAIL_ACK_DATA");
return ack || fack;
} else {
return false;
}
}
// in java/org/apache/catalina/tribes/transport/nio/NioSender.java
protected boolean write() throws IOException {
if ( (!isConnected()) || (this.socketChannel==null && this.dataChannel==null)) {
throw new IOException("NioSender is not connected, this should not occur.");
}
if ( current != null ) {
if ( remaining > 0 ) {
//we have written everything, or we are starting a new package
//protect against buffer overwrite
int byteswritten = isUdpBased()?dataChannel.write(writebuf) : socketChannel.write(writebuf);
if (byteswritten == -1 ) throw new EOFException();
remaining -= byteswritten;
//if the entire message was written from the buffer
//reset the position counter
if ( remaining < 0 ) {
remaining = 0;
}
}
return (remaining==0);
}
//no message to send, we can consider that complete
return true;
}
// in java/org/apache/catalina/tribes/transport/nio/NioSender.java
Override
public synchronized void connect() throws IOException {
if ( connecting || isConnected()) return;
connecting = true;
if ( isConnected() ) throw new IOException("NioSender is already in connected state.");
if ( readbuf == null ) {
readbuf = getReadBuffer();
} else {
readbuf.clear();
}
if ( writebuf == null ) {
writebuf = getWriteBuffer();
} else {
writebuf.clear();
}
if (isUdpBased()) {
InetSocketAddress daddr = new InetSocketAddress(getAddress(),getUdpPort());
if ( dataChannel != null ) throw new IOException("Datagram channel has already been established. Connection might be in progress.");
dataChannel = DatagramChannel.open();
dataChannel.configureBlocking(false);
dataChannel.connect(daddr);
completeConnect();
dataChannel.register(getSelector(),SelectionKey.OP_WRITE, this);
} else {
InetSocketAddress addr = new InetSocketAddress(getAddress(),getPort());
if ( socketChannel != null ) throw new IOException("Socket channel has already been established. Connection might be in progress.");
socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
if ( socketChannel.connect(addr) ) {
completeConnect();
socketChannel.register(getSelector(), SelectionKey.OP_WRITE, this);
} else {
socketChannel.register(getSelector(), SelectionKey.OP_CONNECT, this);
}
}
}
// in java/org/apache/catalina/tribes/transport/nio/NioSender.java
public synchronized void setMessage(byte[] data) throws IOException {
setMessage(data,0,data.length);
}
// in java/org/apache/catalina/tribes/transport/nio/NioSender.java
public synchronized void setMessage(byte[] data,int offset, int length) throws IOException {
if ( data != null ) {
current = data;
remaining = length;
ackbuf.clear();
if ( writebuf != null ) writebuf.clear();
else writebuf = getBuffer(length);
if ( writebuf.capacity() < length ) writebuf = getBuffer(length);
//TODO use ByteBuffer.wrap to avoid copying the data.
writebuf.put(data,offset,length);
//writebuf.rewind();
//set the limit so that we don't write non wanted data
//writebuf.limit(length);
writebuf.flip();
if (isConnected()) {
if (isUdpBased())
dataChannel.register(getSelector(), SelectionKey.OP_WRITE, this);
else
socketChannel.register(getSelector(), SelectionKey.OP_WRITE, this);
}
}
}
// in java/org/apache/catalina/tribes/transport/nio/PooledParallelSender.java
Override
public synchronized void connect() throws IOException {
this.connected = true;
super.connect();
}
// in java/org/apache/catalina/tribes/transport/nio/ParallelNioSender.java
private int doLoop(long selectTimeOut, int maxAttempts, boolean waitForAck, ChannelMessage msg) throws IOException, ChannelException {
int completed = 0;
int selectedKeys = selector.select(selectTimeOut);
if (selectedKeys == 0) {
return 0;
}
Iterator<SelectionKey> it = selector.selectedKeys().iterator();
while (it.hasNext()) {
SelectionKey sk = it.next();
it.remove();
int readyOps = sk.readyOps();
sk.interestOps(sk.interestOps() & ~readyOps);
NioSender sender = (NioSender) sk.attachment();
try {
if (sender.process(sk,waitForAck)) {
completed++;
sender.setComplete(true);
if ( Logs.MESSAGES.isTraceEnabled() ) {
Logs.MESSAGES.trace("ParallelNioSender - Sent msg:" + new UniqueId(msg.getUniqueId()) + " at " +new java.sql.Timestamp(System.currentTimeMillis())+ " to "+sender.getDestination().getName());
}
SenderState.getSenderState(sender.getDestination()).setReady();
}//end if
} catch (Exception x) {
if (log.isTraceEnabled()) {
log.trace("Error while processing send to " + sender.getDestination().getName(), x);
}
SenderState state = SenderState.getSenderState(sender.getDestination());
int attempt = sender.getAttempt()+1;
boolean retry = (sender.getAttempt() <= maxAttempts && maxAttempts>0);
synchronized (state) {
//sk.cancel();
if (state.isSuspect()) state.setFailing();
if (state.isReady()) {
state.setSuspect();
if ( retry )
log.warn("Member send is failing for:" + sender.getDestination().getName() +" ; Setting to suspect and retrying.");
else
log.warn("Member send is failing for:" + sender.getDestination().getName() +" ; Setting to suspect.", x);
}
}
if ( !isConnected() ) {
log.warn("Not retrying send for:" + sender.getDestination().getName() + "; Sender is disconnected.");
ChannelException cx = new ChannelException("Send failed, and sender is disconnected. Not retrying.",x);
cx.addFaultyMember(sender.getDestination(),x);
throw cx;
}
byte[] data = sender.getMessage();
if ( retry ) {
try {
sender.disconnect();
sender.connect();
sender.setAttempt(attempt);
sender.setMessage(data);
}catch ( Exception ignore){
state.setFailing();
}
} else {
ChannelException cx = new ChannelException("Send failed, attempt:"+sender.getAttempt()+" max:"+maxAttempts,x);
cx.addFaultyMember(sender.getDestination(),x);
throw cx;
}//end if
}
}
return completed;
}
// in java/org/apache/catalina/tribes/transport/nio/NioReceiver.java
Override
public void start() throws IOException {
super.start();
try {
setPool(new RxTaskPool(getMaxThreads(),getMinThreads(),this));
} catch (Exception x) {
log.fatal("ThreadPool can initilzed. Listener not started", x);
if ( x instanceof IOException ) throw (IOException)x;
else throw new IOException(x.getMessage());
}
try {
getBind();
bind();
Thread t = new Thread(this, "NioReceiver");
t.setDaemon(true);
t.start();
} catch (Exception x) {
log.fatal("Unable to start cluster receiver", x);
if ( x instanceof IOException ) throw (IOException)x;
else throw new IOException(x.getMessage());
}
}
// in java/org/apache/catalina/tribes/transport/nio/NioReceiver.java
protected void bind() throws IOException {
// allocate an unbound server socket channel
serverChannel = ServerSocketChannel.open();
// Get the associated ServerSocket to bind it with
ServerSocket serverSocket = serverChannel.socket();
// create a new Selector for use below
synchronized (Selector.class) {
// Selector.open() isn't thread safe
// http://bugs.sun.com/view_bug.do?bug_id=6427854
// Affects 1.6.0_29, fixed in 1.7.0_01
selector = Selector.open();
}
// set the port the server channel will listen to
//serverSocket.bind(new InetSocketAddress(getBind(), getTcpListenPort()));
bind(serverSocket,getPort(),getAutoBind());
// set non-blocking mode for the listening socket
serverChannel.configureBlocking(false);
// register the ServerSocketChannel with the Selector
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
//set up the datagram channel
if (this.getUdpPort()>0) {
datagramChannel = DatagramChannel.open();
datagramChannel.configureBlocking(false);
//bind to the address to avoid security checks
bindUdp(datagramChannel.socket(),getUdpPort(),getAutoBind());
}
}
// in java/org/apache/catalina/tribes/transport/nio/NioReceiver.java
private void closeSelector() throws IOException {
Selector selector = this.selector;
this.selector = null;
if (selector==null) return;
try {
Iterator<SelectionKey> it = selector.keys().iterator();
// look at each key in the selected set
while (it.hasNext()) {
SelectionKey key = it.next();
key.channel().close();
key.attach(null);
key.cancel();
}
}catch ( IOException ignore ){
if (log.isWarnEnabled()) {
log.warn("Unable to cleanup on selector close.",ignore);
}
}catch ( ClosedSelectorException ignore){}
selector.close();
}
// in java/org/apache/catalina/tribes/transport/PooledSender.java
Override
public synchronized void connect() throws IOException {
//do nothing, happens in the socket sender itself
queue.open();
setConnected(true);
}
// in java/org/apache/catalina/tribes/transport/ReplicationTransmitter.java
Override
public void start() throws java.io.IOException {
getTransport().connect();
}
// in java/org/apache/catalina/tribes/tipis/AbstractReplicatedMap.java
public void deserialize(ClassLoader[] cls) throws IOException, ClassNotFoundException {
key(cls);
value(cls);
}
// in java/org/apache/catalina/tribes/tipis/AbstractReplicatedMap.java
public Serializable key(ClassLoader[] cls) throws IOException, ClassNotFoundException {
if ( key!=null ) return key;
if ( keydata == null || keydata.length == 0 ) return null;
key = XByteBuffer.deserialize(keydata,0,keydata.length,cls);
keydata = null;
return key;
}
// in java/org/apache/catalina/tribes/tipis/AbstractReplicatedMap.java
public Serializable value(ClassLoader[] cls) throws IOException, ClassNotFoundException {
if ( value!=null ) return value;
if ( valuedata == null || valuedata.length == 0 ) return null;
value = XByteBuffer.deserialize(valuedata,0,valuedata.length,cls);
valuedata = null;
return value;
}
// in java/org/apache/catalina/tribes/tipis/AbstractReplicatedMap.java
protected Member[] readMembers(ObjectInput in) throws IOException {
int nodecount = in.readInt();
Member[] members = new Member[nodecount];
for ( int i=0; i<members.length; i++ ) {
byte[] d = new byte[in.readInt()];
in.readFully(d);
if (d.length > 0) members[i] = MemberImpl.getMember(d);
}
return members;
}
// in java/org/apache/catalina/tribes/tipis/AbstractReplicatedMap.java
protected void writeMembers(ObjectOutput out,Member[] members) throws IOException {
if ( members == null ) members = new Member[0];
out.writeInt(members.length);
for (int i=0; i<members.length; i++ ) {
if ( members[i] != null ) {
byte[] d = members[i] != null ? ( (MemberImpl)members[i]).getData(false) : new byte[0];
out.writeInt(d.length);
out.write(d);
}
}
}
// in java/org/apache/catalina/tribes/membership/MemberImpl.java
public void setHostname(String host) throws IOException {
hostname = host;
this.host = java.net.InetAddress.getByName(host).getAddress();
}
// in java/org/apache/catalina/tribes/membership/MemberImpl.java
Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
int length = in.readInt();
byte[] message = new byte[length];
in.readFully(message);
getMember(message,this);
}
// in java/org/apache/catalina/tribes/membership/MemberImpl.java
Override
public void writeExternal(ObjectOutput out) throws IOException {
byte[] data = this.getData();
out.writeInt(data.length);
out.write(data);
}
// in java/org/apache/catalina/tribes/membership/McastServiceImpl.java
public void init() throws IOException {
setupSocket();
sendPacket = new DatagramPacket(new byte[MAX_PACKET_SIZE],MAX_PACKET_SIZE);
sendPacket.setAddress(address);
sendPacket.setPort(port);
receivePacket = new DatagramPacket(new byte[MAX_PACKET_SIZE],MAX_PACKET_SIZE);
receivePacket.setAddress(address);
receivePacket.setPort(port);
member.setCommand(new byte[0]);
member.getData(true, true);
if ( membership == null ) membership = new Membership(member);
}
// in java/org/apache/catalina/tribes/membership/McastServiceImpl.java
protected void setupSocket() throws IOException {
if (mcastBindAddress != null) {
try {
log.info("Attempting to bind the multicast socket to "+address+":"+port);
socket = new MulticastSocket(new InetSocketAddress(address,port));
} catch (BindException e) {
/*
* On some platforms (e.g. Linux) it is not possible to bind
* to the multicast address. In this case only bind to the
* port.
*/
log.info("Binding to multicast address, failed. Binding to port only.");
socket = new MulticastSocket(port);
}
} else {
socket = new MulticastSocket(port);
}
socket.setLoopbackMode(localLoopbackDisabled); //hint if we want disable loop back(local machine) messages
if (mcastBindAddress != null) {
if(log.isInfoEnabled())
log.info("Setting multihome multicast interface to:" +mcastBindAddress);
socket.setInterface(mcastBindAddress);
} //end if
//force a so timeout so that we don't block forever
if ( mcastSoTimeout <= 0 ) mcastSoTimeout = (int)sendFrequency;
if(log.isInfoEnabled())
log.info("Setting cluster mcast soTimeout to "+mcastSoTimeout);
socket.setSoTimeout(mcastSoTimeout);
if ( mcastTTL >= 0 ) {
if(log.isInfoEnabled())
log.info("Setting cluster mcast TTL to " + mcastTTL);
socket.setTimeToLive(mcastTTL);
}
}
// in java/org/apache/catalina/tribes/membership/McastServiceImpl.java
public synchronized void start(int level) throws IOException {
boolean valid = false;
if ( (level & Channel.MBR_RX_SEQ)==Channel.MBR_RX_SEQ ) {
if ( receiver != null ) throw new IllegalStateException("McastService.receive already running.");
try {
if ( sender == null ) socket.joinGroup(address);
}catch (IOException iox) {
log.error("Unable to join multicast group, make sure your system has multicasting enabled.");
throw iox;
}
doRunReceiver = true;
receiver = new ReceiverThread();
receiver.setDaemon(true);
receiver.start();
valid = true;
}
if ( (level & Channel.MBR_TX_SEQ)==Channel.MBR_TX_SEQ ) {
if ( sender != null ) throw new IllegalStateException("McastService.send already running.");
if ( receiver == null ) socket.joinGroup(address);
//make sure at least one packet gets out there
send(false);
doRunSender = true;
sender = new SenderThread(sendFrequency);
sender.setDaemon(true);
sender.start();
//we have started the receiver, but not yet waited for membership to establish
valid = true;
}
if (!valid) {
throw new IllegalArgumentException("Invalid start level. Only acceptable levels are Channel.MBR_RX_SEQ and Channel.MBR_TX_SEQ");
}
//pause, once or twice
waitForMembers(level);
startLevel = (startLevel | level);
}
// in java/org/apache/catalina/tribes/membership/McastServiceImpl.java
public synchronized boolean stop(int level) throws IOException {
boolean valid = false;
if ( (level & Channel.MBR_RX_SEQ)==Channel.MBR_RX_SEQ ) {
valid = true;
doRunReceiver = false;
if ( receiver !=null ) receiver.interrupt();
receiver = null;
}
if ( (level & Channel.MBR_TX_SEQ)==Channel.MBR_TX_SEQ ) {
valid = true;
doRunSender = false;
if ( sender != null )sender.interrupt();
sender = null;
}
if (!valid) {
throw new IllegalArgumentException("Invalid stop level. Only acceptable levels are Channel.MBR_RX_SEQ and Channel.MBR_TX_SEQ");
}
startLevel = (startLevel & (~level));
//we're shutting down, send a shutdown message and close the socket
if ( startLevel == 0 ) {
//send a stop message
member.setCommand(Member.SHUTDOWN_PAYLOAD);
member.getData(true, true);
send(false);
//leave mcast group
try {socket.leaveGroup(address);}catch ( Exception ignore){}
try {socket.close();}catch ( Exception ignore){}
member.setServiceStartTime(-1);
}
return (startLevel == 0);
}
// in java/org/apache/catalina/tribes/membership/McastServiceImpl.java
public void receive() throws IOException {
boolean checkexpired = true;
try {
socket.receive(receivePacket);
if(receivePacket.getLength() > MAX_PACKET_SIZE) {
log.error("Multicast packet received was too long, dropping package:"+receivePacket.getLength());
} else {
byte[] data = new byte[receivePacket.getLength()];
System.arraycopy(receivePacket.getData(), receivePacket.getOffset(), data, 0, data.length);
if (XByteBuffer.firstIndexOf(data,0,MemberImpl.TRIBES_MBR_BEGIN)==0) {
memberDataReceived(data);
} else {
memberBroadcastsReceived(data);
}
}
} catch (SocketTimeoutException x ) {
//do nothing, this is normal, we don't want to block forever
//since the receive thread is the same thread
//that does membership expiration
}
if (checkexpired) checkExpired();
}
// in java/org/apache/catalina/tribes/membership/McastServiceImpl.java
public void send(boolean checkexpired) throws IOException{
send(checkexpired,null);
}
// in java/org/apache/catalina/tribes/membership/McastServiceImpl.java
public void send(boolean checkexpired, DatagramPacket packet) throws IOException{
checkexpired = (checkexpired && (packet==null));
//ignore if we haven't started the sender
//if ( (startLevel&Channel.MBR_TX_SEQ) != Channel.MBR_TX_SEQ ) return;
if (packet==null) {
member.inc();
if(log.isTraceEnabled()) {
log.trace("Mcast send ping from member " + member);
}
byte[] data = member.getData();
packet = new DatagramPacket(data,data.length);
} else if (log.isTraceEnabled()) {
log.trace("Sending message broadcast "+packet.getLength()+ " bytes from "+ member);
}
packet.setAddress(address);
packet.setPort(port);
//TODO this operation is not thread safe
synchronized (sendLock) {
socket.send(packet);
}
if ( checkexpired ) checkExpired();
}
// in java/org/apache/catalina/session/StandardManager.java
Override
public void load() throws ClassNotFoundException, IOException {
if (SecurityUtil.isPackageProtectionEnabled()){
try{
AccessController.doPrivileged( new PrivilegedDoLoad() );
} catch (PrivilegedActionException ex){
Exception exception = ex.getException();
if (exception instanceof ClassNotFoundException){
throw (ClassNotFoundException)exception;
} else if (exception instanceof IOException){
throw (IOException)exception;
}
if (log.isDebugEnabled())
log.debug("Unreported exception in load() "
+ exception);
}
} else {
doLoad();
}
}
// in java/org/apache/catalina/session/StandardManager.java
protected void doLoad() throws ClassNotFoundException, IOException {
if (log.isDebugEnabled())
log.debug("Start: Loading persisted sessions");
// Initialize our internal data structures
sessions.clear();
// Open an input stream to the specified pathname, if any
File file = file();
if (file == null)
return;
if (log.isDebugEnabled())
log.debug(sm.getString("standardManager.loading", pathname));
FileInputStream fis = null;
BufferedInputStream bis = null;
ObjectInputStream ois = null;
Loader loader = null;
ClassLoader classLoader = null;
try {
fis = new FileInputStream(file.getAbsolutePath());
bis = new BufferedInputStream(fis);
if (container != null)
loader = container.getLoader();
if (loader != null)
classLoader = loader.getClassLoader();
if (classLoader != null) {
if (log.isDebugEnabled())
log.debug("Creating custom object input stream for class loader ");
ois = new CustomObjectInputStream(bis, classLoader);
} else {
if (log.isDebugEnabled())
log.debug("Creating standard object input stream");
ois = new ObjectInputStream(bis);
}
} catch (FileNotFoundException e) {
if (log.isDebugEnabled())
log.debug("No persisted data file found");
return;
} catch (IOException e) {
log.error(sm.getString("standardManager.loading.ioe", e), e);
if (fis != null) {
try {
fis.close();
} catch (IOException f) {
// Ignore
}
}
if (bis != null) {
try {
bis.close();
} catch (IOException f) {
// Ignore
}
}
throw e;
}
// Load the previously unloaded active sessions
synchronized (sessions) {
try {
Integer count = (Integer) ois.readObject();
int n = count.intValue();
if (log.isDebugEnabled())
log.debug("Loading " + n + " persisted sessions");
for (int i = 0; i < n; i++) {
StandardSession session = getNewSession();
session.readObjectData(ois);
session.setManager(this);
sessions.put(session.getIdInternal(), session);
session.activate();
if (!session.isValidInternal()) {
// If session is already invalid,
// expire session to prevent memory leak.
session.setValid(true);
session.expire();
}
sessionCounter++;
}
} catch (ClassNotFoundException e) {
log.error(sm.getString("standardManager.loading.cnfe", e), e);
try {
ois.close();
} catch (IOException f) {
// Ignore
}
throw e;
} catch (IOException e) {
log.error(sm.getString("standardManager.loading.ioe", e), e);
try {
ois.close();
} catch (IOException f) {
// Ignore
}
throw e;
} finally {
// Close the input stream
try {
ois.close();
} catch (IOException f) {
// ignored
}
// Delete the persistent storage file
if (file.exists() )
file.delete();
}
}
if (log.isDebugEnabled())
log.debug("Finish: Loading persisted sessions");
}
// in java/org/apache/catalina/session/StandardManager.java
Override
public void unload() throws IOException {
if (SecurityUtil.isPackageProtectionEnabled()){
try{
AccessController.doPrivileged( new PrivilegedDoUnload() );
} catch (PrivilegedActionException ex){
Exception exception = ex.getException();
if (exception instanceof IOException){
throw (IOException)exception;
}
if (log.isDebugEnabled())
log.debug("Unreported exception in unLoad() "
+ exception);
}
} else {
doUnload();
}
}
// in java/org/apache/catalina/session/StandardManager.java
protected void doUnload() throws IOException {
if (log.isDebugEnabled())
log.debug(sm.getString("standardManager.unloading.debug"));
if (sessions.isEmpty()) {
log.debug(sm.getString("standardManager.unloading.nosessions"));
return; // nothing to do
}
// Open an output stream to the specified pathname, if any
File file = file();
if (file == null)
return;
if (log.isDebugEnabled())
log.debug(sm.getString("standardManager.unloading", pathname));
FileOutputStream fos = null;
BufferedOutputStream bos = null;
ObjectOutputStream oos = null;
boolean error = false;
try {
fos = new FileOutputStream(file.getAbsolutePath());
bos = new BufferedOutputStream(fos);
oos = new ObjectOutputStream(bos);
} catch (IOException e) {
error = true;
log.error(sm.getString("standardManager.unloading.ioe", e), e);
throw e;
} finally {
if (error) {
if (oos != null) {
try {
oos.close();
} catch (IOException ioe) {
// Ignore
}
}
if (bos != null) {
try {
bos.close();
} catch (IOException ioe) {
// Ignore
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException ioe) {
// Ignore
}
}
}
}
// Write the number of active sessions, followed by the details
ArrayList<StandardSession> list = new ArrayList<StandardSession>();
synchronized (sessions) {
if (log.isDebugEnabled())
log.debug("Unloading " + sessions.size() + " sessions");
try {
oos.writeObject(new Integer(sessions.size()));
Iterator<Session> elements = sessions.values().iterator();
while (elements.hasNext()) {
StandardSession session =
(StandardSession) elements.next();
list.add(session);
session.passivate();
session.writeObjectData(oos);
}
} catch (IOException e) {
log.error(sm.getString("standardManager.unloading.ioe", e), e);
try {
oos.close();
} catch (IOException f) {
// Ignore
}
throw e;
}
}
// Flush and close the output stream
try {
oos.flush();
} finally {
try {
oos.close();
} catch (IOException f) {
// Ignore
}
}
// Expire all the sessions we just wrote
if (log.isDebugEnabled())
log.debug("Expiring " + list.size() + " persisted sessions");
Iterator<StandardSession> expires = list.iterator();
while (expires.hasNext()) {
StandardSession session = expires.next();
try {
session.expire(false);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
} finally {
session.recycle();
}
}
if (log.isDebugEnabled())
log.debug("Unloading complete");
}
// in java/org/apache/catalina/session/ManagerBase.java
Override
public Session findSession(String id) throws IOException {
if (id == null)
return (null);
return sessions.get(id);
}
// in java/org/apache/catalina/session/JDBCStore.java
Override
public String[] keys() throws IOException {
ResultSet rst = null;
String keys[] = null;
synchronized (this) {
int numberOfTries = 2;
while (numberOfTries > 0) {
Connection _conn = getConnection();
if (_conn == null) {
return (new String[0]);
}
try {
if (preparedKeysSql == null) {
String keysSql = "SELECT " + sessionIdCol + " FROM "
+ sessionTable + " WHERE " + sessionAppCol
+ " = ?";
preparedKeysSql = _conn.prepareStatement(keysSql);
}
preparedKeysSql.setString(1, getName());
rst = preparedKeysSql.executeQuery();
ArrayList<String> tmpkeys = new ArrayList<String>();
if (rst != null) {
while (rst.next()) {
tmpkeys.add(rst.getString(1));
}
}
keys = tmpkeys.toArray(new String[tmpkeys.size()]);
// Break out after the finally block
numberOfTries = 0;
} catch (SQLException e) {
manager.getContainer().getLogger().error(sm.getString(getStoreName() + ".SQLException", e));
keys = new String[0];
// Close the connection so that it gets reopened next time
if (dbConnection != null)
close(dbConnection);
} finally {
try {
if (rst != null) {
rst.close();
}
} catch (SQLException e) {
// Ignore
}
release(_conn);
}
numberOfTries--;
}
}
return (keys);
}
// in java/org/apache/catalina/session/JDBCStore.java
Override
public int getSize() throws IOException {
int size = 0;
ResultSet rst = null;
synchronized (this) {
int numberOfTries = 2;
while (numberOfTries > 0) {
Connection _conn = getConnection();
if (_conn == null) {
return (size);
}
try {
if (preparedSizeSql == null) {
String sizeSql = "SELECT COUNT(" + sessionIdCol
+ ") FROM " + sessionTable + " WHERE "
+ sessionAppCol + " = ?";
preparedSizeSql = _conn.prepareStatement(sizeSql);
}
preparedSizeSql.setString(1, getName());
rst = preparedSizeSql.executeQuery();
if (rst.next()) {
size = rst.getInt(1);
}
// Break out after the finally block
numberOfTries = 0;
} catch (SQLException e) {
manager.getContainer().getLogger().error(sm.getString(getStoreName() + ".SQLException", e));
if (dbConnection != null)
close(dbConnection);
} finally {
try {
if (rst != null)
rst.close();
} catch (SQLException e) {
// Ignore
}
release(_conn);
}
numberOfTries--;
}
}
return (size);
}
// in java/org/apache/catalina/session/JDBCStore.java
Override
public Session load(String id)
throws ClassNotFoundException, IOException {
ResultSet rst = null;
StandardSession _session = null;
Loader loader = null;
ClassLoader classLoader = null;
ObjectInputStream ois = null;
BufferedInputStream bis = null;
Container container = manager.getContainer();
synchronized (this) {
int numberOfTries = 2;
while (numberOfTries > 0) {
Connection _conn = getConnection();
if (_conn == null) {
return (null);
}
try {
if (preparedLoadSql == null) {
String loadSql = "SELECT " + sessionIdCol + ", "
+ sessionDataCol + " FROM " + sessionTable
+ " WHERE " + sessionIdCol + " = ? AND "
+ sessionAppCol + " = ?";
preparedLoadSql = _conn.prepareStatement(loadSql);
}
preparedLoadSql.setString(1, id);
preparedLoadSql.setString(2, getName());
rst = preparedLoadSql.executeQuery();
if (rst.next()) {
bis = new BufferedInputStream(rst.getBinaryStream(2));
if (container != null) {
loader = container.getLoader();
}
if (loader != null) {
classLoader = loader.getClassLoader();
}
if (classLoader != null) {
ois = new CustomObjectInputStream(bis,
classLoader);
} else {
ois = new ObjectInputStream(bis);
}
if (manager.getContainer().getLogger().isDebugEnabled()) {
manager.getContainer().getLogger().debug(sm.getString(getStoreName() + ".loading",
id, sessionTable));
}
_session = (StandardSession) manager.createEmptySession();
_session.readObjectData(ois);
_session.setManager(manager);
} else if (manager.getContainer().getLogger().isDebugEnabled()) {
manager.getContainer().getLogger().debug(getStoreName() + ": No persisted data object found");
}
// Break out after the finally block
numberOfTries = 0;
} catch (SQLException e) {
manager.getContainer().getLogger().error(sm.getString(getStoreName() + ".SQLException", e));
if (dbConnection != null)
close(dbConnection);
} finally {
try {
if (rst != null) {
rst.close();
}
} catch (SQLException e) {
// Ignore
}
if (ois != null) {
try {
ois.close();
} catch (IOException e) {
// Ignore
}
}
release(_conn);
}
numberOfTries--;
}
}
return (_session);
}
// in java/org/apache/catalina/session/JDBCStore.java
Override
public void remove(String id) throws IOException {
synchronized (this) {
int numberOfTries = 2;
while (numberOfTries > 0) {
Connection _conn = getConnection();
if (_conn == null) {
return;
}
try {
remove(id, _conn);
// Break out after the finally block
numberOfTries = 0;
} catch (SQLException e) {
manager.getContainer().getLogger().error(sm.getString(getStoreName() + ".SQLException", e));
if (dbConnection != null)
close(dbConnection);
} finally {
release(_conn);
}
numberOfTries--;
}
}
if (manager.getContainer().getLogger().isDebugEnabled()) {
manager.getContainer().getLogger().debug(sm.getString(getStoreName() + ".removing", id, sessionTable));
}
}
// in java/org/apache/catalina/session/JDBCStore.java
Override
public void clear() throws IOException {
synchronized (this) {
int numberOfTries = 2;
while (numberOfTries > 0) {
Connection _conn = getConnection();
if (_conn == null) {
return;
}
try {
if (preparedClearSql == null) {
String clearSql = "DELETE FROM " + sessionTable
+ " WHERE " + sessionAppCol + " = ?";
preparedClearSql = _conn.prepareStatement(clearSql);
}
preparedClearSql.setString(1, getName());
preparedClearSql.execute();
// Break out after the finally block
numberOfTries = 0;
} catch (SQLException e) {
manager.getContainer().getLogger().error(sm.getString(getStoreName() + ".SQLException", e));
if (dbConnection != null)
close(dbConnection);
} finally {
release(_conn);
}
numberOfTries--;
}
}
}
// in java/org/apache/catalina/session/JDBCStore.java
Override
public void save(Session session) throws IOException {
ObjectOutputStream oos = null;
ByteArrayOutputStream bos = null;
ByteArrayInputStream bis = null;
InputStream in = null;
synchronized (this) {
int numberOfTries = 2;
while (numberOfTries > 0) {
Connection _conn = getConnection();
if (_conn == null) {
return;
}
try {
// If sessions already exist in DB, remove and insert again.
// TODO:
// * Check if ID exists in database and if so use UPDATE.
remove(session.getIdInternal(), _conn);
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(new BufferedOutputStream(bos));
((StandardSession) session).writeObjectData(oos);
oos.close();
oos = null;
byte[] obs = bos.toByteArray();
int size = obs.length;
bis = new ByteArrayInputStream(obs, 0, size);
in = new BufferedInputStream(bis, size);
if (preparedSaveSql == null) {
String saveSql = "INSERT INTO " + sessionTable + " ("
+ sessionIdCol + ", " + sessionAppCol + ", "
+ sessionDataCol + ", " + sessionValidCol
+ ", " + sessionMaxInactiveCol + ", "
+ sessionLastAccessedCol
+ ") VALUES (?, ?, ?, ?, ?, ?)";
preparedSaveSql = _conn.prepareStatement(saveSql);
}
preparedSaveSql.setString(1, session.getIdInternal());
preparedSaveSql.setString(2, getName());
preparedSaveSql.setBinaryStream(3, in, size);
preparedSaveSql.setString(4, session.isValid() ? "1" : "0");
preparedSaveSql.setInt(5, session.getMaxInactiveInterval());
preparedSaveSql.setLong(6, session.getLastAccessedTime());
preparedSaveSql.execute();
// Break out after the finally block
numberOfTries = 0;
} catch (SQLException e) {
manager.getContainer().getLogger().error(sm.getString(getStoreName() + ".SQLException", e));
if (dbConnection != null)
close(dbConnection);
} catch (IOException e) {
// Ignore
} finally {
if (oos != null) {
oos.close();
}
if (bis != null) {
bis.close();
}
if (in != null) {
in.close();
}
release(_conn);
}
numberOfTries--;
}
}
if (manager.getContainer().getLogger().isDebugEnabled()) {
manager.getContainer().getLogger().debug(sm.getString(getStoreName() + ".saving",
session.getIdInternal(), sessionTable));
}
}
// in java/org/apache/catalina/session/FileStore.java
Override
public int getSize() throws IOException {
// Acquire the list of files in our storage directory
File file = directory();
if (file == null) {
return (0);
}
String files[] = file.list();
// Figure out which files are sessions
int keycount = 0;
for (int i = 0; i < files.length; i++) {
if (files[i].endsWith(FILE_EXT)) {
keycount++;
}
}
return (keycount);
}
// in java/org/apache/catalina/session/FileStore.java
Override
public void clear()
throws IOException {
String[] keys = keys();
for (int i = 0; i < keys.length; i++) {
remove(keys[i]);
}
}
// in java/org/apache/catalina/session/FileStore.java
Override
public String[] keys() throws IOException {
// Acquire the list of files in our storage directory
File file = directory();
if (file == null) {
return (new String[0]);
}
String files[] = file.list();
// Bugzilla 32130
if((files == null) || (files.length < 1)) {
return (new String[0]);
}
// Build and return the list of session identifiers
ArrayList<String> list = new ArrayList<String>();
int n = FILE_EXT.length();
for (int i = 0; i < files.length; i++) {
if (files[i].endsWith(FILE_EXT)) {
list.add(files[i].substring(0, files[i].length() - n));
}
}
return list.toArray(new String[list.size()]);
}
// in java/org/apache/catalina/session/FileStore.java
Override
public Session load(String id)
throws ClassNotFoundException, IOException {
// Open an input stream to the specified pathname, if any
File file = file(id);
if (file == null) {
return (null);
}
if (! file.exists()) {
return (null);
}
if (manager.getContainer().getLogger().isDebugEnabled()) {
manager.getContainer().getLogger().debug(sm.getString(getStoreName()+".loading",
id, file.getAbsolutePath()));
}
FileInputStream fis = null;
BufferedInputStream bis = null;
ObjectInputStream ois = null;
Loader loader = null;
ClassLoader classLoader = null;
try {
fis = new FileInputStream(file.getAbsolutePath());
bis = new BufferedInputStream(fis);
Container container = manager.getContainer();
if (container != null)
loader = container.getLoader();
if (loader != null)
classLoader = loader.getClassLoader();
if (classLoader != null)
ois = new CustomObjectInputStream(bis, classLoader);
else
ois = new ObjectInputStream(bis);
} catch (FileNotFoundException e) {
if (manager.getContainer().getLogger().isDebugEnabled())
manager.getContainer().getLogger().debug("No persisted data file found");
return (null);
} catch (IOException e) {
if (bis != null) {
try {
bis.close();
} catch (IOException f) {
// Ignore
}
}
if (fis != null) {
try {
fis.close();
} catch (IOException f) {
// Ignore
}
}
throw e;
}
try {
StandardSession session =
(StandardSession) manager.createEmptySession();
session.readObjectData(ois);
session.setManager(manager);
return (session);
} finally {
// Close the input stream
try {
ois.close();
} catch (IOException f) {
// Ignore
}
}
}
// in java/org/apache/catalina/session/FileStore.java
Override
public void remove(String id) throws IOException {
File file = file(id);
if (file == null) {
return;
}
if (manager.getContainer().getLogger().isDebugEnabled()) {
manager.getContainer().getLogger().debug(sm.getString(getStoreName()+".removing",
id, file.getAbsolutePath()));
}
file.delete();
}
// in java/org/apache/catalina/session/FileStore.java
Override
public void save(Session session) throws IOException {
// Open an output stream to the specified pathname, if any
File file = file(session.getIdInternal());
if (file == null) {
return;
}
if (manager.getContainer().getLogger().isDebugEnabled()) {
manager.getContainer().getLogger().debug(sm.getString(getStoreName()+".saving",
session.getIdInternal(), file.getAbsolutePath()));
}
FileOutputStream fos = null;
ObjectOutputStream oos = null;
try {
fos = new FileOutputStream(file.getAbsolutePath());
oos = new ObjectOutputStream(new BufferedOutputStream(fos));
} catch (IOException e) {
if (fos != null) {
try {
fos.close();
} catch (IOException f) {
// Ignore
}
}
throw e;
}
try {
((StandardSession)session).writeObjectData(oos);
} finally {
oos.close();
}
}
// in java/org/apache/catalina/session/FileStore.java
private File directory() throws IOException {
if (this.directory == null) {
return (null);
}
if (this.directoryFile != null) {
// NOTE: Race condition is harmless, so do not synchronize
return (this.directoryFile);
}
File file = new File(this.directory);
if (!file.isAbsolute()) {
Container container = manager.getContainer();
if (container instanceof Context) {
ServletContext servletContext =
((Context) container).getServletContext();
File work = (File)
servletContext.getAttribute(ServletContext.TEMPDIR);
file = new File(work, this.directory);
} else {
throw new IllegalArgumentException
("Parent Container is not a Context");
}
}
if (!file.exists() || !file.isDirectory()) {
if (!file.delete() && file.exists()) {
throw new IOException(
sm.getString("fileStore.deleteFailed", file));
}
if (!file.mkdirs() && !file.isDirectory()) {
throw new IOException(
sm.getString("fileStore.createFailed", file));
}
}
this.directoryFile = file;
return (file);
}
// in java/org/apache/catalina/session/FileStore.java
private File file(String id) throws IOException {
if (this.directory == null) {
return (null);
}
String filename = id + FILE_EXT;
File file = new File(directory(), filename);
return (file);
}
// in java/org/apache/catalina/session/PersistentManagerBase.java
Override
public Session findSession(String id) throws IOException {
Session session = super.findSession(id);
// OK, at this point, we're not sure if another thread is trying to
// remove the session or not so the only way around this is to lock it
// (or attempt to) and then try to get it by this session id again. If
// the other code ran swapOut, then we should get a null back during
// this run, and if not, we lock it out so we can access the session
// safely.
if(session != null) {
synchronized(session){
session = super.findSession(session.getIdInternal());
if(session != null){
// To keep any external calling code from messing up the
// concurrency.
session.access();
session.endAccess();
}
}
}
if (session != null)
return (session);
// See if the Session is in the Store
session = swapIn(id);
return (session);
}
// in java/org/apache/catalina/session/PersistentManagerBase.java
protected Session swapIn(String id) throws IOException {
if (store == null)
return null;
Object swapInLock = null;
/*
* The purpose of this sync and these locks is to make sure that a
* session is only loaded once. It doesn't matter if the lock is removed
* and then another thread enters this method and tries to load the same
* session. That thread will re-create a swapIn lock for that session,
* quickly find that the session is already in sessions, use it and
* carry on.
*/
synchronized (this) {
swapInLock = sessionSwapInLocks.get(id);
if (swapInLock == null) {
swapInLock = new Object();
sessionSwapInLocks.put(id, swapInLock);
}
}
Session session = null;
synchronized (swapInLock) {
// First check to see if another thread has loaded the session into
// the manager
session = sessions.get(id);
if (session == null) {
try {
if (SecurityUtil.isPackageProtectionEnabled()){
try {
session = AccessController.doPrivileged(
new PrivilegedStoreLoad(id));
} catch (PrivilegedActionException ex) {
Exception e = ex.getException();
log.error(sm.getString(
"persistentManager.swapInException", id),
e);
if (e instanceof IOException){
throw (IOException)e;
} else if (e instanceof ClassNotFoundException) {
throw (ClassNotFoundException)e;
}
}
} else {
session = store.load(id);
}
} catch (ClassNotFoundException e) {
String msg = sm.getString(
"persistentManager.deserializeError", id);
log.error(msg, e);
throw new IllegalStateException(msg, e);
}
if (session != null && !session.isValid()) {
log.error(sm.getString(
"persistentManager.swapInInvalid", id));
session.expire();
removeSession(id);
session = null;
}
if (session != null) {
if(log.isDebugEnabled())
log.debug(sm.getString("persistentManager.swapIn", id));
session.setManager(this);
// make sure the listeners know about it.
((StandardSession)session).tellNew();
add(session);
((StandardSession)session).activate();
// endAccess() to ensure timeouts happen correctly.
// access() to keep access count correct or it will end up
// negative
session.access();
session.endAccess();
}
}
}
// Make sure the lock is removed
synchronized (this) {
sessionSwapInLocks.remove(id);
}
return (session);
}
// in java/org/apache/catalina/session/PersistentManagerBase.java
protected void swapOut(Session session) throws IOException {
if (store == null || !session.isValid()) {
return;
}
((StandardSession)session).passivate();
writeSession(session);
super.remove(session, true);
session.recycle();
}
// in java/org/apache/catalina/session/PersistentManagerBase.java
protected void writeSession(Session session) throws IOException {
if (store == null || !session.isValid()) {
return;
}
try {
if (SecurityUtil.isPackageProtectionEnabled()){
try{
AccessController.doPrivileged(new PrivilegedStoreSave(session));
}catch(PrivilegedActionException ex){
Exception exception = ex.getException();
if (exception instanceof IOException) {
throw (IOException) exception;
}
log.error("Exception in the Store during writeSession: "
+ exception, exception);
}
} else {
store.save(session);
}
} catch (IOException e) {
log.error(sm.getString
("persistentManager.serializeError", session.getIdInternal(), e));
throw e;
}
}
// in java/org/apache/catalina/session/StandardSession.java
public void readObjectData(ObjectInputStream stream)
throws ClassNotFoundException, IOException {
readObject(stream);
}
// in java/org/apache/catalina/session/StandardSession.java
public void writeObjectData(ObjectOutputStream stream)
throws IOException {
writeObject(stream);
}
// in java/org/apache/catalina/session/StandardSession.java
protected void readObject(ObjectInputStream stream)
throws ClassNotFoundException, IOException {
// Deserialize the scalar instance variables (except Manager)
authType = null; // Transient only
creationTime = ((Long) stream.readObject()).longValue();
lastAccessedTime = ((Long) stream.readObject()).longValue();
maxInactiveInterval = ((Integer) stream.readObject()).intValue();
isNew = ((Boolean) stream.readObject()).booleanValue();
isValid = ((Boolean) stream.readObject()).booleanValue();
thisAccessedTime = ((Long) stream.readObject()).longValue();
principal = null; // Transient only
// setId((String) stream.readObject());
id = (String) stream.readObject();
if (manager.getContainer().getLogger().isDebugEnabled())
manager.getContainer().getLogger().debug
("readObject() loading session " + id);
// Deserialize the attribute count and attribute values
if (attributes == null)
attributes = new ConcurrentHashMap<String, Object>();
int n = ((Integer) stream.readObject()).intValue();
boolean isValidSave = isValid;
isValid = true;
for (int i = 0; i < n; i++) {
String name = (String) stream.readObject();
Object value = stream.readObject();
if ((value instanceof String) && (value.equals(NOT_SERIALIZED)))
continue;
if (manager.getContainer().getLogger().isDebugEnabled())
manager.getContainer().getLogger().debug(" loading attribute '" + name +
"' with value '" + value + "'");
attributes.put(name, value);
}
isValid = isValidSave;
if (listeners == null) {
listeners = new ArrayList<SessionListener>();
}
if (notes == null) {
notes = new Hashtable<String, Object>();
}
}
// in java/org/apache/catalina/session/StandardSession.java
protected void writeObject(ObjectOutputStream stream) throws IOException {
// Write the scalar instance variables (except Manager)
stream.writeObject(Long.valueOf(creationTime));
stream.writeObject(Long.valueOf(lastAccessedTime));
stream.writeObject(Integer.valueOf(maxInactiveInterval));
stream.writeObject(Boolean.valueOf(isNew));
stream.writeObject(Boolean.valueOf(isValid));
stream.writeObject(Long.valueOf(thisAccessedTime));
stream.writeObject(id);
if (manager.getContainer().getLogger().isDebugEnabled())
manager.getContainer().getLogger().debug
("writeObject() storing session " + id);
// Accumulate the names of serializable and non-serializable attributes
String keys[] = keys();
ArrayList<String> saveNames = new ArrayList<String>();
ArrayList<Object> saveValues = new ArrayList<Object>();
for (int i = 0; i < keys.length; i++) {
Object value = attributes.get(keys[i]);
if (value == null)
continue;
else if ( (value instanceof Serializable)
&& (!exclude(keys[i]) )) {
saveNames.add(keys[i]);
saveValues.add(value);
} else {
removeAttributeInternal(keys[i], true);
}
}
// Serialize the attribute count and the Serializable attributes
int n = saveNames.size();
stream.writeObject(Integer.valueOf(n));
for (int i = 0; i < n; i++) {
stream.writeObject(saveNames.get(i));
try {
stream.writeObject(saveValues.get(i));
if (manager.getContainer().getLogger().isDebugEnabled())
manager.getContainer().getLogger().debug
(" storing attribute '" + saveNames.get(i) +
"' with value '" + saveValues.get(i) + "'");
} catch (NotSerializableException e) {
manager.getContainer().getLogger().warn
(sm.getString("standardSession.notSerializable",
saveNames.get(i), id), e);
stream.writeObject(NOT_SERIALIZED);
if (manager.getContainer().getLogger().isDebugEnabled())
manager.getContainer().getLogger().debug
(" storing attribute '" + saveNames.get(i) +
"' with value NOT_SERIALIZED");
}
}
}
// in java/org/apache/catalina/valves/RequestFilterValve.java
protected void process(String property, Request request, Response response)
throws IOException, ServletException {
if (isAllowed(property)) {
getNext().invoke(request, response);
return;
}
// Deny this request
denyRequest(request, response);
}
// in java/org/apache/catalina/valves/RequestFilterValve.java
protected void denyRequest(Request request, Response response)
throws IOException, ServletException {
response.sendError(denyStatus);
}
// in java/org/apache/catalina/valves/RemoteHostValve.java
Override
public void invoke(Request request, Response response)
throws IOException, ServletException {
process(request.getRequest().getRemoteHost(), request, response);
}
// in java/org/apache/catalina/valves/CometConnectionManagerValve.java
Override
public void invoke(Request request, Response response)
throws IOException, ServletException {
// Perform the request
getNext().invoke(request, response);
if (request.isComet() && !response.isClosed()) {
// Start tracking this connection, since this is a
// begin event, and Comet mode is on
HttpSession session = request.getSession(true);
// Track the connection for webapp reload
cometRequests.add(request);
// Track the connection for session expiration
synchronized (session) {
Request[] requests = (Request[])
session.getAttribute(cometRequestsAttribute);
if (requests == null) {
requests = new Request[1];
requests[0] = request;
session.setAttribute(cometRequestsAttribute,
requests);
} else {
Request[] newRequests =
new Request[requests.length + 1];
for (int i = 0; i < requests.length; i++) {
newRequests[i] = requests[i];
}
newRequests[requests.length] = request;
session.setAttribute(cometRequestsAttribute, newRequests);
}
}
}
}
// in java/org/apache/catalina/valves/CometConnectionManagerValve.java
Override
public void event(Request request, Response response, CometEvent event)
throws IOException, ServletException {
// Perform the request
boolean ok = false;
try {
getNext().event(request, response, event);
ok = true;
} finally {
if (!ok || response.isClosed()
|| (event.getEventType() == CometEvent.EventType.END)
|| (event.getEventType() == CometEvent.EventType.ERROR
&& !(event.getEventSubType() ==
CometEvent.EventSubType.TIMEOUT))) {
// Remove the connection from webapp reload tracking
cometRequests.remove(request);
// Remove connection from session expiration tracking
// Note: can't get the session if it has been invalidated but
// OK since session listener will have done clean-up
HttpSession session = request.getSession(false);
if (session != null) {
synchronized (session) {
Request[] reqs = null;
try {
reqs = (Request[])
session.getAttribute(cometRequestsAttribute);
} catch (IllegalStateException ise) {
// Ignore - session has been invalidated
// Listener will have cleaned up
}
if (reqs != null) {
boolean found = false;
for (int i = 0; !found && (i < reqs.length); i++) {
found = (reqs[i] == request);
}
if (found) {
if (reqs.length > 1) {
Request[] newConnectionInfos =
new Request[reqs.length - 1];
int pos = 0;
for (int i = 0; i < reqs.length; i++) {
if (reqs[i] != request) {
newConnectionInfos[pos++] = reqs[i];
}
}
try {
session.setAttribute(
cometRequestsAttribute,
newConnectionInfos);
} catch (IllegalStateException ise) {
// Ignore - session has been invalidated
// Listener will have cleaned up
}
} else {
try {
session.removeAttribute(
cometRequestsAttribute);
} catch (IllegalStateException ise) {
// Ignore - session has been invalidated
// Listener will have cleaned up
}
}
}
}
}
}
}
}
}
// in java/org/apache/catalina/valves/CrawlerSessionManagerValve.java
Override
public void invoke(Request request, Response response) throws IOException,
ServletException {
boolean isBot = false;
String sessionId = null;
String clientIp = null;
if (log.isDebugEnabled()) {
log.debug(request.hashCode() + ": ClientIp=" +
request.getRemoteAddr() + ", RequestedSessionId=" +
request.getRequestedSessionId());
}
// If the incoming request has a valid session ID, no action is required
if (request.getSession(false) == null) {
// Is this a crawler - check the UA headers
Enumeration<String> uaHeaders = request.getHeaders("user-agent");
String uaHeader = null;
if (uaHeaders.hasMoreElements()) {
uaHeader = uaHeaders.nextElement();
}
// If more than one UA header - assume not a bot
if (uaHeader != null && !uaHeaders.hasMoreElements()) {
if (log.isDebugEnabled()) {
log.debug(request.hashCode() + ": UserAgent=" + uaHeader);
}
if (uaPattern.matcher(uaHeader).matches()) {
isBot = true;
if (log.isDebugEnabled()) {
log.debug(request.hashCode() +
": Bot found. UserAgent=" + uaHeader);
}
}
}
// If this is a bot, is the session ID known?
if (isBot) {
clientIp = request.getRemoteAddr();
sessionId = clientIpSessionId.get(clientIp);
if (sessionId != null) {
request.setRequestedSessionId(sessionId);
if (log.isDebugEnabled()) {
log.debug(request.hashCode() + ": SessionID=" +
sessionId);
}
}
}
}
getNext().invoke(request, response);
if (isBot) {
if (sessionId == null) {
// Has bot just created a session, if so make a note of it
HttpSession s = request.getSession(false);
if (s != null) {
clientIpSessionId.put(clientIp, s.getId());
sessionIdClientIp.put(s.getId(), clientIp);
// #valueUnbound() will be called on session expiration
s.setAttribute(this.getClass().getName(), this);
s.setMaxInactiveInterval(sessionInactiveInterval);
if (log.isDebugEnabled()) {
log.debug(request.hashCode() +
": New bot session. SessionID=" + s.getId());
}
}
} else {
if (log.isDebugEnabled()) {
log.debug(request.hashCode() +
": Bot session accessed. SessionID=" + sessionId);
}
}
}
}
// in java/org/apache/catalina/valves/RemoteAddrValve.java
Override
public void invoke(Request request, Response response)
throws IOException, ServletException {
process(request.getRequest().getRemoteAddr(), request, response);
}
// in java/org/apache/catalina/valves/JDBCAccessLogValve.java
Override
public void invoke(Request request, Response response) throws IOException,
ServletException {
getNext().invoke(request, response);
}
// in java/org/apache/catalina/valves/StuckThreadDetectionValve.java
Override
public void invoke(Request request, Response response)
throws IOException, ServletException {
if (threshold <= 0) {
// short-circuit if not monitoring stuck threads
getNext().invoke(request, response);
return;
}
// Save the thread/runnable
// Keeping a reference to the thread object here does not prevent
// GC'ing, as the reference is removed from the Map in the finally clause
Long key = Long.valueOf(Thread.currentThread().getId());
StringBuffer requestUrl = request.getRequestURL();
if(request.getQueryString()!=null) {
requestUrl.append("?");
requestUrl.append(request.getQueryString());
}
MonitoredThread monitoredThread = new MonitoredThread(Thread.currentThread(),
requestUrl.toString());
activeThreads.put(key, monitoredThread);
try {
getNext().invoke(request, response);
} finally {
activeThreads.remove(key);
if (monitoredThread.markAsDone() == MonitoredThreadState.STUCK) {
completedStuckThreadsQueue.add(
new CompletedStuckThread(monitoredThread.getThread().getName(),
monitoredThread.getActiveTimeInMillis()));
}
}
}
// in java/org/apache/catalina/valves/SSLValve.java
Override
public void invoke(Request request, Response response)
throws IOException, ServletException {
/* mod_header converts the '\n' into ' ' so we have to rebuild the client certificate */
String strcert0 = mygetHeader(request, "ssl_client_cert");
if (strcert0 != null && strcert0.length()>28) {
String strcert1 = strcert0.replace(' ', '\n');
String strcert2 = strcert1.substring(28, strcert1.length()-26);
String strcert3 = "-----BEGIN CERTIFICATE-----\n";
String strcert4 = strcert3.concat(strcert2);
String strcerts = strcert4.concat("\n-----END CERTIFICATE-----\n");
// ByteArrayInputStream bais = new ByteArrayInputStream(strcerts.getBytes("UTF-8"));
ByteArrayInputStream bais = new ByteArrayInputStream(
strcerts.getBytes(B2CConverter.ISO_8859_1));
X509Certificate jsseCerts[] = null;
String providerName = (String) request.getConnector().getProperty(
"clientCertProvider");
try {
CertificateFactory cf;
if (providerName == null) {
cf = CertificateFactory.getInstance("X.509");
} else {
cf = CertificateFactory.getInstance("X.509", providerName);
}
X509Certificate cert = (X509Certificate) cf.generateCertificate(bais);
jsseCerts = new X509Certificate[1];
jsseCerts[0] = cert;
} catch (java.security.cert.CertificateException e) {
log.warn(sm.getString("sslValve.certError", strcerts), e);
} catch (NoSuchProviderException e) {
log.error(sm.getString(
"sslValve.invalidProvider", providerName), e);
}
request.setAttribute(Globals.CERTIFICATES_ATTR, jsseCerts);
}
strcert0 = mygetHeader(request, "ssl_cipher");
if (strcert0 != null) {
request.setAttribute(Globals.CIPHER_SUITE_ATTR, strcert0);
}
strcert0 = mygetHeader(request, "ssl_session_id");
if (strcert0 != null) {
request.setAttribute(Globals.SSL_SESSION_ID_ATTR, strcert0);
}
strcert0 = mygetHeader(request, "ssl_cipher_usekeysize");
if (strcert0 != null) {
request.setAttribute(Globals.KEY_SIZE_ATTR,
Integer.valueOf(strcert0));
}
getNext().invoke(request, response);
}
// in java/org/apache/catalina/valves/ErrorReportValve.java
Override
public void invoke(Request request, Response response)
throws IOException, ServletException {
// Perform the request
getNext().invoke(request, response);
if (response.isCommitted()) {
return;
}
Throwable throwable =
(Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
if (request.isAsyncStarted() && response.getStatus() < 400 &&
throwable == null) {
return;
}
if (throwable != null) {
// The response is an error
response.setError();
// Reset the response (if possible)
try {
response.reset();
} catch (IllegalStateException e) {
// Ignore
}
response.sendError
(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
response.setSuspended(false);
try {
report(request, response, throwable);
} catch (Throwable tt) {
ExceptionUtils.handleThrowable(tt);
}
if (request.isAsyncStarted()) {
request.getAsyncContext().complete();
}
}
// in java/org/apache/catalina/valves/SemaphoreValve.java
Override
public void invoke(Request request, Response response)
throws IOException, ServletException {
if (controlConcurrency(request, response)) {
boolean shouldRelease = true;
try {
if (block) {
if (interruptible) {
try {
semaphore.acquire();
} catch (InterruptedException e) {
shouldRelease = false;
permitDenied(request, response);
return;
}
} else {
semaphore.acquireUninterruptibly();
}
} else {
if (!semaphore.tryAcquire()) {
shouldRelease = false;
permitDenied(request, response);
return;
}
}
getNext().invoke(request, response);
} finally {
if (shouldRelease) {
semaphore.release();
}
}
} else {
getNext().invoke(request, response);
}
}
// in java/org/apache/catalina/valves/SemaphoreValve.java
public void permitDenied(Request request, Response response)
throws IOException, ServletException {
// NO-OP by default
}
// in java/org/apache/catalina/valves/PersistentValve.java
Override
public void invoke(Request request, Response response)
throws IOException, ServletException {
// Select the Context to be used for this Request
Context context = request.getContext();
if (context == null) {
response.sendError
(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
sm.getString("standardHost.noContext"));
return;
}
// Bind the context CL to the current thread
Thread.currentThread().setContextClassLoader
(context.getLoader().getClassLoader());
// Update the session last access time for our session (if any)
String sessionId = request.getRequestedSessionId();
Manager manager = context.getManager();
if (sessionId != null && manager != null) {
if (manager instanceof StoreManager) {
Store store = ((StoreManager) manager).getStore();
if (store != null) {
Session session = null;
try {
session = store.load(sessionId);
} catch (Exception e) {
container.getLogger().error("deserializeError");
}
if (session != null) {
if (!session.isValid() ||
isSessionStale(session, System.currentTimeMillis())) {
if (container.getLogger().isDebugEnabled()) {
container.getLogger().debug("session swapped in is invalid or expired");
}
session.expire();
store.remove(sessionId);
} else {
session.setManager(manager);
// session.setId(sessionId); Only if new ???
manager.add(session);
// ((StandardSession)session).activate();
session.access();
session.endAccess();
}
}
}
}
}
if (container.getLogger().isDebugEnabled()) {
container.getLogger().debug("sessionId: " + sessionId);
}
// Ask the next valve to process the request.
getNext().invoke(request, response);
// If still processing async, don't try to store the session
// TODO: Are there some async states where it is would be safe to store
// the session?
if (!request.isAsync()) {
// Read the sessionid after the response.
// HttpSession hsess = hreq.getSession(false);
Session hsess;
try {
hsess = request.getSessionInternal();
} catch (Exception ex) {
hsess = null;
}
String newsessionId = null;
if (hsess!=null) {
newsessionId = hsess.getIdInternal();
}
if (container.getLogger().isDebugEnabled()) {
container.getLogger().debug("newsessionId: " + newsessionId);
}
if (newsessionId!=null) {
/* store the session and remove it from the manager */
if (manager instanceof StoreManager) {
Session session = manager.findSession(newsessionId);
Store store = ((StoreManager) manager).getStore();
if (store != null && session!=null &&
session.isValid() &&
!isSessionStale(session, System.currentTimeMillis())) {
// ((StandardSession)session).passivate();
store.save(session);
((StoreManager) manager).removeSuper(session);
session.recycle();
} else {
if (container.getLogger().isDebugEnabled()) {
container.getLogger().debug("newsessionId store: " +
store + " session: " + session +
" valid: " +
(session == null ? "N/A" : Boolean.toString(
session.isValid())) +
" stale: " + isSessionStale(session,
System.currentTimeMillis()));
}
}
} else {
if (container.getLogger().isDebugEnabled()) {
container.getLogger().debug("newsessionId Manager: " +
manager);
}
}
}
}
}
// in java/org/apache/catalina/valves/AccessLogValve.java
Override
public void invoke(Request request, Response response) throws IOException,
ServletException {
getNext().invoke(request, response);
}
// in java/org/apache/catalina/valves/RemoteIpValve.java
Override
public void invoke(Request request, Response response) throws IOException, ServletException {
final String originalRemoteAddr = request.getRemoteAddr();
final String originalRemoteHost = request.getRemoteHost();
final String originalScheme = request.getScheme();
final boolean originalSecure = request.isSecure();
final int originalServerPort = request.getServerPort();
if (internalProxies !=null &&
internalProxies.matcher(originalRemoteAddr).matches()) {
String remoteIp = null;
// In java 6, proxiesHeaderValue should be declared as a java.util.Deque
LinkedList<String> proxiesHeaderValue = new LinkedList<String>();
StringBuilder concatRemoteIpHeaderValue = new StringBuilder();
for (Enumeration<String> e = request.getHeaders(remoteIpHeader); e.hasMoreElements();) {
if (concatRemoteIpHeaderValue.length() > 0) {
concatRemoteIpHeaderValue.append(", ");
}
concatRemoteIpHeaderValue.append(e.nextElement());
}
String[] remoteIpHeaderValue = commaDelimitedListToStringArray(concatRemoteIpHeaderValue.toString());
int idx;
// loop on remoteIpHeaderValue to find the first trusted remote ip and to build the proxies chain
for (idx = remoteIpHeaderValue.length - 1; idx >= 0; idx--) {
String currentRemoteIp = remoteIpHeaderValue[idx];
remoteIp = currentRemoteIp;
if (internalProxies.matcher(currentRemoteIp).matches()) {
// do nothing, internalProxies IPs are not appended to the
} else if (trustedProxies != null &&
trustedProxies.matcher(currentRemoteIp).matches()) {
proxiesHeaderValue.addFirst(currentRemoteIp);
} else {
idx--; // decrement idx because break statement doesn't do it
break;
}
}
// continue to loop on remoteIpHeaderValue to build the new value of the remoteIpHeader
LinkedList<String> newRemoteIpHeaderValue = new LinkedList<String>();
for (; idx >= 0; idx--) {
String currentRemoteIp = remoteIpHeaderValue[idx];
newRemoteIpHeaderValue.addFirst(currentRemoteIp);
}
if (remoteIp != null) {
request.setRemoteAddr(remoteIp);
request.setRemoteHost(remoteIp);
// use request.coyoteRequest.mimeHeaders.setValue(str).setString(str) because request.addHeader(str, str) is no-op in Tomcat
// 6.0
if (proxiesHeaderValue.size() == 0) {
request.getCoyoteRequest().getMimeHeaders().removeHeader(proxiesHeader);
} else {
String commaDelimitedListOfProxies = listToCommaDelimitedString(proxiesHeaderValue);
request.getCoyoteRequest().getMimeHeaders().setValue(proxiesHeader).setString(commaDelimitedListOfProxies);
}
if (newRemoteIpHeaderValue.size() == 0) {
request.getCoyoteRequest().getMimeHeaders().removeHeader(remoteIpHeader);
} else {
String commaDelimitedRemoteIpHeaderValue = listToCommaDelimitedString(newRemoteIpHeaderValue);
request.getCoyoteRequest().getMimeHeaders().setValue(remoteIpHeader).setString(commaDelimitedRemoteIpHeaderValue);
}
}
if (protocolHeader != null) {
String protocolHeaderValue = request.getHeader(protocolHeader);
if (protocolHeaderValue == null) {
// don't modify the secure,scheme and serverPort attributes
// of the request
} else if (protocolHeaderHttpsValue.equalsIgnoreCase(protocolHeaderValue)) {
request.setSecure(true);
// use request.coyoteRequest.scheme instead of request.setScheme() because request.setScheme() is no-op in Tomcat 6.0
request.getCoyoteRequest().scheme().setString("https");
setPorts(request, httpsServerPort);
} else {
request.setSecure(false);
// use request.coyoteRequest.scheme instead of request.setScheme() because request.setScheme() is no-op in Tomcat 6.0
request.getCoyoteRequest().scheme().setString("http");
setPorts(request, httpServerPort);
}
}
if (log.isDebugEnabled()) {
log.debug("Incoming request " + request.getRequestURI() + " with originalRemoteAddr '" + originalRemoteAddr
+ "', originalRemoteHost='" + originalRemoteHost + "', originalSecure='" + originalSecure + "', originalScheme='"
+ originalScheme + "' will be seen as newRemoteAddr='" + request.getRemoteAddr() + "', newRemoteHost='"
+ request.getRemoteHost() + "', newScheme='" + request.getScheme() + "', newSecure='" + request.isSecure() + "'");
}
} else {
if (log.isDebugEnabled()) {
log.debug("Skip RemoteIpValve for request " + request.getRequestURI() + " with originalRemoteAddr '"
+ request.getRemoteAddr() + "'");
}
}
if (requestAttributesEnabled) {
request.setAttribute(AccessLog.REMOTE_ADDR_ATTRIBUTE,
request.getRemoteAddr());
request.setAttribute(AccessLog.REMOTE_HOST_ATTRIBUTE,
request.getRemoteHost());
request.setAttribute(AccessLog.PROTOCOL_ATTRIBUTE,
request.getProtocol());
request.setAttribute(AccessLog.SERVER_PORT_ATTRIBUTE,
Integer.valueOf(request.getServerPort()));
}
try {
getNext().invoke(request, response);
} finally {
request.setRemoteAddr(originalRemoteAddr);
request.setRemoteHost(originalRemoteHost);
request.setSecure(originalSecure);
// use request.coyoteRequest.scheme instead of request.setScheme() because request.setScheme() is no-op in Tomcat 6.0
request.getCoyoteRequest().scheme().setString(originalScheme);
request.setServerPort(originalServerPort);
}
}
// in java/org/apache/catalina/valves/ValveBase.java
Override
public void event(Request request, Response response, CometEvent event)
throws IOException, ServletException {
// Perform the request
getNext().event(request, response, event);
}
// in java/org/apache/catalina/valves/ExtendedAccessLogValve.java
public String getToken() throws IOException {
if(ended) {
return null ;
}
String result = null;
subToken = false;
parameter = false;
int c = sr.read();
while (c != -1) {
switch (c) {
case ' ':
result = buf.toString();
buf = new StringBuilder();
buf.append((char) c);
return result;
case '-':
result = buf.toString();
buf = new StringBuilder();
subToken = true;
return result;
case '(':
result = buf.toString();
buf = new StringBuilder();
parameter = true;
return result;
case ')':
result = buf.toString();
buf = new StringBuilder();
break;
default:
buf.append((char) c);
}
c = sr.read();
}
ended = true;
if (buf.length() != 0) {
return buf.toString();
} else {
return null;
}
}
// in java/org/apache/catalina/valves/ExtendedAccessLogValve.java
public String getParameter()throws IOException {
String result;
if (!parameter) {
return null;
}
parameter = false;
int c = sr.read();
while (c != -1) {
if (c == ')') {
result = buf.toString();
buf = new StringBuilder();
return result;
}
buf.append((char) c);
c = sr.read();
}
return null;
}
// in java/org/apache/catalina/valves/ExtendedAccessLogValve.java
public String getWhiteSpaces() throws IOException {
if(isEnded()) {
return "" ;
}
StringBuilder whiteSpaces = new StringBuilder();
if (buf.length() > 0) {
whiteSpaces.append(buf);
buf = new StringBuilder();
}
int c = sr.read();
while (Character.isWhitespace((char) c)) {
whiteSpaces.append((char) c);
c = sr.read();
}
if (c == -1) {
ended = true;
} else {
buf.append((char) c);
}
return whiteSpaces.toString();
}
// in java/org/apache/catalina/valves/ExtendedAccessLogValve.java
public String getRemains() throws IOException {
StringBuilder remains = new StringBuilder();
for(int c = sr.read(); c != -1; c = sr.read()) {
remains.append((char) c);
}
return remains.toString();
}
// in java/org/apache/catalina/valves/ExtendedAccessLogValve.java
protected AccessLogElement getLogElement(String token, PatternTokenizer tokenizer) throws IOException {
if ("date".equals(token)) {
return new DateElement();
} else if ("time".equals(token)) {
if (tokenizer.hasSubToken()) {
String nextToken = tokenizer.getToken();
if ("taken".equals(nextToken)) {
return new ElapsedTimeElement(false);
}
} else {
return new TimeElement();
}
} else if ("bytes".equals(token)) {
return new ByteSentElement(true);
} else if ("cached".equals(token)) {
/* I don't know how to evaluate this! */
return new StringElement("-");
} else if ("c".equals(token)) {
String nextToken = tokenizer.getToken();
if ("ip".equals(nextToken)) {
return new RemoteAddrElement();
} else if ("dns".equals(nextToken)) {
return new HostElement();
}
} else if ("s".equals(token)) {
String nextToken = tokenizer.getToken();
if ("ip".equals(nextToken)) {
return new LocalAddrElement();
} else if ("dns".equals(nextToken)) {
return new AccessLogElement() {
@Override
public void addElement(StringBuilder buf, Date date,
Request request, Response response, long time) {
String value;
try {
value = InetAddress.getLocalHost().getHostName();
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
value = "localhost";
}
buf.append(value);
}
};
}
} else if ("cs".equals(token)) {
return getClientToServerElement(tokenizer);
} else if ("sc".equals(token)) {
return getServerToClientElement(tokenizer);
} else if ("sr".equals(token) || "rs".equals(token)) {
return getProxyElement(tokenizer);
} else if ("x".equals(token)) {
return getXParameterElement(tokenizer);
}
log.error("unable to decode with rest of chars starting: " + token);
return null;
}
// in java/org/apache/catalina/valves/ExtendedAccessLogValve.java
protected AccessLogElement getClientToServerElement(
PatternTokenizer tokenizer) throws IOException {
if (tokenizer.hasSubToken()) {
String token = tokenizer.getToken();
if ("method".equals(token)) {
return new MethodElement();
} else if ("uri".equals(token)) {
if (tokenizer.hasSubToken()) {
token = tokenizer.getToken();
if ("stem".equals(token)) {
return new RequestURIElement();
} else if ("query".equals(token)) {
return new AccessLogElement() {
@Override
public void addElement(StringBuilder buf, Date date,
Request request, Response response,
long time) {
String query = request.getQueryString();
if (query != null) {
buf.append(query);
} else {
buf.append('-');
}
}
};
}
} else {
return new AccessLogElement() {
@Override
public void addElement(StringBuilder buf, Date date,
Request request, Response response, long time) {
String query = request.getQueryString();
if (query == null) {
buf.append(request.getRequestURI());
} else {
buf.append(request.getRequestURI());
buf.append('?');
buf.append(request.getQueryString());
}
}
};
}
}
} else if (tokenizer.hasParameter()) {
String parameter = tokenizer.getParameter();
if (parameter == null) {
log.error("No closing ) found for in decode");
return null;
}
return new RequestHeaderElement(parameter);
}
log.error("The next characters couldn't be decoded: "
+ tokenizer.getRemains());
return null;
}
// in java/org/apache/catalina/valves/ExtendedAccessLogValve.java
protected AccessLogElement getServerToClientElement(
PatternTokenizer tokenizer) throws IOException {
if (tokenizer.hasSubToken()) {
String token = tokenizer.getToken();
if ("status".equals(token)) {
return new HttpStatusCodeElement();
} else if ("comment".equals(token)) {
return new StringElement("?");
}
} else if (tokenizer.hasParameter()) {
String parameter = tokenizer.getParameter();
if (parameter == null) {
log.error("No closing ) found for in decode");
return null;
}
return new ResponseHeaderElement(parameter);
}
log.error("The next characters couldn't be decoded: "
+ tokenizer.getRemains());
return null;
}
// in java/org/apache/catalina/valves/ExtendedAccessLogValve.java
protected AccessLogElement getProxyElement(PatternTokenizer tokenizer)
throws IOException {
String token = null;
if (tokenizer.hasSubToken()) {
tokenizer.getToken();
return new StringElement("-");
} else if (tokenizer.hasParameter()) {
tokenizer.getParameter();
return new StringElement("-");
}
log.error("The next characters couldn't be decoded: " + token);
return null;
}
// in java/org/apache/catalina/valves/ExtendedAccessLogValve.java
protected AccessLogElement getXParameterElement(PatternTokenizer tokenizer)
throws IOException {
if (!tokenizer.hasSubToken()) {
log.error("x param in wrong format. Needs to be 'x-#(...)' read the docs!");
return null;
}
String token = tokenizer.getToken();
if ("threadname".equals(token)) {
return new ThreadNameElement();
}
if (!tokenizer.hasParameter()) {
log.error("x param in wrong format. Needs to be 'x-#(...)' read the docs!");
return null;
}
String parameter = tokenizer.getParameter();
if (parameter == null) {
log.error("No closing ) found for in decode");
return null;
}
if ("A".equals(token)) {
return new ServletContextElement(parameter);
} else if ("C".equals(token)) {
return new CookieElement(parameter);
} else if ("R".equals(token)) {
return new RequestAttributeElement(parameter);
} else if ("S".equals(token)) {
return new SessionAttributeElement(parameter);
} else if ("H".equals(token)) {
return getServletRequestElement(parameter);
} else if ("P".equals(token)) {
return new RequestParameterElement(parameter);
} else if ("O".equals(token)) {
return new ResponseAllHeaderElement(parameter);
}
log.error("x param for servlet request, couldn't decode value: "
+ token);
return null;
}
// in java/org/apache/catalina/authenticator/SingleSignOn.java
Override
public void invoke(Request request, Response response)
throws IOException, ServletException {
request.removeNote(Constants.REQ_SSOID_NOTE);
// Has a valid user already been authenticated?
if (containerLog.isDebugEnabled()) {
containerLog.debug("Process request for '" + request.getRequestURI() + "'");
}
if (request.getUserPrincipal() != null) {
if (containerLog.isDebugEnabled()) {
containerLog.debug(" Principal '" + request.getUserPrincipal().getName() +
"' has already been authenticated");
}
getNext().invoke(request, response);
return;
}
// Check for the single sign on cookie
if (containerLog.isDebugEnabled()) {
containerLog.debug(" Checking for SSO cookie");
}
Cookie cookie = null;
Cookie cookies[] = request.getCookies();
if (cookies == null) {
cookies = new Cookie[0];
}
for (int i = 0; i < cookies.length; i++) {
if (Constants.SINGLE_SIGN_ON_COOKIE.equals(cookies[i].getName())) {
cookie = cookies[i];
break;
}
}
if (cookie == null) {
if (containerLog.isDebugEnabled()) {
containerLog.debug(" SSO cookie is not present");
}
getNext().invoke(request, response);
return;
}
// Look up the cached Principal associated with this cookie value
if (containerLog.isDebugEnabled()) {
containerLog.debug(" Checking for cached principal for " + cookie.getValue());
}
SingleSignOnEntry entry = lookup(cookie.getValue());
if (entry != null) {
if (containerLog.isDebugEnabled()) {
containerLog.debug(" Found cached principal '" +
(entry.getPrincipal() != null ? entry.getPrincipal().getName() : "") + "' with auth type '" +
entry.getAuthType() + "'");
}
request.setNote(Constants.REQ_SSOID_NOTE, cookie.getValue());
// Only set security elements if reauthentication is not required
if (!getRequireReauthentication()) {
request.setAuthType(entry.getAuthType());
request.setUserPrincipal(entry.getPrincipal());
}
} else {
if (containerLog.isDebugEnabled()) {
containerLog.debug(" No cached principal found, erasing SSO cookie");
}
cookie.setMaxAge(0);
response.addCookie(cookie);
}
// Invoke the next Valve in our pipeline
getNext().invoke(request, response);
}
// in java/org/apache/catalina/authenticator/SSLAuthenticator.java
Override
public boolean authenticate(Request request, HttpServletResponse response)
throws IOException {
// Have we already authenticated someone?
Principal principal = request.getUserPrincipal();
//String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE);
if (principal != null) {
if (containerLog.isDebugEnabled()) {
containerLog.debug("Already authenticated '" + principal.getName() + "'");
}
// Associate the session with any existing SSO session in order
// to get coordinated session invalidation at logout
String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE);
if (ssoId != null) {
associate(ssoId, request.getSessionInternal(true));
}
return (true);
}
// NOTE: We don't try to reauthenticate using any existing SSO session,
// because that will only work if the original authentication was
// BASIC or FORM, which are less secure than the CLIENT_CERT auth-type
// specified for this webapp
//
// Uncomment below to allow previous FORM or BASIC authentications
// to authenticate users for this webapp
// TODO make this a configurable attribute (in SingleSignOn??)
/*
// Is there an SSO session against which we can try to reauthenticate?
if (ssoId != null) {
if (log.isDebugEnabled())
log.debug("SSO Id " + ssoId + " set; attempting " +
"reauthentication");
// Try to reauthenticate using data cached by SSO. If this fails,
// either the original SSO logon was of DIGEST or SSL (which
// we can't reauthenticate ourselves because there is no
// cached username and password), or the realm denied
// the user's reauthentication for some reason.
// In either case we have to prompt the user for a logon
if (reauthenticateFromSSO(ssoId, request))
return true;
}
*/
// Retrieve the certificate chain for this client
if (containerLog.isDebugEnabled()) {
containerLog.debug(" Looking up certificates");
}
X509Certificate certs[] = (X509Certificate[])
request.getAttribute(Globals.CERTIFICATES_ATTR);
if ((certs == null) || (certs.length < 1)) {
try {
request.getCoyoteRequest().action
(ActionCode.REQ_SSL_CERTIFICATE, null);
} catch (IllegalStateException ise) {
// Request body was too large for save buffer
response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
sm.getString("authenticator.certificates"));
return false;
}
certs = (X509Certificate[])
request.getAttribute(Globals.CERTIFICATES_ATTR);
}
if ((certs == null) || (certs.length < 1)) {
if (containerLog.isDebugEnabled()) {
containerLog.debug(" No certificates included with this request");
}
response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
sm.getString("authenticator.certificates"));
return (false);
}
// Authenticate the specified certificate chain
principal = context.getRealm().authenticate(certs);
if (principal == null) {
if (containerLog.isDebugEnabled()) {
containerLog.debug(" Realm.authenticate() returned false");
}
response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
sm.getString("authenticator.unauthorized"));
return (false);
}
// Cache the principal (if requested) and record this authentication
register(request, response, principal,
HttpServletRequest.CLIENT_CERT_AUTH, null, null);
return (true);
}
// in java/org/apache/catalina/authenticator/NonLoginAuthenticator.java
Override
public boolean authenticate(Request request, HttpServletResponse response)
throws IOException {
Principal principal = request.getPrincipal();
if (principal != null) {
// excellent... we have already authenticated the client somehow,
// probably from another container that has a login-config
if (containerLog.isDebugEnabled())
containerLog.debug("Already authenticated as '"
+ principal.getName() + "'");
if (cache) {
// create a new session (only if necessary)
Session session = request.getSessionInternal(true);
// save the inherited Principal (if necessary) in this
// session so it can remain authenticated until it expires
session.setPrincipal(principal);
// is there an SSO session cookie?
String ssoId =
(String) request.getNote(Constants.REQ_SSOID_NOTE);
if (ssoId != null) {
if (containerLog.isDebugEnabled())
containerLog.debug("User authenticated by existing SSO");
// Associate session with the existing SSO ID if necessary
associate(ssoId, session);
}
}
// user was already authenticated, with or without a cookie
return true;
}
// No Principal means the user is not already authenticated
// and so will not be assigned any roles. It is safe to
// to say the user is now authenticated because access to
// protected resources will only be allowed with a matching role.
// i.e. SC_FORBIDDEN (403 status) will be generated later.
if (containerLog.isDebugEnabled())
containerLog.debug("User authenticated without any roles");
return true;
}
// in java/org/apache/catalina/authenticator/AuthenticatorBase.java
Override
public void invoke(Request request, Response response)
throws IOException, ServletException {
if (log.isDebugEnabled()) {
log.debug("Security checking request " +
request.getMethod() + " " + request.getRequestURI());
}
// Have we got a cached authenticated Principal to record?
if (cache) {
Principal principal = request.getUserPrincipal();
if (principal == null) {
Session session = request.getSessionInternal(false);
if (session != null) {
principal = session.getPrincipal();
if (principal != null) {
if (log.isDebugEnabled()) {
log.debug("We have cached auth type " +
session.getAuthType() +
" for principal " +
session.getPrincipal());
}
request.setAuthType(session.getAuthType());
request.setUserPrincipal(principal);
}
}
}
}
// Special handling for form-based logins to deal with the case
// where the login form (and therefore the "j_security_check" URI
// to which it submits) might be outside the secured area
String contextPath = this.context.getPath();
String requestURI = request.getDecodedRequestURI();
if (requestURI.startsWith(contextPath) &&
requestURI.endsWith(Constants.FORM_ACTION)) {
if (!authenticate(request, response)) {
if (log.isDebugEnabled()) {
log.debug(" Failed authenticate() test ??" + requestURI );
}
return;
}
}
// The Servlet may specify security constraints through annotations.
// Ensure that they have been processed before constraints are checked
Wrapper wrapper = (Wrapper) request.getMappingData().wrapper;
if (wrapper != null) {
wrapper.servletSecurityAnnotationScan();
}
Realm realm = this.context.getRealm();
// Is this request URI subject to a security constraint?
SecurityConstraint [] constraints
= realm.findSecurityConstraints(request, this.context);
if (constraints == null && !context.getPreemptiveAuthentication()) {
if (log.isDebugEnabled()) {
log.debug(" Not subject to any constraint");
}
getNext().invoke(request, response);
return;
}
// Make sure that constrained resources are not cached by web proxies
// or browsers as caching can provide a security hole
if (constraints != null && disableProxyCaching &&
!"POST".equalsIgnoreCase(request.getMethod())) {
if (securePagesWithPragma) {
// Note: These can cause problems with downloading files with IE
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
} else {
response.setHeader("Cache-Control", "private");
}
response.setHeader("Expires", DATE_ONE);
}
int i;
if (constraints != null) {
// Enforce any user data constraint for this security constraint
if (log.isDebugEnabled()) {
log.debug(" Calling hasUserDataPermission()");
}
if (!realm.hasUserDataPermission(request, response,
constraints)) {
if (log.isDebugEnabled()) {
log.debug(" Failed hasUserDataPermission() test");
}
/*
* ASSERT: Authenticator already set the appropriate
* HTTP status code, so we do not have to do anything special
*/
return;
}
}
// Since authenticate modifies the response on failure,
// we have to check for allow-from-all first.
boolean authRequired;
if (constraints == null) {
authRequired = false;
} else {
authRequired = true;
for(i=0; i < constraints.length && authRequired; i++) {
if(!constraints[i].getAuthConstraint()) {
authRequired = false;
} else if(!constraints[i].getAllRoles()) {
String [] roles = constraints[i].findAuthRoles();
if(roles == null || roles.length == 0) {
authRequired = false;
}
}
}
}
if (!authRequired && context.getPreemptiveAuthentication()) {
authRequired =
request.getCoyoteRequest().getMimeHeaders().getValue(
"authorization") != null;
}
if (!authRequired && context.getPreemptiveAuthentication()) {
X509Certificate[] certs = (X509Certificate[]) request.getAttribute(
Globals.CERTIFICATES_ATTR);
authRequired = certs != null && certs.length > 0;
}
if(authRequired) {
if (log.isDebugEnabled()) {
log.debug(" Calling authenticate()");
}
if (!authenticate(request, response)) {
if (log.isDebugEnabled()) {
log.debug(" Failed authenticate() test");
}
/*
* ASSERT: Authenticator already set the appropriate
* HTTP status code, so we do not have to do anything
* special
*/
return;
}
}
if (constraints != null) {
if (log.isDebugEnabled()) {
log.debug(" Calling accessControl()");
}
if (!realm.hasResourcePermission(request, response,
constraints,
this.context)) {
if (log.isDebugEnabled()) {
log.debug(" Failed accessControl() test");
}
/*
* ASSERT: AccessControl method has already set the
* appropriate HTTP status code, so we do not have to do
* anything special
*/
return;
}
}
// Any and all specified constraints have been satisfied
if (log.isDebugEnabled()) {
log.debug(" Successfully passed all security constraints");
}
getNext().invoke(request, response);
}
// in java/org/apache/catalina/authenticator/DigestAuthenticator.java
Override
public boolean authenticate(Request request, HttpServletResponse response)
throws IOException {
// Have we already authenticated someone?
Principal principal = request.getUserPrincipal();
//String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE);
if (principal != null) {
if (log.isDebugEnabled()) {
log.debug("Already authenticated '" + principal.getName() + "'");
}
// Associate the session with any existing SSO session in order
// to get coordinated session invalidation at logout
String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE);
if (ssoId != null) {
associate(ssoId, request.getSessionInternal(true));
}
return (true);
}
// NOTE: We don't try to reauthenticate using any existing SSO session,
// because that will only work if the original authentication was
// BASIC or FORM, which are less secure than the DIGEST auth-type
// specified for this webapp
//
// Uncomment below to allow previous FORM or BASIC authentications
// to authenticate users for this webapp
// TODO make this a configurable attribute (in SingleSignOn??)
/*
// Is there an SSO session against which we can try to reauthenticate?
if (ssoId != null) {
if (log.isDebugEnabled())
log.debug("SSO Id " + ssoId + " set; attempting " +
"reauthentication");
// Try to reauthenticate using data cached by SSO. If this fails,
// either the original SSO logon was of DIGEST or SSL (which
// we can't reauthenticate ourselves because there is no
// cached username and password), or the realm denied
// the user's reauthentication for some reason.
// In either case we have to prompt the user for a logon
if (reauthenticateFromSSO(ssoId, request))
return true;
}
*/
// Validate any credentials already included with this request
String authorization = request.getHeader("authorization");
DigestInfo digestInfo = new DigestInfo(getOpaque(), getNonceValidity(),
getKey(), cnonces, isValidateUri());
if (authorization != null) {
if (digestInfo.validate(request, authorization)) {
principal = digestInfo.authenticate(context.getRealm());
}
if (principal != null) {
String username = parseUsername(authorization);
register(request, response, principal,
HttpServletRequest.DIGEST_AUTH, username, null);
return (true);
}
}
// Send an "unauthorized" response and an appropriate challenge
// Next, generate a nonce token (that is a token which is supposed
// to be unique).
String nonce = generateNonce(request);
setAuthenticateHeader(request, response, nonce,
digestInfo.isNonceStale());
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
// hres.flushBuffer();
return (false);
}
// in java/org/apache/catalina/authenticator/BasicAuthenticator.java
Override
public boolean authenticate(Request request, HttpServletResponse response)
throws IOException {
// Have we already authenticated someone?
Principal principal = request.getUserPrincipal();
String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE);
if (principal != null) {
if (log.isDebugEnabled()) {
log.debug("Already authenticated '" + principal.getName() + "'");
}
// Associate the session with any existing SSO session
if (ssoId != null) {
associate(ssoId, request.getSessionInternal(true));
}
return (true);
}
// Is there an SSO session against which we can try to reauthenticate?
if (ssoId != null) {
if (log.isDebugEnabled()) {
log.debug("SSO Id " + ssoId + " set; attempting " +
"reauthentication");
}
/* Try to reauthenticate using data cached by SSO. If this fails,
either the original SSO logon was of DIGEST or SSL (which
we can't reauthenticate ourselves because there is no
cached username and password), or the realm denied
the user's reauthentication for some reason.
In either case we have to prompt the user for a logon */
if (reauthenticateFromSSO(ssoId, request)) {
return true;
}
}
// Validate any credentials already included with this request
String username = null;
String password = null;
MessageBytes authorization =
request.getCoyoteRequest().getMimeHeaders()
.getValue("authorization");
if (authorization != null) {
authorization.toBytes();
ByteChunk authorizationBC = authorization.getByteChunk();
if (authorizationBC.startsWithIgnoreCase("basic ", 0)) {
authorizationBC.setOffset(authorizationBC.getOffset() + 6);
// FIXME: Add trimming
// authorizationBC.trim();
CharChunk authorizationCC = authorization.getCharChunk();
Base64.decode(authorizationBC, authorizationCC);
// Get username and password
int colon = authorizationCC.indexOf(':');
if (colon < 0) {
username = authorizationCC.toString();
} else {
char[] buf = authorizationCC.getBuffer();
username = new String(buf, 0, colon);
password = new String(buf, colon + 1,
authorizationCC.getEnd() - colon - 1);
}
authorizationBC.setOffset(authorizationBC.getOffset() - 6);
}
principal = context.getRealm().authenticate(username, password);
if (principal != null) {
register(request, response, principal,
HttpServletRequest.BASIC_AUTH, username, password);
return (true);
}
}
StringBuilder value = new StringBuilder(16);
value.append("Basic realm=\"");
value.append(getRealmName(context));
value.append('\"');
response.setHeader(AUTH_HEADER_NAME, value.toString());
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return (false);
}
// in java/org/apache/catalina/authenticator/SpnegoAuthenticator.java
Override
public boolean authenticate(Request request, HttpServletResponse response)
throws IOException {
// Have we already authenticated someone?
Principal principal = request.getUserPrincipal();
String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE);
if (principal != null) {
if (log.isDebugEnabled()) {
log.debug("Already authenticated '" + principal.getName() + "'");
}
// Associate the session with any existing SSO session
if (ssoId != null) {
associate(ssoId, request.getSessionInternal(true));
}
return true;
}
// Is there an SSO session against which we can try to reauthenticate?
if (ssoId != null) {
if (log.isDebugEnabled()) {
log.debug("SSO Id " + ssoId + " set; attempting " +
"reauthentication");
}
/* Try to reauthenticate using data cached by SSO. If this fails,
either the original SSO logon was of DIGEST or SSL (which
we can't reauthenticate ourselves because there is no
cached username and password), or the realm denied
the user's reauthentication for some reason.
In either case we have to prompt the user for a logon */
if (reauthenticateFromSSO(ssoId, request)) {
return true;
}
}
MessageBytes authorization =
request.getCoyoteRequest().getMimeHeaders()
.getValue("authorization");
if (authorization == null) {
if (log.isDebugEnabled()) {
log.debug(sm.getString("authenticator.noAuthHeader"));
}
response.setHeader("WWW-Authenticate", "Negotiate");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return false;
}
authorization.toBytes();
ByteChunk authorizationBC = authorization.getByteChunk();
if (!authorizationBC.startsWithIgnoreCase("negotiate ", 0)) {
if (log.isDebugEnabled()) {
log.debug(sm.getString(
"spnegoAuthenticator.authHeaderNotNego"));
}
response.setHeader("WWW-Authenticate", "Negotiate");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return false;
}
authorizationBC.setOffset(authorizationBC.getOffset() + 10);
// FIXME: Add trimming
// authorizationBC.trim();
ByteChunk decoded = new ByteChunk();
Base64.decode(authorizationBC, decoded);
if (decoded.getLength() == 0) {
if (log.isDebugEnabled()) {
log.debug(sm.getString(
"spnegoAuthenticator.authHeaderNoToken"));
}
response.setHeader("WWW-Authenticate", "Negotiate");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return false;
}
LoginContext lc = null;
GSSContext gssContext = null;
byte[] outToken = null;
try {
try {
lc = new LoginContext(getLoginConfigName());
lc.login();
} catch (LoginException e) {
log.error(sm.getString("spnegoAuthenticator.serviceLoginFail"),
e);
response.sendError(
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return false;
}
// Assume the GSSContext is stateless
// TODO: Confirm this assumption
final GSSManager manager = GSSManager.getInstance();
final PrivilegedExceptionAction<GSSCredential> action =
new PrivilegedExceptionAction<GSSCredential>() {
@Override
public GSSCredential run() throws GSSException {
return manager.createCredential(null,
GSSCredential.DEFAULT_LIFETIME,
new Oid("1.3.6.1.5.5.2"),
GSSCredential.ACCEPT_ONLY);
}
};
gssContext = manager.createContext(Subject.doAs(lc.getSubject(), action));
outToken = gssContext.acceptSecContext(decoded.getBytes(),
decoded.getOffset(), decoded.getLength());
if (outToken == null) {
if (log.isDebugEnabled()) {
log.debug(sm.getString(
"spnegoAuthenticator.ticketValidateFail"));
}
// Start again
response.setHeader("WWW-Authenticate", "Negotiate");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return false;
}
principal = context.getRealm().authenticate(gssContext,
isStoreDelegatedCredential());
} catch (GSSException e) {
if (log.isDebugEnabled()) {
log.debug(sm.getString("spnegoAuthenticator.ticketValidateFail",
e));
}
response.setHeader("WWW-Authenticate", "Negotiate");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return false;
} catch (PrivilegedActionException e) {
log.error(sm.getString("spnegoAuthenticator.serviceLoginFail", e));
response.setHeader("WWW-Authenticate", "Negotiate");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return false;
} finally {
if (gssContext != null) {
try {
gssContext.dispose();
} catch (GSSException e) {
// Ignore
}
}
if (lc != null) {
try {
lc.logout();
} catch (LoginException e) {
// Ignore
}
}
}
// Send response token on success and failure
response.setHeader("WWW-Authenticate", "Negotiate "
+ Base64.encode(outToken));
if (principal != null) {
register(request, response, principal, Constants.SPNEGO_METHOD,
principal.getName(), null);
return true;
}
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return false;
}
// in java/org/apache/catalina/authenticator/FormAuthenticator.java
Override
public boolean authenticate(Request request, HttpServletResponse response)
throws IOException {
// References to objects we will need later
Session session = null;
// Have we already authenticated someone?
Principal principal = request.getUserPrincipal();
String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE);
if (principal != null) {
if (log.isDebugEnabled()) {
log.debug("Already authenticated '" +
principal.getName() + "'");
}
// Associate the session with any existing SSO session
if (ssoId != null) {
associate(ssoId, request.getSessionInternal(true));
}
return (true);
}
// Is there an SSO session against which we can try to reauthenticate?
if (ssoId != null) {
if (log.isDebugEnabled()) {
log.debug("SSO Id " + ssoId + " set; attempting " +
"reauthentication");
}
// Try to reauthenticate using data cached by SSO. If this fails,
// either the original SSO logon was of DIGEST or SSL (which
// we can't reauthenticate ourselves because there is no
// cached username and password), or the realm denied
// the user's reauthentication for some reason.
// In either case we have to prompt the user for a logon */
if (reauthenticateFromSSO(ssoId, request)) {
return true;
}
}
// Have we authenticated this user before but have caching disabled?
if (!cache) {
session = request.getSessionInternal(true);
if (log.isDebugEnabled()) {
log.debug("Checking for reauthenticate in session " + session);
}
String username =
(String) session.getNote(Constants.SESS_USERNAME_NOTE);
String password =
(String) session.getNote(Constants.SESS_PASSWORD_NOTE);
if ((username != null) && (password != null)) {
if (log.isDebugEnabled()) {
log.debug("Reauthenticating username '" + username + "'");
}
principal =
context.getRealm().authenticate(username, password);
if (principal != null) {
session.setNote(Constants.FORM_PRINCIPAL_NOTE, principal);
if (!matchRequest(request)) {
register(request, response, principal,
HttpServletRequest.FORM_AUTH,
username, password);
return (true);
}
}
if (log.isDebugEnabled()) {
log.debug("Reauthentication failed, proceed normally");
}
}
}
// Is this the re-submit of the original request URI after successful
// authentication? If so, forward the *original* request instead.
if (matchRequest(request)) {
session = request.getSessionInternal(true);
if (log.isDebugEnabled()) {
log.debug("Restore request from session '"
+ session.getIdInternal()
+ "'");
}
principal = (Principal)
session.getNote(Constants.FORM_PRINCIPAL_NOTE);
register(request, response, principal, HttpServletRequest.FORM_AUTH,
(String) session.getNote(Constants.SESS_USERNAME_NOTE),
(String) session.getNote(Constants.SESS_PASSWORD_NOTE));
// If we're caching principals we no longer need the username
// and password in the session, so remove them
if (cache) {
session.removeNote(Constants.SESS_USERNAME_NOTE);
session.removeNote(Constants.SESS_PASSWORD_NOTE);
}
if (restoreRequest(request, session)) {
if (log.isDebugEnabled()) {
log.debug("Proceed to restored request");
}
return (true);
} else {
if (log.isDebugEnabled()) {
log.debug("Restore of original request failed");
}
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return (false);
}
}
// Acquire references to objects we will need to evaluate
MessageBytes uriMB = MessageBytes.newInstance();
CharChunk uriCC = uriMB.getCharChunk();
uriCC.setLimit(-1);
String contextPath = request.getContextPath();
String requestURI = request.getDecodedRequestURI();
// Is this the action request from the login page?
boolean loginAction =
requestURI.startsWith(contextPath) &&
requestURI.endsWith(Constants.FORM_ACTION);
LoginConfig config = context.getLoginConfig();
// No -- Save this request and redirect to the form login page
if (!loginAction) {
session = request.getSessionInternal(true);
if (log.isDebugEnabled()) {
log.debug("Save request in session '" + session.getIdInternal() + "'");
}
try {
saveRequest(request, session);
} catch (IOException ioe) {
log.debug("Request body too big to save during authentication");
response.sendError(HttpServletResponse.SC_FORBIDDEN,
sm.getString("authenticator.requestBodyTooBig"));
return (false);
}
forwardToLoginPage(request, response, config);
return (false);
}
// Yes -- Acknowledge the request, validate the specified credentials
// and redirect to the error page if they are not correct
request.getResponse().sendAcknowledgement();
Realm realm = context.getRealm();
if (characterEncoding != null) {
request.setCharacterEncoding(characterEncoding);
}
String username = request.getParameter(Constants.FORM_USERNAME);
String password = request.getParameter(Constants.FORM_PASSWORD);
if (log.isDebugEnabled()) {
log.debug("Authenticating username '" + username + "'");
}
principal = realm.authenticate(username, password);
if (principal == null) {
forwardToErrorPage(request, response, config);
return (false);
}
if (log.isDebugEnabled()) {
log.debug("Authentication of '" + username + "' was successful");
}
if (session == null) {
session = request.getSessionInternal(false);
}
if (session == null) {
if (containerLog.isDebugEnabled()) {
containerLog.debug
("User took so long to log on the session expired");
}
if (landingPage == null) {
response.sendError(HttpServletResponse.SC_REQUEST_TIMEOUT,
sm.getString("authenticator.sessionExpired"));
} else {
// Make the authenticator think the user originally requested
// the landing page
String uri = request.getContextPath() + landingPage;
SavedRequest saved = new SavedRequest();
saved.setMethod("GET");
saved.setRequestURI(uri);
request.getSessionInternal(true).setNote(
Constants.FORM_REQUEST_NOTE, saved);
response.sendRedirect(response.encodeRedirectURL(uri));
}
return (false);
}
// Save the authenticated Principal in our session
session.setNote(Constants.FORM_PRINCIPAL_NOTE, principal);
// Save the username and password as well
session.setNote(Constants.SESS_USERNAME_NOTE, username);
session.setNote(Constants.SESS_PASSWORD_NOTE, password);
// Redirect the user to the original request URI (which will cause
// the original request to be restored)
requestURI = savedRequestURL(session);
if (log.isDebugEnabled()) {
log.debug("Redirecting to original '" + requestURI + "'");
}
if (requestURI == null) {
if (landingPage == null) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST,
sm.getString("authenticator.formlogin"));
} else {
// Make the authenticator think the user originally requested
// the landing page
String uri = request.getContextPath() + landingPage;
SavedRequest saved = new SavedRequest();
saved.setMethod("GET");
saved.setRequestURI(uri);
session.setNote(Constants.FORM_REQUEST_NOTE, saved);
response.sendRedirect(response.encodeRedirectURL(uri));
}
} else {
response.sendRedirect(response.encodeRedirectURL(requestURI));
}
return (false);
}
// in java/org/apache/catalina/authenticator/FormAuthenticator.java
protected void forwardToLoginPage(Request request,
HttpServletResponse response, LoginConfig config)
throws IOException {
if (log.isDebugEnabled()) {
log.debug(sm.getString("formAuthenticator.forwardLogin",
request.getRequestURI(), request.getMethod(),
config.getLoginPage(), context.getName()));
}
String loginPage = config.getLoginPage();
if (loginPage == null || loginPage.length() == 0) {
String msg = sm.getString("formAuthenticator.noLoginPage",
context.getName());
log.warn(msg);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
msg);
return;
}
// Always use GET for the login page, regardless of the method used
String oldMethod = request.getMethod();
request.getCoyoteRequest().method().setString("GET");
RequestDispatcher disp =
context.getServletContext().getRequestDispatcher(loginPage);
try {
if (context.fireRequestInitEvent(request)) {
disp.forward(request.getRequest(), response);
context.fireRequestDestroyEvent(request);
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
String msg = sm.getString("formAuthenticator.forwardLoginFail");
log.warn(msg, t);
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
msg);
} finally {
// Restore original method so that it is written into access log
request.getCoyoteRequest().method().setString(oldMethod);
}
}
// in java/org/apache/catalina/authenticator/FormAuthenticator.java
protected void forwardToErrorPage(Request request,
HttpServletResponse response, LoginConfig config)
throws IOException {
String errorPage = config.getErrorPage();
if (errorPage == null || errorPage.length() == 0) {
String msg = sm.getString("formAuthenticator.noErrorPage",
context.getName());
log.warn(msg);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
msg);
return;
}
RequestDispatcher disp =
context.getServletContext().getRequestDispatcher
(config.getErrorPage());
try {
if (context.fireRequestInitEvent(request)) {
disp.forward(request.getRequest(), response);
context.fireRequestDestroyEvent(request);
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
String msg = sm.getString("formAuthenticator.forwardErrorFail");
log.warn(msg, t);
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
msg);
}
}
// in java/org/apache/catalina/authenticator/FormAuthenticator.java
protected boolean restoreRequest(Request request, Session session)
throws IOException {
// Retrieve and remove the SavedRequest object from our session
SavedRequest saved = (SavedRequest)
session.getNote(Constants.FORM_REQUEST_NOTE);
session.removeNote(Constants.FORM_REQUEST_NOTE);
session.removeNote(Constants.FORM_PRINCIPAL_NOTE);
if (saved == null) {
return (false);
}
// Modify our current request to reflect the original one
request.clearCookies();
Iterator<Cookie> cookies = saved.getCookies();
while (cookies.hasNext()) {
request.addCookie(cookies.next());
}
String method = saved.getMethod();
MimeHeaders rmh = request.getCoyoteRequest().getMimeHeaders();
rmh.recycle();
boolean cachable = "GET".equalsIgnoreCase(method) ||
"HEAD".equalsIgnoreCase(method);
Iterator<String> names = saved.getHeaderNames();
while (names.hasNext()) {
String name = names.next();
// The browser isn't expecting this conditional response now.
// Assuming that it can quietly recover from an unexpected 412.
// BZ 43687
if(!("If-Modified-Since".equalsIgnoreCase(name) ||
(cachable && "If-None-Match".equalsIgnoreCase(name)))) {
Iterator<String> values = saved.getHeaderValues(name);
while (values.hasNext()) {
rmh.addValue(name).setString(values.next());
}
}
}
request.clearLocales();
Iterator<Locale> locales = saved.getLocales();
while (locales.hasNext()) {
request.addLocale(locales.next());
}
request.getCoyoteRequest().getParameters().recycle();
request.getCoyoteRequest().getParameters().setQueryStringEncoding(
request.getConnector().getURIEncoding());
// Swallow any request body since we will be replacing it
byte[] buffer = new byte[4096];
InputStream is = request.createInputStream();
while (is.read(buffer) >= 0) {
// Ignore request body
}
ByteChunk body = saved.getBody();
if (body != null) {
request.getCoyoteRequest().action
(ActionCode.REQ_SET_BODY_REPLAY, body);
// Set content type
MessageBytes contentType = MessageBytes.newInstance();
// If no content type specified, use default for POST
String savedContentType = saved.getContentType();
if (savedContentType == null && "POST".equalsIgnoreCase(method)) {
savedContentType = "application/x-www-form-urlencoded";
}
contentType.setString(savedContentType);
request.getCoyoteRequest().setContentType(contentType);
}
request.getCoyoteRequest().method().setString(method);
request.getCoyoteRequest().queryString().setString
(saved.getQueryString());
request.getCoyoteRequest().requestURI().setString
(saved.getRequestURI());
return (true);
}
// in java/org/apache/catalina/authenticator/FormAuthenticator.java
protected void saveRequest(Request request, Session session)
throws IOException {
// Create and populate a SavedRequest object for this request
SavedRequest saved = new SavedRequest();
Cookie cookies[] = request.getCookies();
if (cookies != null) {
for (int i = 0; i < cookies.length; i++) {
saved.addCookie(cookies[i]);
}
}
Enumeration<String> names = request.getHeaderNames();
while (names.hasMoreElements()) {
String name = names.nextElement();
Enumeration<String> values = request.getHeaders(name);
while (values.hasMoreElements()) {
String value = values.nextElement();
saved.addHeader(name, value);
}
}
Enumeration<Locale> locales = request.getLocales();
while (locales.hasMoreElements()) {
Locale locale = locales.nextElement();
saved.addLocale(locale);
}
// May need to acknowledge a 100-continue expectation
request.getResponse().sendAcknowledgement();
ByteChunk body = new ByteChunk();
body.setLimit(request.getConnector().getMaxSavePostSize());
byte[] buffer = new byte[4096];
int bytesRead;
InputStream is = request.getInputStream();
while ( (bytesRead = is.read(buffer) ) >= 0) {
body.append(buffer, 0, bytesRead);
}
// Only save the request body if there is something to save
if (body.getLength() > 0) {
saved.setContentType(request.getContentType());
saved.setBody(body);
}
saved.setMethod(request.getMethod());
saved.setQueryString(request.getQueryString());
saved.setRequestURI(request.getRequestURI());
// Stash the SavedRequest in our session for later use
session.setNote(Constants.FORM_REQUEST_NOTE, saved);
}
// in java/org/apache/catalina/servlets/DefaultServlet.java
Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
// Serve the requested resource, including the data content
serveResource(request, response, true);
}
// in java/org/apache/catalina/servlets/DefaultServlet.java
Override
protected void doHead(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
// Serve the requested resource, without the data content
serveResource(request, response, false);
}
// in java/org/apache/catalina/servlets/DefaultServlet.java
Override
protected void doOptions(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
StringBuilder allow = new StringBuilder();
// There is a doGet method
allow.append("GET, HEAD");
// There is a doPost
allow.append(", POST");
// There is a doPut
allow.append(", PUT");
// There is a doDelete
allow.append(", DELETE");
// Trace - assume disabled unless we can prove otherwise
if (req instanceof RequestFacade &&
((RequestFacade) req).getAllowTrace()) {
allow.append(", TRACE");
}
// Always allow options
allow.append(", OPTIONS");
resp.setHeader("Allow", allow.toString());
}
// in java/org/apache/catalina/servlets/DefaultServlet.java
Override
protected void doPost(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
doGet(request, response);
}
// in java/org/apache/catalina/servlets/DefaultServlet.java
Override
protected void doPut(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
if (readOnly) {
resp.sendError(HttpServletResponse.SC_FORBIDDEN);
return;
}
String path = getRelativePath(req);
boolean exists = true;
try {
resources.lookup(path);
} catch (NamingException e) {
exists = false;
}
boolean result = true;
// Temp. content file used to support partial PUT
File contentFile = null;
Range range = parseContentRange(req, resp);
InputStream resourceInputStream = null;
// Append data specified in ranges to existing content for this
// resource - create a temp. file on the local filesystem to
// perform this operation
// Assume just one range is specified for now
if (range != null) {
contentFile = executePartialPut(req, range, path);
resourceInputStream = new FileInputStream(contentFile);
} else {
resourceInputStream = req.getInputStream();
}
try {
Resource newResource = new Resource(resourceInputStream);
// FIXME: Add attributes
if (exists) {
resources.rebind(path, newResource);
} else {
resources.bind(path, newResource);
}
} catch(NamingException e) {
result = false;
}
if (result) {
if (exists) {
resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
} else {
resp.setStatus(HttpServletResponse.SC_CREATED);
}
} else {
resp.sendError(HttpServletResponse.SC_CONFLICT);
}
}
// in java/org/apache/catalina/servlets/DefaultServlet.java
protected File executePartialPut(HttpServletRequest req, Range range,
String path)
throws IOException {
// Append data specified in ranges to existing content for this
// resource - create a temp. file on the local filesystem to
// perform this operation
File tempDir = (File) getServletContext().getAttribute
(ServletContext.TEMPDIR);
// Convert all '/' characters to '.' in resourcePath
String convertedResourcePath = path.replace('/', '.');
File contentFile = new File(tempDir, convertedResourcePath);
if (contentFile.createNewFile()) {
// Clean up contentFile when Tomcat is terminated
contentFile.deleteOnExit();
}
RandomAccessFile randAccessContentFile =
new RandomAccessFile(contentFile, "rw");
Resource oldResource = null;
try {
Object obj = resources.lookup(path);
if (obj instanceof Resource)
oldResource = (Resource) obj;
} catch (NamingException e) {
// Ignore
}
// Copy data in oldRevisionContent to contentFile
if (oldResource != null) {
BufferedInputStream bufOldRevStream =
new BufferedInputStream(oldResource.streamContent(),
BUFFER_SIZE);
int numBytesRead;
byte[] copyBuffer = new byte[BUFFER_SIZE];
while ((numBytesRead = bufOldRevStream.read(copyBuffer)) != -1) {
randAccessContentFile.write(copyBuffer, 0, numBytesRead);
}
bufOldRevStream.close();
}
randAccessContentFile.setLength(range.length);
// Append data in request input stream to contentFile
randAccessContentFile.seek(range.start);
int numBytesRead;
byte[] transferBuffer = new byte[BUFFER_SIZE];
BufferedInputStream requestBufInStream =
new BufferedInputStream(req.getInputStream(), BUFFER_SIZE);
while ((numBytesRead = requestBufInStream.read(transferBuffer)) != -1) {
randAccessContentFile.write(transferBuffer, 0, numBytesRead);
}
randAccessContentFile.close();
requestBufInStream.close();
return contentFile;
}
// in java/org/apache/catalina/servlets/DefaultServlet.java
Override
protected void doDelete(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
if (readOnly) {
resp.sendError(HttpServletResponse.SC_FORBIDDEN);
return;
}
String path = getRelativePath(req);
boolean exists = true;
try {
resources.lookup(path);
} catch (NamingException e) {
exists = false;
}
if (exists) {
boolean result = true;
try {
resources.unbind(path);
} catch (NamingException e) {
result = false;
}
if (result) {
resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
} else {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
}
} else {
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
}
}
// in java/org/apache/catalina/servlets/DefaultServlet.java
protected boolean checkIfHeaders(HttpServletRequest request,
HttpServletResponse response,
ResourceAttributes resourceAttributes)
throws IOException {
return checkIfMatch(request, response, resourceAttributes)
&& checkIfModifiedSince(request, response, resourceAttributes)
&& checkIfNoneMatch(request, response, resourceAttributes)
&& checkIfUnmodifiedSince(request, response, resourceAttributes);
}
// in java/org/apache/catalina/servlets/DefaultServlet.java
protected void serveResource(HttpServletRequest request,
HttpServletResponse response,
boolean content)
throws IOException, ServletException {
boolean serveContent = content;
// Identify the requested resource path
String path = getRelativePath(request);
if (debug > 0) {
if (serveContent)
log("DefaultServlet.serveResource: Serving resource '" +
path + "' headers and data");
else
log("DefaultServlet.serveResource: Serving resource '" +
path + "' headers only");
}
CacheEntry cacheEntry = resources.lookupCache(path);
if (!cacheEntry.exists) {
// Check if we're included so we can return the appropriate
// missing resource name in the error
String requestUri = (String) request.getAttribute(
RequestDispatcher.INCLUDE_REQUEST_URI);
if (requestUri == null) {
requestUri = request.getRequestURI();
} else {
// We're included
// SRV.9.3 says we must throw a FNFE
throw new FileNotFoundException(
sm.getString("defaultServlet.missingResource",
requestUri));
}
response.sendError(HttpServletResponse.SC_NOT_FOUND,
requestUri);
return;
}
// If the resource is not a collection, and the resource path
// ends with "/" or "\", return NOT FOUND
if (cacheEntry.context == null) {
if (path.endsWith("/") || (path.endsWith("\\"))) {
// Check if we're included so we can return the appropriate
// missing resource name in the error
String requestUri = (String) request.getAttribute(
RequestDispatcher.INCLUDE_REQUEST_URI);
if (requestUri == null) {
requestUri = request.getRequestURI();
}
response.sendError(HttpServletResponse.SC_NOT_FOUND,
requestUri);
return;
}
}
boolean isError =
response.getStatus() >= HttpServletResponse.SC_BAD_REQUEST;
// Check if the conditions specified in the optional If headers are
// satisfied.
if (cacheEntry.context == null) {
// Checking If headers
boolean included = (request.getAttribute(
RequestDispatcher.INCLUDE_CONTEXT_PATH) != null);
if (!included && !isError &&
!checkIfHeaders(request, response, cacheEntry.attributes)) {
return;
}
}
// Find content type.
String contentType = cacheEntry.attributes.getMimeType();
if (contentType == null) {
contentType = getServletContext().getMimeType(cacheEntry.name);
cacheEntry.attributes.setMimeType(contentType);
}
ArrayList<Range> ranges = null;
long contentLength = -1L;
if (cacheEntry.context != null) {
// Skip directory listings if we have been configured to
// suppress them
if (!listings) {
response.sendError(HttpServletResponse.SC_NOT_FOUND,
request.getRequestURI());
return;
}
contentType = "text/html;charset=UTF-8";
} else {
if (!isError) {
if (useAcceptRanges) {
// Accept ranges header
response.setHeader("Accept-Ranges", "bytes");
}
// Parse range specifier
ranges = parseRange(request, response, cacheEntry.attributes);
// ETag header
response.setHeader("ETag", cacheEntry.attributes.getETag());
// Last-Modified header
response.setHeader("Last-Modified",
cacheEntry.attributes.getLastModifiedHttp());
}
// Get content length
contentLength = cacheEntry.attributes.getContentLength();
// Special case for zero length files, which would cause a
// (silent) ISE when setting the output buffer size
if (contentLength == 0L) {
serveContent = false;
}
}
ServletOutputStream ostream = null;
PrintWriter writer = null;
if (serveContent) {
// Trying to retrieve the servlet output stream
try {
ostream = response.getOutputStream();
} catch (IllegalStateException e) {
// If it fails, we try to get a Writer instead if we're
// trying to serve a text file
if ( (contentType == null)
|| (contentType.startsWith("text"))
|| (contentType.endsWith("xml"))
|| (contentType.contains("/javascript")) ) {
writer = response.getWriter();
// Cannot reliably serve partial content with a Writer
ranges = FULL;
} else {
throw e;
}
}
}
// Check to see if a Filter, Valve of wrapper has written some content.
// If it has, disable range requests and setting of a content length
// since neither can be done reliably.
ServletResponse r = response;
long contentWritten = 0;
while (r instanceof ServletResponseWrapper) {
r = ((ServletResponseWrapper) r).getResponse();
}
if (r instanceof ResponseFacade) {
contentWritten = ((ResponseFacade) r).getContentWritten();
}
if (contentWritten > 0) {
ranges = FULL;
}
if ( (cacheEntry.context != null)
|| isError
|| ( ((ranges == null) || (ranges.isEmpty()))
&& (request.getHeader("Range") == null) )
|| (ranges == FULL) ) {
// Set the appropriate output headers
if (contentType != null) {
if (debug > 0)
log("DefaultServlet.serveFile: contentType='" +
contentType + "'");
response.setContentType(contentType);
}
if ((cacheEntry.resource != null) && (contentLength >= 0)
&& (!serveContent || ostream != null)) {
if (debug > 0)
log("DefaultServlet.serveFile: contentLength=" +
contentLength);
// Don't set a content length if something else has already
// written to the response.
if (contentWritten == 0) {
if (contentLength < Integer.MAX_VALUE) {
response.setContentLength((int) contentLength);
} else {
// Set the content-length as String to be able to use a
// long
response.setHeader("content-length",
"" + contentLength);
}
}
}
InputStream renderResult = null;
if (cacheEntry.context != null) {
if (serveContent) {
// Serve the directory browser
renderResult = render(getPathPrefix(request), cacheEntry);
}
}
// Copy the input stream to our output stream (if requested)
if (serveContent) {
try {
response.setBufferSize(output);
} catch (IllegalStateException e) {
// Silent catch
}
if (ostream != null) {
if (!checkSendfile(request, response, cacheEntry, contentLength, null))
copy(cacheEntry, renderResult, ostream);
} else {
copy(cacheEntry, renderResult, writer);
}
}
} else {
if ((ranges == null) || (ranges.isEmpty()))
return;
// Partial content response.
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
if (ranges.size() == 1) {
Range range = ranges.get(0);
response.addHeader("Content-Range", "bytes "
+ range.start
+ "-" + range.end + "/"
+ range.length);
long length = range.end - range.start + 1;
if (length < Integer.MAX_VALUE) {
response.setContentLength((int) length);
} else {
// Set the content-length as String to be able to use a long
response.setHeader("content-length", "" + length);
}
if (contentType != null) {
if (debug > 0)
log("DefaultServlet.serveFile: contentType='" +
contentType + "'");
response.setContentType(contentType);
}
if (serveContent) {
try {
response.setBufferSize(output);
} catch (IllegalStateException e) {
// Silent catch
}
if (ostream != null) {
if (!checkSendfile(request, response, cacheEntry, range.end - range.start + 1, range))
copy(cacheEntry, ostream, range);
} else {
// we should not get here
throw new IllegalStateException();
}
}
} else {
response.setContentType("multipart/byteranges; boundary="
+ mimeSeparation);
if (serveContent) {
try {
response.setBufferSize(output);
} catch (IllegalStateException e) {
// Silent catch
}
if (ostream != null) {
copy(cacheEntry, ostream, ranges.iterator(),
contentType);
} else {
// we should not get here
throw new IllegalStateException();
}
}
}
}
}
// in java/org/apache/catalina/servlets/DefaultServlet.java
protected Range parseContentRange(HttpServletRequest request,
HttpServletResponse response)
throws IOException {
// Retrieving the content-range header (if any is specified
String rangeHeader = request.getHeader("Content-Range");
if (rangeHeader == null)
return null;
// bytes is the only range unit supported
if (!rangeHeader.startsWith("bytes")) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return null;
}
rangeHeader = rangeHeader.substring(6).trim();
int dashPos = rangeHeader.indexOf('-');
int slashPos = rangeHeader.indexOf('/');
if (dashPos == -1) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return null;
}
if (slashPos == -1) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return null;
}
Range range = new Range();
try {
range.start = Long.parseLong(rangeHeader.substring(0, dashPos));
range.end =
Long.parseLong(rangeHeader.substring(dashPos + 1, slashPos));
range.length = Long.parseLong
(rangeHeader.substring(slashPos + 1, rangeHeader.length()));
} catch (NumberFormatException e) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return null;
}
if (!range.validate()) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return null;
}
return range;
}
// in java/org/apache/catalina/servlets/DefaultServlet.java
protected ArrayList<Range> parseRange(HttpServletRequest request,
HttpServletResponse response,
ResourceAttributes resourceAttributes) throws IOException {
// Checking If-Range
String headerValue = request.getHeader("If-Range");
if (headerValue != null) {
long headerValueTime = (-1L);
try {
headerValueTime = request.getDateHeader("If-Range");
} catch (IllegalArgumentException e) {
// Ignore
}
String eTag = resourceAttributes.getETag();
long lastModified = resourceAttributes.getLastModified();
if (headerValueTime == (-1L)) {
// If the ETag the client gave does not match the entity
// etag, then the entire entity is returned.
if (!eTag.equals(headerValue.trim()))
return FULL;
} else {
// If the timestamp of the entity the client got is older than
// the last modification date of the entity, the entire entity
// is returned.
if (lastModified > (headerValueTime + 1000))
return FULL;
}
}
long fileLength = resourceAttributes.getContentLength();
if (fileLength == 0)
return null;
// Retrieving the range header (if any is specified
String rangeHeader = request.getHeader("Range");
if (rangeHeader == null)
return null;
// bytes is the only range unit supported (and I don't see the point
// of adding new ones).
if (!rangeHeader.startsWith("bytes")) {
response.addHeader("Content-Range", "bytes */" + fileLength);
response.sendError
(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
return null;
}
rangeHeader = rangeHeader.substring(6);
// Vector which will contain all the ranges which are successfully
// parsed.
ArrayList<Range> result = new ArrayList<Range>();
StringTokenizer commaTokenizer = new StringTokenizer(rangeHeader, ",");
// Parsing the range list
while (commaTokenizer.hasMoreTokens()) {
String rangeDefinition = commaTokenizer.nextToken().trim();
Range currentRange = new Range();
currentRange.length = fileLength;
int dashPos = rangeDefinition.indexOf('-');
if (dashPos == -1) {
response.addHeader("Content-Range", "bytes */" + fileLength);
response.sendError
(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
return null;
}
if (dashPos == 0) {
try {
long offset = Long.parseLong(rangeDefinition);
currentRange.start = fileLength + offset;
currentRange.end = fileLength - 1;
} catch (NumberFormatException e) {
response.addHeader("Content-Range",
"bytes */" + fileLength);
response.sendError
(HttpServletResponse
.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
return null;
}
} else {
try {
currentRange.start = Long.parseLong
(rangeDefinition.substring(0, dashPos));
if (dashPos < rangeDefinition.length() - 1)
currentRange.end = Long.parseLong
(rangeDefinition.substring
(dashPos + 1, rangeDefinition.length()));
else
currentRange.end = fileLength - 1;
} catch (NumberFormatException e) {
response.addHeader("Content-Range",
"bytes */" + fileLength);
response.sendError
(HttpServletResponse
.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
return null;
}
}
if (!currentRange.validate()) {
response.addHeader("Content-Range", "bytes */" + fileLength);
response.sendError
(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
return null;
}
result.add(currentRange);
}
return result;
}
// in java/org/apache/catalina/servlets/DefaultServlet.java
protected InputStream render(String contextPath, CacheEntry cacheEntry)
throws IOException, ServletException {
InputStream xsltInputStream =
findXsltInputStream(cacheEntry.context);
if (xsltInputStream==null) {
return renderHtml(contextPath, cacheEntry);
}
return renderXml(contextPath, cacheEntry, xsltInputStream);
}
// in java/org/apache/catalina/servlets/DefaultServlet.java
protected InputStream renderXml(String contextPath,
CacheEntry cacheEntry,
InputStream xsltInputStream)
throws IOException, ServletException {
StringBuilder sb = new StringBuilder();
sb.append("<?xml version=\"1.0\"?>");
sb.append("<listing ");
sb.append(" contextPath='");
sb.append(contextPath);
sb.append("'");
sb.append(" directory='");
sb.append(cacheEntry.name);
sb.append("' ");
sb.append(" hasParent='").append(!cacheEntry.name.equals("/"));
sb.append("'>");
sb.append("<entries>");
try {
// Render the directory entries within this directory
NamingEnumeration<NameClassPair> enumeration =
resources.list(cacheEntry.name);
// rewriteUrl(contextPath) is expensive. cache result for later reuse
String rewrittenContextPath = rewriteUrl(contextPath);
while (enumeration.hasMoreElements()) {
NameClassPair ncPair = enumeration.nextElement();
String resourceName = ncPair.getName();
String trimmed = resourceName/*.substring(trim)*/;
if (trimmed.equalsIgnoreCase("WEB-INF") ||
trimmed.equalsIgnoreCase("META-INF") ||
trimmed.equalsIgnoreCase(localXsltFile))
continue;
if ((cacheEntry.name + trimmed).equals(contextXsltFile))
continue;
CacheEntry childCacheEntry =
resources.lookupCache(cacheEntry.name + resourceName);
if (!childCacheEntry.exists) {
continue;
}
sb.append("<entry");
sb.append(" type='")
.append((childCacheEntry.context != null)?"dir":"file")
.append("'");
sb.append(" urlPath='")
.append(rewrittenContextPath)
.append(rewriteUrl(cacheEntry.name + resourceName))
.append((childCacheEntry.context != null)?"/":"")
.append("'");
if (childCacheEntry.resource != null) {
sb.append(" size='")
.append(renderSize(childCacheEntry.attributes.getContentLength()))
.append("'");
}
sb.append(" date='")
.append(childCacheEntry.attributes.getLastModifiedHttp())
.append("'");
sb.append(">");
sb.append(RequestUtil.filter(trimmed));
if (childCacheEntry.context != null)
sb.append("/");
sb.append("</entry>");
}
} catch (NamingException e) {
// Something went wrong
throw new ServletException("Error accessing resource", e);
}
sb.append("</entries>");
String readme = getReadme(cacheEntry.context);
if (readme!=null) {
sb.append("<readme><![CDATA[");
sb.append(readme);
sb.append("]]></readme>");
}
sb.append("</listing>");
try {
TransformerFactory tFactory = TransformerFactory.newInstance();
Source xmlSource = new StreamSource(new StringReader(sb.toString()));
Source xslSource = new StreamSource(xsltInputStream);
Transformer transformer = tFactory.newTransformer(xslSource);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
OutputStreamWriter osWriter = new OutputStreamWriter(stream, "UTF8");
StreamResult out = new StreamResult(osWriter);
transformer.transform(xmlSource, out);
osWriter.flush();
return (new ByteArrayInputStream(stream.toByteArray()));
} catch (TransformerException e) {
throw new ServletException("XSL transformer error", e);
}
}
// in java/org/apache/catalina/servlets/DefaultServlet.java
protected InputStream renderHtml(String contextPath, CacheEntry cacheEntry)
throws IOException, ServletException {
String name = cacheEntry.name;
// Prepare a writer to a buffered area
ByteArrayOutputStream stream = new ByteArrayOutputStream();
OutputStreamWriter osWriter = new OutputStreamWriter(stream, "UTF8");
PrintWriter writer = new PrintWriter(osWriter);
StringBuilder sb = new StringBuilder();
// rewriteUrl(contextPath) is expensive. cache result for later reuse
String rewrittenContextPath = rewriteUrl(contextPath);
// Render the page header
sb.append("<html>\r\n");
sb.append("<head>\r\n");
sb.append("<title>");
sb.append(sm.getString("directory.title", name));
sb.append("</title>\r\n");
sb.append("<STYLE><!--");
sb.append(org.apache.catalina.util.TomcatCSS.TOMCAT_CSS);
sb.append("--></STYLE> ");
sb.append("</head>\r\n");
sb.append("<body>");
sb.append("<h1>");
sb.append(sm.getString("directory.title", name));
// Render the link to our parent (if required)
String parentDirectory = name;
if (parentDirectory.endsWith("/")) {
parentDirectory =
parentDirectory.substring(0, parentDirectory.length() - 1);
}
int slash = parentDirectory.lastIndexOf('/');
if (slash >= 0) {
String parent = name.substring(0, slash);
sb.append(" - <a href=\"");
sb.append(rewrittenContextPath);
if (parent.equals(""))
parent = "/";
sb.append(rewriteUrl(parent));
if (!parent.endsWith("/"))
sb.append("/");
sb.append("\">");
sb.append("<b>");
sb.append(sm.getString("directory.parent", parent));
sb.append("</b>");
sb.append("</a>");
}
sb.append("</h1>");
sb.append("<HR size=\"1\" noshade=\"noshade\">");
sb.append("<table width=\"100%\" cellspacing=\"0\"" +
" cellpadding=\"5\" align=\"center\">\r\n");
// Render the column headings
sb.append("<tr>\r\n");
sb.append("<td align=\"left\"><font size=\"+1\"><strong>");
sb.append(sm.getString("directory.filename"));
sb.append("</strong></font></td>\r\n");
sb.append("<td align=\"center\"><font size=\"+1\"><strong>");
sb.append(sm.getString("directory.size"));
sb.append("</strong></font></td>\r\n");
sb.append("<td align=\"right\"><font size=\"+1\"><strong>");
sb.append(sm.getString("directory.lastModified"));
sb.append("</strong></font></td>\r\n");
sb.append("</tr>");
try {
// Render the directory entries within this directory
NamingEnumeration<NameClassPair> enumeration =
resources.list(cacheEntry.name);
boolean shade = false;
while (enumeration.hasMoreElements()) {
NameClassPair ncPair = enumeration.nextElement();
String resourceName = ncPair.getName();
String trimmed = resourceName/*.substring(trim)*/;
if (trimmed.equalsIgnoreCase("WEB-INF") ||
trimmed.equalsIgnoreCase("META-INF"))
continue;
CacheEntry childCacheEntry =
resources.lookupCache(cacheEntry.name + resourceName);
if (!childCacheEntry.exists) {
continue;
}
sb.append("<tr");
if (shade)
sb.append(" bgcolor=\"#eeeeee\"");
sb.append(">\r\n");
shade = !shade;
sb.append("<td align=\"left\"> \r\n");
sb.append("<a href=\"");
sb.append(rewrittenContextPath);
resourceName = rewriteUrl(name + resourceName);
sb.append(resourceName);
if (childCacheEntry.context != null)
sb.append("/");
sb.append("\"><tt>");
sb.append(RequestUtil.filter(trimmed));
if (childCacheEntry.context != null)
sb.append("/");
sb.append("</tt></a></td>\r\n");
sb.append("<td align=\"right\"><tt>");
if (childCacheEntry.context != null)
sb.append(" ");
else
sb.append(renderSize(childCacheEntry.attributes.getContentLength()));
sb.append("</tt></td>\r\n");
sb.append("<td align=\"right\"><tt>");
sb.append(childCacheEntry.attributes.getLastModifiedHttp());
sb.append("</tt></td>\r\n");
sb.append("</tr>\r\n");
}
} catch (NamingException e) {
// Something went wrong
throw new ServletException("Error accessing resource", e);
}
// Render the page footer
sb.append("</table>\r\n");
sb.append("<HR size=\"1\" noshade=\"noshade\">");
String readme = getReadme(cacheEntry.context);
if (readme!=null) {
sb.append(readme);
sb.append("<HR size=\"1\" noshade=\"noshade\">");
}
sb.append("<h3>").append(ServerInfo.getServerInfo()).append("</h3>");
sb.append("</body>\r\n");
sb.append("</html>\r\n");
// Return an input stream to the underlying bytes
writer.write(sb.toString());
writer.flush();
return (new ByteArrayInputStream(stream.toByteArray()));
}
// in java/org/apache/catalina/servlets/DefaultServlet.java
protected String getReadme(DirContext directory)
throws IOException {
if (readmeFile != null) {
try {
Object obj = directory.lookup(readmeFile);
if ((obj != null) && (obj instanceof Resource)) {
StringWriter buffer = new StringWriter();
InputStream is = ((Resource) obj).streamContent();
copyRange(new InputStreamReader(is),
new PrintWriter(buffer));
return buffer.toString();
}
} catch (NamingException e) {
if (debug > 10)
log("readme '" + readmeFile + "' not found", e);
return null;
}
}
return null;
}
// in java/org/apache/catalina/servlets/DefaultServlet.java
protected InputStream findXsltInputStream(DirContext directory)
throws IOException {
if (localXsltFile != null) {
try {
Object obj = directory.lookup(localXsltFile);
if ((obj != null) && (obj instanceof Resource)) {
InputStream is = ((Resource) obj).streamContent();
if (is != null)
return is;
}
} catch (NamingException e) {
if (debug > 10)
log("localXsltFile '" + localXsltFile + "' not found", e);
}
}
if (contextXsltFile != null) {
InputStream is =
getServletContext().getResourceAsStream(contextXsltFile);
if (is != null)
return is;
if (debug > 10)
log("contextXsltFile '" + contextXsltFile + "' not found");
}
/* Open and read in file in one fell swoop to reduce chance
* chance of leaving handle open.
*/
if (globalXsltFile!=null) {
FileInputStream fis = null;
try {
File f = new File(globalXsltFile);
if (f.exists()){
fis =new FileInputStream(f);
byte b[] = new byte[(int)f.length()]; /* danger! */
fis.read(b);
return new ByteArrayInputStream(b);
}
} finally {
if (fis!=null)
fis.close();
}
}
return null;
}
// in java/org/apache/catalina/servlets/DefaultServlet.java
protected boolean checkIfMatch(HttpServletRequest request,
HttpServletResponse response,
ResourceAttributes resourceAttributes)
throws IOException {
String eTag = resourceAttributes.getETag();
String headerValue = request.getHeader("If-Match");
if (headerValue != null) {
if (headerValue.indexOf('*') == -1) {
StringTokenizer commaTokenizer = new StringTokenizer
(headerValue, ",");
boolean conditionSatisfied = false;
while (!conditionSatisfied && commaTokenizer.hasMoreTokens()) {
String currentToken = commaTokenizer.nextToken();
if (currentToken.trim().equals(eTag))
conditionSatisfied = true;
}
// If none of the given ETags match, 412 Precodition failed is
// sent back
if (!conditionSatisfied) {
response.sendError
(HttpServletResponse.SC_PRECONDITION_FAILED);
return false;
}
}
}
return true;
}
// in java/org/apache/catalina/servlets/DefaultServlet.java
protected boolean checkIfNoneMatch(HttpServletRequest request,
HttpServletResponse response,
ResourceAttributes resourceAttributes)
throws IOException {
String eTag = resourceAttributes.getETag();
String headerValue = request.getHeader("If-None-Match");
if (headerValue != null) {
boolean conditionSatisfied = false;
if (!headerValue.equals("*")) {
StringTokenizer commaTokenizer =
new StringTokenizer(headerValue, ",");
while (!conditionSatisfied && commaTokenizer.hasMoreTokens()) {
String currentToken = commaTokenizer.nextToken();
if (currentToken.trim().equals(eTag))
conditionSatisfied = true;
}
} else {
conditionSatisfied = true;
}
if (conditionSatisfied) {
// For GET and HEAD, we should respond with
// 304 Not Modified.
// For every other method, 412 Precondition Failed is sent
// back.
if ( ("GET".equals(request.getMethod()))
|| ("HEAD".equals(request.getMethod())) ) {
response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
response.setHeader("ETag", eTag);
return false;
}
response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED);
return false;
}
}
return true;
}
// in java/org/apache/catalina/servlets/DefaultServlet.java
protected boolean checkIfUnmodifiedSince(HttpServletRequest request,
HttpServletResponse response,
ResourceAttributes resourceAttributes)
throws IOException {
try {
long lastModified = resourceAttributes.getLastModified();
long headerValue = request.getDateHeader("If-Unmodified-Since");
if (headerValue != -1) {
if ( lastModified >= (headerValue + 1000)) {
// The entity has not been modified since the date
// specified by the client. This is not an error case.
response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED);
return false;
}
}
} catch(IllegalArgumentException illegalArgument) {
return true;
}
return true;
}
// in java/org/apache/catalina/servlets/DefaultServlet.java
protected void copy(CacheEntry cacheEntry, InputStream is,
ServletOutputStream ostream)
throws IOException {
IOException exception = null;
InputStream resourceInputStream = null;
// Optimization: If the binary content has already been loaded, send
// it directly
if (cacheEntry.resource != null) {
byte buffer[] = cacheEntry.resource.getContent();
if (buffer != null) {
ostream.write(buffer, 0, buffer.length);
return;
}
resourceInputStream = cacheEntry.resource.streamContent();
} else {
resourceInputStream = is;
}
InputStream istream = new BufferedInputStream
(resourceInputStream, input);
// Copy the input stream to the output stream
exception = copyRange(istream, ostream);
// Clean up the input stream
istream.close();
// Rethrow any exception that has occurred
if (exception != null)
throw exception;
}
// in java/org/apache/catalina/servlets/DefaultServlet.java
protected void copy(CacheEntry cacheEntry, InputStream is, PrintWriter writer)
throws IOException {
IOException exception = null;
InputStream resourceInputStream = null;
if (cacheEntry.resource != null) {
resourceInputStream = cacheEntry.resource.streamContent();
} else {
resourceInputStream = is;
}
Reader reader;
if (fileEncoding == null) {
reader = new InputStreamReader(resourceInputStream);
} else {
reader = new InputStreamReader(resourceInputStream,
fileEncoding);
}
// Copy the input stream to the output stream
exception = copyRange(reader, writer);
// Clean up the reader
reader.close();
// Rethrow any exception that has occurred
if (exception != null)
throw exception;
}
// in java/org/apache/catalina/servlets/DefaultServlet.java
protected void copy(CacheEntry cacheEntry, ServletOutputStream ostream,
Range range)
throws IOException {
IOException exception = null;
InputStream resourceInputStream = cacheEntry.resource.streamContent();
InputStream istream =
new BufferedInputStream(resourceInputStream, input);
exception = copyRange(istream, ostream, range.start, range.end);
// Clean up the input stream
istream.close();
// Rethrow any exception that has occurred
if (exception != null)
throw exception;
}
// in java/org/apache/catalina/servlets/DefaultServlet.java
protected void copy(CacheEntry cacheEntry, ServletOutputStream ostream,
Iterator<Range> ranges, String contentType)
throws IOException {
IOException exception = null;
while ( (exception == null) && (ranges.hasNext()) ) {
InputStream resourceInputStream = cacheEntry.resource.streamContent();
InputStream istream =
new BufferedInputStream(resourceInputStream, input);
Range currentRange = ranges.next();
// Writing MIME header.
ostream.println();
ostream.println("--" + mimeSeparation);
if (contentType != null)
ostream.println("Content-Type: " + contentType);
ostream.println("Content-Range: bytes " + currentRange.start
+ "-" + currentRange.end + "/"
+ currentRange.length);
ostream.println();
// Printing content
exception = copyRange(istream, ostream, currentRange.start,
currentRange.end);
istream.close();
}
ostream.println();
ostream.print("--" + mimeSeparation + "--");
// Rethrow any exception that has occurred
if (exception != null)
throw exception;
}
// in java/org/apache/catalina/servlets/WebdavServlet.java
Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
final String path = getRelativePath(req);
// Block access to special subdirectories.
// DefaultServlet assumes it services resources from the root of the web app
// and doesn't add any special path protection
// WebdavServlet remounts the webapp under a new path, so this check is
// necessary on all methods (including GET).
if (isSpecialPath(path)) {
resp.sendError(WebdavStatus.SC_NOT_FOUND);
return;
}
final String method = req.getMethod();
if (debug > 0) {
log("[" + method + "] " + path);
}
if (method.equals(METHOD_PROPFIND)) {
doPropfind(req, resp);
} else if (method.equals(METHOD_PROPPATCH)) {
doProppatch(req, resp);
} else if (method.equals(METHOD_MKCOL)) {
doMkcol(req, resp);
} else if (method.equals(METHOD_COPY)) {
doCopy(req, resp);
} else if (method.equals(METHOD_MOVE)) {
doMove(req, resp);
} else if (method.equals(METHOD_LOCK)) {
doLock(req, resp);
} else if (method.equals(METHOD_UNLOCK)) {
doUnlock(req, resp);
} else {
// DefaultServlet processing
super.service(req, resp);
}
}
// in java/org/apache/catalina/servlets/WebdavServlet.java
Override
protected boolean checkIfHeaders(HttpServletRequest request,
HttpServletResponse response,
ResourceAttributes resourceAttributes)
throws IOException {
if (!super.checkIfHeaders(request, response, resourceAttributes))
return false;
// TODO : Checking the WebDAV If header
return true;
}
// in java/org/apache/catalina/servlets/WebdavServlet.java
Override
protected void doOptions(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.addHeader("DAV", "1,2");
StringBuilder methodsAllowed = determineMethodsAllowed(resources,
req);
resp.addHeader("Allow", methodsAllowed.toString());
resp.addHeader("MS-Author-Via", "DAV");
}
// in java/org/apache/catalina/servlets/WebdavServlet.java
protected void doPropfind(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
if (!listings) {
// Get allowed methods
StringBuilder methodsAllowed = determineMethodsAllowed(resources,
req);
resp.addHeader("Allow", methodsAllowed.toString());
resp.sendError(WebdavStatus.SC_METHOD_NOT_ALLOWED);
return;
}
String path = getRelativePath(req);
if (path.endsWith("/"))
path = path.substring(0, path.length() - 1);
// Properties which are to be displayed.
Vector<String> properties = null;
// Propfind depth
int depth = maxDepth;
// Propfind type
int type = FIND_ALL_PROP;
String depthStr = req.getHeader("Depth");
if (depthStr == null) {
depth = maxDepth;
} else {
if (depthStr.equals("0")) {
depth = 0;
} else if (depthStr.equals("1")) {
depth = 1;
} else if (depthStr.equals("infinity")) {
depth = maxDepth;
}
}
Node propNode = null;
if (req.getContentLength() > 0) {
DocumentBuilder documentBuilder = getDocumentBuilder();
try {
Document document = documentBuilder.parse
(new InputSource(req.getInputStream()));
// Get the root element of the document
Element rootElement = document.getDocumentElement();
NodeList childList = rootElement.getChildNodes();
for (int i=0; i < childList.getLength(); i++) {
Node currentNode = childList.item(i);
switch (currentNode.getNodeType()) {
case Node.TEXT_NODE:
break;
case Node.ELEMENT_NODE:
if (currentNode.getNodeName().endsWith("prop")) {
type = FIND_BY_PROPERTY;
propNode = currentNode;
}
if (currentNode.getNodeName().endsWith("propname")) {
type = FIND_PROPERTY_NAMES;
}
if (currentNode.getNodeName().endsWith("allprop")) {
type = FIND_ALL_PROP;
}
break;
}
}
} catch (SAXException e) {
// Something went wrong - bad request
resp.sendError(WebdavStatus.SC_BAD_REQUEST);
} catch (IOException e) {
// Something went wrong - bad request
resp.sendError(WebdavStatus.SC_BAD_REQUEST);
}
}
if (type == FIND_BY_PROPERTY) {
properties = new Vector<String>();
// propNode must be non-null if type == FIND_BY_PROPERTY
@SuppressWarnings("null")
NodeList childList = propNode.getChildNodes();
for (int i=0; i < childList.getLength(); i++) {
Node currentNode = childList.item(i);
switch (currentNode.getNodeType()) {
case Node.TEXT_NODE:
break;
case Node.ELEMENT_NODE:
String nodeName = currentNode.getNodeName();
String propertyName = null;
if (nodeName.indexOf(':') != -1) {
propertyName = nodeName.substring
(nodeName.indexOf(':') + 1);
} else {
propertyName = nodeName;
}
// href is a live property which is handled differently
properties.addElement(propertyName);
break;
}
}
}
boolean exists = true;
Object object = null;
try {
object = resources.lookup(path);
} catch (NamingException e) {
exists = false;
int slash = path.lastIndexOf('/');
if (slash != -1) {
String parentPath = path.substring(0, slash);
Vector<String> currentLockNullResources =
lockNullResources.get(parentPath);
if (currentLockNullResources != null) {
Enumeration<String> lockNullResourcesList =
currentLockNullResources.elements();
while (lockNullResourcesList.hasMoreElements()) {
String lockNullPath =
lockNullResourcesList.nextElement();
if (lockNullPath.equals(path)) {
resp.setStatus(WebdavStatus.SC_MULTI_STATUS);
resp.setContentType("text/xml; charset=UTF-8");
// Create multistatus object
XMLWriter generatedXML =
new XMLWriter(resp.getWriter());
generatedXML.writeXMLHeader();
generatedXML.writeElement("D", DEFAULT_NAMESPACE,
"multistatus", XMLWriter.OPENING);
parseLockNullProperties
(req, generatedXML, lockNullPath, type,
properties);
generatedXML.writeElement("D", "multistatus",
XMLWriter.CLOSING);
generatedXML.sendData();
return;
}
}
}
}
}
if (!exists) {
resp.sendError(HttpServletResponse.SC_NOT_FOUND, path);
return;
}
resp.setStatus(WebdavStatus.SC_MULTI_STATUS);
resp.setContentType("text/xml; charset=UTF-8");
// Create multistatus object
XMLWriter generatedXML = new XMLWriter(resp.getWriter());
generatedXML.writeXMLHeader();
generatedXML.writeElement("D", DEFAULT_NAMESPACE, "multistatus",
XMLWriter.OPENING);
if (depth == 0) {
parseProperties(req, generatedXML, path, type,
properties);
} else {
// The stack always contains the object of the current level
Stack<String> stack = new Stack<String>();
stack.push(path);
// Stack of the objects one level below
Stack<String> stackBelow = new Stack<String>();
while ((!stack.isEmpty()) && (depth >= 0)) {
String currentPath = stack.pop();
parseProperties(req, generatedXML, currentPath,
type, properties);
try {
object = resources.lookup(currentPath);
} catch (NamingException e) {
continue;
}
if ((object instanceof DirContext) && (depth > 0)) {
try {
NamingEnumeration<NameClassPair> enumeration =
resources.list(currentPath);
while (enumeration.hasMoreElements()) {
NameClassPair ncPair = enumeration.nextElement();
String newPath = currentPath;
if (!(newPath.endsWith("/")))
newPath += "/";
newPath += ncPair.getName();
stackBelow.push(newPath);
}
} catch (NamingException e) {
resp.sendError
(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
path);
return;
}
// Displaying the lock-null resources present in that
// collection
String lockPath = currentPath;
if (lockPath.endsWith("/"))
lockPath =
lockPath.substring(0, lockPath.length() - 1);
Vector<String> currentLockNullResources =
lockNullResources.get(lockPath);
if (currentLockNullResources != null) {
Enumeration<String> lockNullResourcesList =
currentLockNullResources.elements();
while (lockNullResourcesList.hasMoreElements()) {
String lockNullPath =
lockNullResourcesList.nextElement();
parseLockNullProperties
(req, generatedXML, lockNullPath, type,
properties);
}
}
}
if (stack.isEmpty()) {
depth--;
stack = stackBelow;
stackBelow = new Stack<String>();
}
generatedXML.sendData();
}
}
generatedXML.writeElement("D", "multistatus", XMLWriter.CLOSING);
generatedXML.sendData();
}
// in java/org/apache/catalina/servlets/WebdavServlet.java
protected void doProppatch(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
if (readOnly) {
resp.sendError(WebdavStatus.SC_FORBIDDEN);
return;
}
if (isLocked(req)) {
resp.sendError(WebdavStatus.SC_LOCKED);
return;
}
resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
}
// in java/org/apache/catalina/servlets/WebdavServlet.java
protected void doMkcol(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
if (readOnly) {
resp.sendError(WebdavStatus.SC_FORBIDDEN);
return;
}
if (isLocked(req)) {
resp.sendError(WebdavStatus.SC_LOCKED);
return;
}
String path = getRelativePath(req);
boolean exists = true;
try {
resources.lookup(path);
} catch (NamingException e) {
exists = false;
}
// Can't create a collection if a resource already exists at the given
// path
if (exists) {
// Get allowed methods
StringBuilder methodsAllowed = determineMethodsAllowed(resources,
req);
resp.addHeader("Allow", methodsAllowed.toString());
resp.sendError(WebdavStatus.SC_METHOD_NOT_ALLOWED);
return;
}
if (req.getContentLength() > 0) {
DocumentBuilder documentBuilder = getDocumentBuilder();
try {
// Document document =
documentBuilder.parse(new InputSource(req.getInputStream()));
// TODO : Process this request body
resp.sendError(WebdavStatus.SC_NOT_IMPLEMENTED);
return;
} catch(SAXException saxe) {
// Parse error - assume invalid content
resp.sendError(WebdavStatus.SC_UNSUPPORTED_MEDIA_TYPE);
return;
}
}
boolean result = true;
try {
resources.createSubcontext(path);
} catch (NamingException e) {
result = false;
}
if (!result) {
resp.sendError(WebdavStatus.SC_CONFLICT,
WebdavStatus.getStatusText
(WebdavStatus.SC_CONFLICT));
} else {
resp.setStatus(WebdavStatus.SC_CREATED);
// Removing any lock-null resource which would be present
lockNullResources.remove(path);
}
}
// in java/org/apache/catalina/servlets/WebdavServlet.java
Override
protected void doDelete(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
if (readOnly) {
resp.sendError(WebdavStatus.SC_FORBIDDEN);
return;
}
if (isLocked(req)) {
resp.sendError(WebdavStatus.SC_LOCKED);
return;
}
deleteResource(req, resp);
}
// in java/org/apache/catalina/servlets/WebdavServlet.java
Override
protected void doPut(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
if (isLocked(req)) {
resp.sendError(WebdavStatus.SC_LOCKED);
return;
}
super.doPut(req, resp);
String path = getRelativePath(req);
// Removing any lock-null resource which would be present
lockNullResources.remove(path);
}
// in java/org/apache/catalina/servlets/WebdavServlet.java
protected void doCopy(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
if (readOnly) {
resp.sendError(WebdavStatus.SC_FORBIDDEN);
return;
}
copyResource(req, resp);
}
// in java/org/apache/catalina/servlets/WebdavServlet.java
protected void doMove(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
if (readOnly) {
resp.sendError(WebdavStatus.SC_FORBIDDEN);
return;
}
if (isLocked(req)) {
resp.sendError(WebdavStatus.SC_LOCKED);
return;
}
String path = getRelativePath(req);
if (copyResource(req, resp)) {
deleteResource(path, req, resp, false);
}
}
// in java/org/apache/catalina/servlets/WebdavServlet.java
protected void doLock(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
if (readOnly) {
resp.sendError(WebdavStatus.SC_FORBIDDEN);
return;
}
if (isLocked(req)) {
resp.sendError(WebdavStatus.SC_LOCKED);
return;
}
LockInfo lock = new LockInfo();
// Parsing lock request
// Parsing depth header
String depthStr = req.getHeader("Depth");
if (depthStr == null) {
lock.depth = maxDepth;
} else {
if (depthStr.equals("0")) {
lock.depth = 0;
} else {
lock.depth = maxDepth;
}
}
// Parsing timeout header
int lockDuration = DEFAULT_TIMEOUT;
String lockDurationStr = req.getHeader("Timeout");
if (lockDurationStr == null) {
lockDuration = DEFAULT_TIMEOUT;
} else {
int commaPos = lockDurationStr.indexOf(",");
// If multiple timeouts, just use the first
if (commaPos != -1) {
lockDurationStr = lockDurationStr.substring(0,commaPos);
}
if (lockDurationStr.startsWith("Second-")) {
lockDuration =
(new Integer(lockDurationStr.substring(7))).intValue();
} else {
if (lockDurationStr.equalsIgnoreCase("infinity")) {
lockDuration = MAX_TIMEOUT;
} else {
try {
lockDuration =
(new Integer(lockDurationStr)).intValue();
} catch (NumberFormatException e) {
lockDuration = MAX_TIMEOUT;
}
}
}
if (lockDuration == 0) {
lockDuration = DEFAULT_TIMEOUT;
}
if (lockDuration > MAX_TIMEOUT) {
lockDuration = MAX_TIMEOUT;
}
}
lock.expiresAt = System.currentTimeMillis() + (lockDuration * 1000);
int lockRequestType = LOCK_CREATION;
Node lockInfoNode = null;
DocumentBuilder documentBuilder = getDocumentBuilder();
try {
Document document = documentBuilder.parse(new InputSource
(req.getInputStream()));
// Get the root element of the document
Element rootElement = document.getDocumentElement();
lockInfoNode = rootElement;
} catch (IOException e) {
lockRequestType = LOCK_REFRESH;
} catch (SAXException e) {
lockRequestType = LOCK_REFRESH;
}
if (lockInfoNode != null) {
// Reading lock information
NodeList childList = lockInfoNode.getChildNodes();
StringWriter strWriter = null;
DOMWriter domWriter = null;
Node lockScopeNode = null;
Node lockTypeNode = null;
Node lockOwnerNode = null;
for (int i=0; i < childList.getLength(); i++) {
Node currentNode = childList.item(i);
switch (currentNode.getNodeType()) {
case Node.TEXT_NODE:
break;
case Node.ELEMENT_NODE:
String nodeName = currentNode.getNodeName();
if (nodeName.endsWith("lockscope")) {
lockScopeNode = currentNode;
}
if (nodeName.endsWith("locktype")) {
lockTypeNode = currentNode;
}
if (nodeName.endsWith("owner")) {
lockOwnerNode = currentNode;
}
break;
}
}
if (lockScopeNode != null) {
childList = lockScopeNode.getChildNodes();
for (int i=0; i < childList.getLength(); i++) {
Node currentNode = childList.item(i);
switch (currentNode.getNodeType()) {
case Node.TEXT_NODE:
break;
case Node.ELEMENT_NODE:
String tempScope = currentNode.getNodeName();
if (tempScope.indexOf(':') != -1) {
lock.scope = tempScope.substring
(tempScope.indexOf(':') + 1);
} else {
lock.scope = tempScope;
}
break;
}
}
if (lock.scope == null) {
// Bad request
resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
}
} else {
// Bad request
resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
}
if (lockTypeNode != null) {
childList = lockTypeNode.getChildNodes();
for (int i=0; i < childList.getLength(); i++) {
Node currentNode = childList.item(i);
switch (currentNode.getNodeType()) {
case Node.TEXT_NODE:
break;
case Node.ELEMENT_NODE:
String tempType = currentNode.getNodeName();
if (tempType.indexOf(':') != -1) {
lock.type =
tempType.substring(tempType.indexOf(':') + 1);
} else {
lock.type = tempType;
}
break;
}
}
if (lock.type == null) {
// Bad request
resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
}
} else {
// Bad request
resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
}
if (lockOwnerNode != null) {
childList = lockOwnerNode.getChildNodes();
for (int i=0; i < childList.getLength(); i++) {
Node currentNode = childList.item(i);
switch (currentNode.getNodeType()) {
case Node.TEXT_NODE:
lock.owner += currentNode.getNodeValue();
break;
case Node.ELEMENT_NODE:
strWriter = new StringWriter();
domWriter = new DOMWriter(strWriter, true);
domWriter.setQualifiedNames(false);
domWriter.print(currentNode);
lock.owner += strWriter.toString();
break;
}
}
if (lock.owner == null) {
// Bad request
resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
}
} else {
lock.owner = "";
}
}
String path = getRelativePath(req);
lock.path = path;
boolean exists = true;
Object object = null;
try {
object = resources.lookup(path);
} catch (NamingException e) {
exists = false;
}
Enumeration<LockInfo> locksList = null;
if (lockRequestType == LOCK_CREATION) {
// Generating lock id
String lockTokenStr = req.getServletPath() + "-" + lock.type + "-"
+ lock.scope + "-" + req.getUserPrincipal() + "-"
+ lock.depth + "-" + lock.owner + "-" + lock.tokens + "-"
+ lock.expiresAt + "-" + System.currentTimeMillis() + "-"
+ secret;
String lockToken = md5Encoder.encode(md5Helper.digest(
lockTokenStr.getBytes(B2CConverter.ISO_8859_1)));
if ( (exists) && (object instanceof DirContext) &&
(lock.depth == maxDepth) ) {
// Locking a collection (and all its member resources)
// Checking if a child resource of this collection is
// already locked
Vector<String> lockPaths = new Vector<String>();
locksList = collectionLocks.elements();
while (locksList.hasMoreElements()) {
LockInfo currentLock = locksList.nextElement();
if (currentLock.hasExpired()) {
resourceLocks.remove(currentLock.path);
continue;
}
if ( (currentLock.path.startsWith(lock.path)) &&
((currentLock.isExclusive()) ||
(lock.isExclusive())) ) {
// A child collection of this collection is locked
lockPaths.addElement(currentLock.path);
}
}
locksList = resourceLocks.elements();
while (locksList.hasMoreElements()) {
LockInfo currentLock = locksList.nextElement();
if (currentLock.hasExpired()) {
resourceLocks.remove(currentLock.path);
continue;
}
if ( (currentLock.path.startsWith(lock.path)) &&
((currentLock.isExclusive()) ||
(lock.isExclusive())) ) {
// A child resource of this collection is locked
lockPaths.addElement(currentLock.path);
}
}
if (!lockPaths.isEmpty()) {
// One of the child paths was locked
// We generate a multistatus error report
Enumeration<String> lockPathsList = lockPaths.elements();
resp.setStatus(WebdavStatus.SC_CONFLICT);
XMLWriter generatedXML = new XMLWriter();
generatedXML.writeXMLHeader();
generatedXML.writeElement("D", DEFAULT_NAMESPACE,
"multistatus", XMLWriter.OPENING);
while (lockPathsList.hasMoreElements()) {
generatedXML.writeElement("D", "response",
XMLWriter.OPENING);
generatedXML.writeElement("D", "href",
XMLWriter.OPENING);
generatedXML.writeText(lockPathsList.nextElement());
generatedXML.writeElement("D", "href",
XMLWriter.CLOSING);
generatedXML.writeElement("D", "status",
XMLWriter.OPENING);
generatedXML
.writeText("HTTP/1.1 " + WebdavStatus.SC_LOCKED
+ " " + WebdavStatus
.getStatusText(WebdavStatus.SC_LOCKED));
generatedXML.writeElement("D", "status",
XMLWriter.CLOSING);
generatedXML.writeElement("D", "response",
XMLWriter.CLOSING);
}
generatedXML.writeElement("D", "multistatus",
XMLWriter.CLOSING);
Writer writer = resp.getWriter();
writer.write(generatedXML.toString());
writer.close();
return;
}
boolean addLock = true;
// Checking if there is already a shared lock on this path
locksList = collectionLocks.elements();
while (locksList.hasMoreElements()) {
LockInfo currentLock = locksList.nextElement();
if (currentLock.path.equals(lock.path)) {
if (currentLock.isExclusive()) {
resp.sendError(WebdavStatus.SC_LOCKED);
return;
} else {
if (lock.isExclusive()) {
resp.sendError(WebdavStatus.SC_LOCKED);
return;
}
}
currentLock.tokens.addElement(lockToken);
lock = currentLock;
addLock = false;
}
}
if (addLock) {
lock.tokens.addElement(lockToken);
collectionLocks.addElement(lock);
}
} else {
// Locking a single resource
// Retrieving an already existing lock on that resource
LockInfo presentLock = resourceLocks.get(lock.path);
if (presentLock != null) {
if ((presentLock.isExclusive()) || (lock.isExclusive())) {
// If either lock is exclusive, the lock can't be
// granted
resp.sendError(WebdavStatus.SC_PRECONDITION_FAILED);
return;
} else {
presentLock.tokens.addElement(lockToken);
lock = presentLock;
}
} else {
lock.tokens.addElement(lockToken);
resourceLocks.put(lock.path, lock);
// Checking if a resource exists at this path
exists = true;
try {
object = resources.lookup(path);
} catch (NamingException e) {
exists = false;
}
if (!exists) {
// "Creating" a lock-null resource
int slash = lock.path.lastIndexOf('/');
String parentPath = lock.path.substring(0, slash);
Vector<String> lockNulls =
lockNullResources.get(parentPath);
if (lockNulls == null) {
lockNulls = new Vector<String>();
lockNullResources.put(parentPath, lockNulls);
}
lockNulls.addElement(lock.path);
}
// Add the Lock-Token header as by RFC 2518 8.10.1
// - only do this for newly created locks
resp.addHeader("Lock-Token", "<opaquelocktoken:"
+ lockToken + ">");
}
}
}
if (lockRequestType == LOCK_REFRESH) {
String ifHeader = req.getHeader("If");
if (ifHeader == null)
ifHeader = "";
// Checking resource locks
LockInfo toRenew = resourceLocks.get(path);
Enumeration<String> tokenList = null;
if (toRenew != null) {
// At least one of the tokens of the locks must have been given
tokenList = toRenew.tokens.elements();
while (tokenList.hasMoreElements()) {
String token = tokenList.nextElement();
if (ifHeader.indexOf(token) != -1) {
toRenew.expiresAt = lock.expiresAt;
lock = toRenew;
}
}
}
// Checking inheritable collection locks
Enumeration<LockInfo> collectionLocksList =
collectionLocks.elements();
while (collectionLocksList.hasMoreElements()) {
toRenew = collectionLocksList.nextElement();
if (path.equals(toRenew.path)) {
tokenList = toRenew.tokens.elements();
while (tokenList.hasMoreElements()) {
String token = tokenList.nextElement();
if (ifHeader.indexOf(token) != -1) {
toRenew.expiresAt = lock.expiresAt;
lock = toRenew;
}
}
}
}
}
// Set the status, then generate the XML response containing
// the lock information
XMLWriter generatedXML = new XMLWriter();
generatedXML.writeXMLHeader();
generatedXML.writeElement("D", DEFAULT_NAMESPACE, "prop",
XMLWriter.OPENING);
generatedXML.writeElement("D", "lockdiscovery", XMLWriter.OPENING);
lock.toXML(generatedXML);
generatedXML.writeElement("D", "lockdiscovery", XMLWriter.CLOSING);
generatedXML.writeElement("D", "prop", XMLWriter.CLOSING);
resp.setStatus(WebdavStatus.SC_OK);
resp.setContentType("text/xml; charset=UTF-8");
Writer writer = resp.getWriter();
writer.write(generatedXML.toString());
writer.close();
}
// in java/org/apache/catalina/servlets/WebdavServlet.java
protected void doUnlock(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
if (readOnly) {
resp.sendError(WebdavStatus.SC_FORBIDDEN);
return;
}
if (isLocked(req)) {
resp.sendError(WebdavStatus.SC_LOCKED);
return;
}
String path = getRelativePath(req);
String lockTokenHeader = req.getHeader("Lock-Token");
if (lockTokenHeader == null)
lockTokenHeader = "";
// Checking resource locks
LockInfo lock = resourceLocks.get(path);
Enumeration<String> tokenList = null;
if (lock != null) {
// At least one of the tokens of the locks must have been given
tokenList = lock.tokens.elements();
while (tokenList.hasMoreElements()) {
String token = tokenList.nextElement();
if (lockTokenHeader.indexOf(token) != -1) {
lock.tokens.removeElement(token);
}
}
if (lock.tokens.isEmpty()) {
resourceLocks.remove(path);
// Removing any lock-null resource which would be present
lockNullResources.remove(path);
}
}
// Checking inheritable collection locks
Enumeration<LockInfo> collectionLocksList = collectionLocks.elements();
while (collectionLocksList.hasMoreElements()) {
lock = collectionLocksList.nextElement();
if (path.equals(lock.path)) {
tokenList = lock.tokens.elements();
while (tokenList.hasMoreElements()) {
String token = tokenList.nextElement();
if (lockTokenHeader.indexOf(token) != -1) {
lock.tokens.removeElement(token);
break;
}
}
if (lock.tokens.isEmpty()) {
collectionLocks.removeElement(lock);
// Removing any lock-null resource which would be present
lockNullResources.remove(path);
}
}
}
resp.setStatus(WebdavStatus.SC_NO_CONTENT);
}
// in java/org/apache/catalina/servlets/WebdavServlet.java
private boolean copyResource(HttpServletRequest req,
HttpServletResponse resp)
throws IOException {
// Parsing destination header
String destinationPath = req.getHeader("Destination");
if (destinationPath == null) {
resp.sendError(WebdavStatus.SC_BAD_REQUEST);
return false;
}
// Remove url encoding from destination
destinationPath = org.apache.catalina.util.RequestUtil.URLDecode(
destinationPath, "UTF8");
int protocolIndex = destinationPath.indexOf("://");
if (protocolIndex >= 0) {
// if the Destination URL contains the protocol, we can safely
// trim everything upto the first "/" character after "://"
int firstSeparator =
destinationPath.indexOf("/", protocolIndex + 4);
if (firstSeparator < 0) {
destinationPath = "/";
} else {
destinationPath = destinationPath.substring(firstSeparator);
}
} else {
String hostName = req.getServerName();
if ((hostName != null) && (destinationPath.startsWith(hostName))) {
destinationPath = destinationPath.substring(hostName.length());
}
int portIndex = destinationPath.indexOf(":");
if (portIndex >= 0) {
destinationPath = destinationPath.substring(portIndex);
}
if (destinationPath.startsWith(":")) {
int firstSeparator = destinationPath.indexOf("/");
if (firstSeparator < 0) {
destinationPath = "/";
} else {
destinationPath =
destinationPath.substring(firstSeparator);
}
}
}
// Normalise destination path (remove '.' and '..')
destinationPath = RequestUtil.normalize(destinationPath);
String contextPath = req.getContextPath();
if ((contextPath != null) &&
(destinationPath.startsWith(contextPath))) {
destinationPath = destinationPath.substring(contextPath.length());
}
String pathInfo = req.getPathInfo();
if (pathInfo != null) {
String servletPath = req.getServletPath();
if ((servletPath != null) &&
(destinationPath.startsWith(servletPath))) {
destinationPath = destinationPath
.substring(servletPath.length());
}
}
if (debug > 0)
log("Dest path :" + destinationPath);
// Check destination path to protect special subdirectories
if (isSpecialPath(destinationPath)) {
resp.sendError(WebdavStatus.SC_FORBIDDEN);
return false;
}
String path = getRelativePath(req);
if (destinationPath.equals(path)) {
resp.sendError(WebdavStatus.SC_FORBIDDEN);
return false;
}
// Parsing overwrite header
boolean overwrite = true;
String overwriteHeader = req.getHeader("Overwrite");
if (overwriteHeader != null) {
if (overwriteHeader.equalsIgnoreCase("T")) {
overwrite = true;
} else {
overwrite = false;
}
}
// Overwriting the destination
boolean exists = true;
try {
resources.lookup(destinationPath);
} catch (NamingException e) {
exists = false;
}
if (overwrite) {
// Delete destination resource, if it exists
if (exists) {
if (!deleteResource(destinationPath, req, resp, true)) {
return false;
}
} else {
resp.setStatus(WebdavStatus.SC_CREATED);
}
} else {
// If the destination exists, then it's a conflict
if (exists) {
resp.sendError(WebdavStatus.SC_PRECONDITION_FAILED);
return false;
}
}
// Copying source to destination
Hashtable<String,Integer> errorList = new Hashtable<String,Integer>();
boolean result = copyResource(resources, errorList,
path, destinationPath);
if ((!result) || (!errorList.isEmpty())) {
if (errorList.size() == 1) {
resp.sendError(errorList.elements().nextElement().intValue());
} else {
sendReport(req, resp, errorList);
}
return false;
}
// Copy was successful
if (exists) {
resp.setStatus(WebdavStatus.SC_NO_CONTENT);
} else {
resp.setStatus(WebdavStatus.SC_CREATED);
}
// Removing any lock-null resource which would be present at
// the destination path
lockNullResources.remove(destinationPath);
return true;
}
// in java/org/apache/catalina/servlets/WebdavServlet.java
private boolean deleteResource(HttpServletRequest req,
HttpServletResponse resp)
throws IOException {
String path = getRelativePath(req);
return deleteResource(path, req, resp, true);
}
// in java/org/apache/catalina/servlets/WebdavServlet.java
private boolean deleteResource(String path, HttpServletRequest req,
HttpServletResponse resp, boolean setStatus)
throws IOException {
String ifHeader = req.getHeader("If");
if (ifHeader == null)
ifHeader = "";
String lockTokenHeader = req.getHeader("Lock-Token");
if (lockTokenHeader == null)
lockTokenHeader = "";
if (isLocked(path, ifHeader + lockTokenHeader)) {
resp.sendError(WebdavStatus.SC_LOCKED);
return false;
}
boolean exists = true;
Object object = null;
try {
object = resources.lookup(path);
} catch (NamingException e) {
exists = false;
}
if (!exists) {
resp.sendError(WebdavStatus.SC_NOT_FOUND);
return false;
}
boolean collection = (object instanceof DirContext);
if (!collection) {
try {
resources.unbind(path);
} catch (NamingException e) {
resp.sendError(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
return false;
}
} else {
Hashtable<String,Integer> errorList =
new Hashtable<String,Integer>();
deleteCollection(req, resources, path, errorList);
try {
resources.unbind(path);
} catch (NamingException e) {
errorList.put(path, new Integer
(WebdavStatus.SC_INTERNAL_SERVER_ERROR));
}
if (!errorList.isEmpty()) {
sendReport(req, resp, errorList);
return false;
}
}
if (setStatus) {
resp.setStatus(WebdavStatus.SC_NO_CONTENT);
}
return true;
}
// in java/org/apache/catalina/servlets/WebdavServlet.java
private void sendReport(HttpServletRequest req, HttpServletResponse resp,
Hashtable<String,Integer> errorList)
throws IOException {
resp.setStatus(WebdavStatus.SC_MULTI_STATUS);
String absoluteUri = req.getRequestURI();
String relativePath = getRelativePath(req);
XMLWriter generatedXML = new XMLWriter();
generatedXML.writeXMLHeader();
generatedXML.writeElement("D", DEFAULT_NAMESPACE, "multistatus",
XMLWriter.OPENING);
Enumeration<String> pathList = errorList.keys();
while (pathList.hasMoreElements()) {
String errorPath = pathList.nextElement();
int errorCode = errorList.get(errorPath).intValue();
generatedXML.writeElement("D", "response", XMLWriter.OPENING);
generatedXML.writeElement("D", "href", XMLWriter.OPENING);
String toAppend = errorPath.substring(relativePath.length());
if (!toAppend.startsWith("/"))
toAppend = "/" + toAppend;
generatedXML.writeText(absoluteUri + toAppend);
generatedXML.writeElement("D", "href", XMLWriter.CLOSING);
generatedXML.writeElement("D", "status", XMLWriter.OPENING);
generatedXML.writeText("HTTP/1.1 " + errorCode + " "
+ WebdavStatus.getStatusText(errorCode));
generatedXML.writeElement("D", "status", XMLWriter.CLOSING);
generatedXML.writeElement("D", "response", XMLWriter.CLOSING);
}
generatedXML.writeElement("D", "multistatus", XMLWriter.CLOSING);
Writer writer = resp.getWriter();
writer.write(generatedXML.toString());
writer.close();
}
// in java/org/apache/catalina/servlets/CGIServlet.java
protected void printServletEnvironment(ServletOutputStream out,
HttpServletRequest req, HttpServletResponse res)
throws IOException {
// Document the properties from ServletRequest
out.println("<h1>ServletRequest Properties</h1>");
out.println("<ul>");
Enumeration<String> attrs = req.getAttributeNames();
while (attrs.hasMoreElements()) {
String attr = attrs.nextElement();
out.println("<li><b>attribute</b> " + attr + " = " +
req.getAttribute(attr));
}
out.println("<li><b>characterEncoding</b> = " +
req.getCharacterEncoding());
out.println("<li><b>contentLength</b> = " +
req.getContentLength());
out.println("<li><b>contentType</b> = " +
req.getContentType());
Enumeration<Locale> locales = req.getLocales();
while (locales.hasMoreElements()) {
Locale locale = locales.nextElement();
out.println("<li><b>locale</b> = " + locale);
}
Enumeration<String> params = req.getParameterNames();
while (params.hasMoreElements()) {
String param = params.nextElement();
String values[] = req.getParameterValues(param);
for (int i = 0; i < values.length; i++)
out.println("<li><b>parameter</b> " + param + " = " +
values[i]);
}
out.println("<li><b>protocol</b> = " + req.getProtocol());
out.println("<li><b>remoteAddr</b> = " + req.getRemoteAddr());
out.println("<li><b>remoteHost</b> = " + req.getRemoteHost());
out.println("<li><b>scheme</b> = " + req.getScheme());
out.println("<li><b>secure</b> = " + req.isSecure());
out.println("<li><b>serverName</b> = " + req.getServerName());
out.println("<li><b>serverPort</b> = " + req.getServerPort());
out.println("</ul>");
out.println("<hr>");
// Document the properties from HttpServletRequest
out.println("<h1>HttpServletRequest Properties</h1>");
out.println("<ul>");
out.println("<li><b>authType</b> = " + req.getAuthType());
out.println("<li><b>contextPath</b> = " +
req.getContextPath());
Cookie cookies[] = req.getCookies();
if (cookies!=null) {
for (int i = 0; i < cookies.length; i++)
out.println("<li><b>cookie</b> " + cookies[i].getName() +" = " +cookies[i].getValue());
}
Enumeration<String> headers = req.getHeaderNames();
while (headers.hasMoreElements()) {
String header = headers.nextElement();
out.println("<li><b>header</b> " + header + " = " +
req.getHeader(header));
}
out.println("<li><b>method</b> = " + req.getMethod());
out.println("<li><a name=\"pathInfo\"><b>pathInfo</b></a> = "
+ req.getPathInfo());
out.println("<li><b>pathTranslated</b> = " +
req.getPathTranslated());
out.println("<li><b>queryString</b> = " +
req.getQueryString());
out.println("<li><b>remoteUser</b> = " +
req.getRemoteUser());
out.println("<li><b>requestedSessionId</b> = " +
req.getRequestedSessionId());
out.println("<li><b>requestedSessionIdFromCookie</b> = " +
req.isRequestedSessionIdFromCookie());
out.println("<li><b>requestedSessionIdFromURL</b> = " +
req.isRequestedSessionIdFromURL());
out.println("<li><b>requestedSessionIdValid</b> = " +
req.isRequestedSessionIdValid());
out.println("<li><b>requestURI</b> = " +
req.getRequestURI());
out.println("<li><b>servletPath</b> = " +
req.getServletPath());
out.println("<li><b>userPrincipal</b> = " +
req.getUserPrincipal());
out.println("</ul>");
out.println("<hr>");
// Document the servlet request attributes
out.println("<h1>ServletRequest Attributes</h1>");
out.println("<ul>");
attrs = req.getAttributeNames();
while (attrs.hasMoreElements()) {
String attr = attrs.nextElement();
out.println("<li><b>" + attr + "</b> = " +
req.getAttribute(attr));
}
out.println("</ul>");
out.println("<hr>");
// Process the current session (if there is one)
HttpSession session = req.getSession(false);
if (session != null) {
// Document the session properties
out.println("<h1>HttpSession Properties</h1>");
out.println("<ul>");
out.println("<li><b>id</b> = " +
session.getId());
out.println("<li><b>creationTime</b> = " +
new Date(session.getCreationTime()));
out.println("<li><b>lastAccessedTime</b> = " +
new Date(session.getLastAccessedTime()));
out.println("<li><b>maxInactiveInterval</b> = " +
session.getMaxInactiveInterval());
out.println("</ul>");
out.println("<hr>");
// Document the session attributes
out.println("<h1>HttpSession Attributes</h1>");
out.println("<ul>");
attrs = session.getAttributeNames();
while (attrs.hasMoreElements()) {
String attr = attrs.nextElement();
out.println("<li><b>" + attr + "</b> = " +
session.getAttribute(attr));
}
out.println("</ul>");
out.println("<hr>");
}
// Document the servlet configuration properties
out.println("<h1>ServletConfig Properties</h1>");
out.println("<ul>");
out.println("<li><b>servletName</b> = " +
getServletConfig().getServletName());
out.println("</ul>");
out.println("<hr>");
// Document the servlet configuration initialization parameters
out.println("<h1>ServletConfig Initialization Parameters</h1>");
out.println("<ul>");
params = getServletConfig().getInitParameterNames();
while (params.hasMoreElements()) {
String param = params.nextElement();
String value = getServletConfig().getInitParameter(param);
out.println("<li><b>" + param + "</b> = " + value);
}
out.println("</ul>");
out.println("<hr>");
// Document the servlet context properties
out.println("<h1>ServletContext Properties</h1>");
out.println("<ul>");
out.println("<li><b>majorVersion</b> = " +
getServletContext().getMajorVersion());
out.println("<li><b>minorVersion</b> = " +
getServletContext().getMinorVersion());
out.println("<li><b>realPath('/')</b> = " +
getServletContext().getRealPath("/"));
out.println("<li><b>serverInfo</b> = " +
getServletContext().getServerInfo());
out.println("</ul>");
out.println("<hr>");
// Document the servlet context initialization parameters
out.println("<h1>ServletContext Initialization Parameters</h1>");
out.println("<ul>");
params = getServletContext().getInitParameterNames();
while (params.hasMoreElements()) {
String param = params.nextElement();
String value = getServletContext().getInitParameter(param);
out.println("<li><b>" + param + "</b> = " + value);
}
out.println("</ul>");
out.println("<hr>");
// Document the servlet context attributes
out.println("<h1>ServletContext Attributes</h1>");
out.println("<ul>");
attrs = getServletContext().getAttributeNames();
while (attrs.hasMoreElements()) {
String attr = attrs.nextElement();
out.println("<li><b>" + attr + "</b> = " +
getServletContext().getAttribute(attr));
}
out.println("</ul>");
out.println("<hr>");
}
// in java/org/apache/catalina/servlets/CGIServlet.java
Override
protected void doPost(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
doGet(req, res);
}
// in java/org/apache/catalina/servlets/CGIServlet.java
Override
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
CGIEnvironment cgiEnv = new CGIEnvironment(req, getServletContext());
if (cgiEnv.isValid()) {
CGIRunner cgi = new CGIRunner(cgiEnv.getCommand(),
cgiEnv.getEnvironment(),
cgiEnv.getWorkingDirectory(),
cgiEnv.getParameters());
//if POST, we need to cgi.setInput
//REMIND: how does this interact with Servlet API 2.3's Filters?!
if ("POST".equals(req.getMethod())) {
cgi.setInput(req.getInputStream());
}
cgi.setResponse(res);
cgi.run();
}
if (!cgiEnv.isValid()) {
res.setStatus(404);
}
if (debug >= 10) {
ServletOutputStream out = res.getOutputStream();
out.println("<HTML><HEAD><TITLE>$Name$</TITLE></HEAD>");
out.println("<BODY>$Header$<p>");
if (cgiEnv.isValid()) {
out.println(cgiEnv.toString());
} else {
out.println("<H3>");
out.println("CGI script not found or not specified.");
out.println("</H3>");
out.println("<H4>");
out.println("Check the <b>HttpServletRequest ");
out.println("<a href=\"#pathInfo\">pathInfo</a></b> ");
out.println("property to see if it is what you meant ");
out.println("it to be. You must specify an existant ");
out.println("and executable file as part of the ");
out.println("path-info.");
out.println("</H4>");
out.println("<H4>");
out.println("For a good discussion of how CGI scripts ");
out.println("work and what their environment variables ");
out.println("mean, please visit the <a ");
out.println("href=\"http://cgi-spec.golux.com\">CGI ");
out.println("Specification page</a>.");
out.println("</H4>");
}
printServletEnvironment(out, req, res);
out.println("</BODY></HTML>");
}
}
// in java/org/apache/catalina/servlets/CGIServlet.java
protected boolean setCGIEnvironment(HttpServletRequest req) throws IOException {
/*
* This method is slightly ugly; c'est la vie.
* "You cannot stop [ugliness], you can only hope to contain [it]"
* (apologies to Marv Albert regarding MJ)
*/
Hashtable<String,String> envp = new Hashtable<String,String>();
// Add the shell environment variables (if any)
envp.putAll(shellEnv);
// Add the CGI environment variables
String sPathInfoOrig = null;
String sPathInfoCGI = null;
String sPathTranslatedCGI = null;
String sCGIFullPath = null;
String sCGIScriptName = null;
String sCGIFullName = null;
String sCGIName = null;
String[] sCGINames;
sPathInfoOrig = this.pathInfo;
sPathInfoOrig = sPathInfoOrig == null ? "" : sPathInfoOrig;
if (webAppRootDir == null ) {
// The app has not been deployed in exploded form
webAppRootDir = tmpDir.toString();
expandCGIScript();
}
sCGINames = findCGI(sPathInfoOrig,
webAppRootDir,
contextPath,
servletPath,
cgiPathPrefix);
sCGIFullPath = sCGINames[0];
sCGIScriptName = sCGINames[1];
sCGIFullName = sCGINames[2];
sCGIName = sCGINames[3];
if (sCGIFullPath == null
|| sCGIScriptName == null
|| sCGIFullName == null
|| sCGIName == null) {
return false;
}
envp.put("SERVER_SOFTWARE", "TOMCAT");
envp.put("SERVER_NAME", nullsToBlanks(req.getServerName()));
envp.put("GATEWAY_INTERFACE", "CGI/1.1");
envp.put("SERVER_PROTOCOL", nullsToBlanks(req.getProtocol()));
int port = req.getServerPort();
Integer iPort =
(port == 0 ? Integer.valueOf(-1) : Integer.valueOf(port));
envp.put("SERVER_PORT", iPort.toString());
envp.put("REQUEST_METHOD", nullsToBlanks(req.getMethod()));
envp.put("REQUEST_URI", nullsToBlanks(req.getRequestURI()));
/*-
* PATH_INFO should be determined by using sCGIFullName:
* 1) Let sCGIFullName not end in a "/" (see method findCGI)
* 2) Let sCGIFullName equal the pathInfo fragment which
* corresponds to the actual cgi script.
* 3) Thus, PATH_INFO = request.getPathInfo().substring(
* sCGIFullName.length())
*
* (see method findCGI, where the real work is done)
*
*/
if (pathInfo == null
|| (pathInfo.substring(sCGIFullName.length()).length() <= 0)) {
sPathInfoCGI = "";
} else {
sPathInfoCGI = pathInfo.substring(sCGIFullName.length());
}
envp.put("PATH_INFO", sPathInfoCGI);
/*-
* PATH_TRANSLATED must be determined after PATH_INFO (and the
* implied real cgi-script) has been taken into account.
*
* The following example demonstrates:
*
* servlet info = /servlet/cgigw/dir1/dir2/cgi1/trans1/trans2
* cgifullpath = /servlet/cgigw/dir1/dir2/cgi1
* path_info = /trans1/trans2
* webAppRootDir = servletContext.getRealPath("/")
*
* path_translated = servletContext.getRealPath("/trans1/trans2")
*
* That is, PATH_TRANSLATED = webAppRootDir + sPathInfoCGI
* (unless sPathInfoCGI is null or blank, then the CGI
* specification dictates that the PATH_TRANSLATED metavariable
* SHOULD NOT be defined.
*
*/
if (sPathInfoCGI != null && !("".equals(sPathInfoCGI))) {
sPathTranslatedCGI = context.getRealPath(sPathInfoCGI);
}
if (sPathTranslatedCGI == null || "".equals(sPathTranslatedCGI)) {
//NOOP
} else {
envp.put("PATH_TRANSLATED", nullsToBlanks(sPathTranslatedCGI));
}
envp.put("SCRIPT_NAME", nullsToBlanks(sCGIScriptName));
envp.put("QUERY_STRING", nullsToBlanks(req.getQueryString()));
envp.put("REMOTE_HOST", nullsToBlanks(req.getRemoteHost()));
envp.put("REMOTE_ADDR", nullsToBlanks(req.getRemoteAddr()));
envp.put("AUTH_TYPE", nullsToBlanks(req.getAuthType()));
envp.put("REMOTE_USER", nullsToBlanks(req.getRemoteUser()));
envp.put("REMOTE_IDENT", ""); //not necessary for full compliance
envp.put("CONTENT_TYPE", nullsToBlanks(req.getContentType()));
/* Note CGI spec says CONTENT_LENGTH must be NULL ("") or undefined
* if there is no content, so we cannot put 0 or -1 in as per the
* Servlet API spec.
*/
int contentLength = req.getContentLength();
String sContentLength = (contentLength <= 0 ? "" :
(Integer.valueOf(contentLength)).toString());
envp.put("CONTENT_LENGTH", sContentLength);
Enumeration<String> headers = req.getHeaderNames();
String header = null;
while (headers.hasMoreElements()) {
header = null;
header = headers.nextElement().toUpperCase(Locale.ENGLISH);
//REMIND: rewrite multiple headers as if received as single
//REMIND: change character set
//REMIND: I forgot what the previous REMIND means
if ("AUTHORIZATION".equalsIgnoreCase(header) ||
"PROXY_AUTHORIZATION".equalsIgnoreCase(header)) {
//NOOP per CGI specification section 11.2
} else {
envp.put("HTTP_" + header.replace('-', '_'),
req.getHeader(header));
}
}
File fCGIFullPath = new File(sCGIFullPath);
command = fCGIFullPath.getCanonicalPath();
envp.put("X_TOMCAT_SCRIPT_PATH", command); //for kicks
envp.put("SCRIPT_FILENAME", command); //for PHP
this.env = envp;
return true;
}
// in java/org/apache/catalina/servlets/CGIServlet.java
protected void run() throws IOException {
/*
* REMIND: this method feels too big; should it be re-written?
*/
if (!isReady()) {
throw new IOException(this.getClass().getName()
+ ": not ready to run.");
}
if (debug >= 1 ) {
log("runCGI(envp=[" + env + "], command=" + command + ")");
}
if ((command.indexOf(File.separator + "." + File.separator) >= 0)
|| (command.indexOf(File.separator + "..") >= 0)
|| (command.indexOf(".." + File.separator) >= 0)) {
throw new IOException(this.getClass().getName()
+ "Illegal Character in CGI command "
+ "path ('.' or '..') detected. Not "
+ "running CGI [" + command + "].");
}
/* original content/structure of this section taken from
* http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4216884
* with major modifications by Martin Dengler
*/
Runtime rt = null;
BufferedReader cgiHeaderReader = null;
InputStream cgiOutput = null;
BufferedReader commandsStdErr = null;
Thread errReaderThread = null;
BufferedOutputStream commandsStdIn = null;
Process proc = null;
int bufRead = -1;
List<String> cmdAndArgs = new ArrayList<String>();
if (cgiExecutable.length() != 0) {
cmdAndArgs.add(cgiExecutable);
}
if (cgiExecutableArgs != null) {
cmdAndArgs.addAll(cgiExecutableArgs);
}
cmdAndArgs.add(command);
cmdAndArgs.addAll(params);
try {
rt = Runtime.getRuntime();
proc = rt.exec(
cmdAndArgs.toArray(new String[cmdAndArgs.size()]),
hashToStringArray(env), wd);
String sContentLength = env.get("CONTENT_LENGTH");
if(!"".equals(sContentLength)) {
commandsStdIn = new BufferedOutputStream(proc.getOutputStream());
IOTools.flow(stdin, commandsStdIn);
commandsStdIn.flush();
commandsStdIn.close();
}
/* we want to wait for the process to exit, Process.waitFor()
* is useless in our situation; see
* http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4223650
*/
boolean isRunning = true;
commandsStdErr = new BufferedReader
(new InputStreamReader(proc.getErrorStream()));
final BufferedReader stdErrRdr = commandsStdErr ;
errReaderThread = new Thread() {
@Override
public void run () {
sendToLog(stdErrRdr) ;
}
};
errReaderThread.start();
InputStream cgiHeaderStream =
new HTTPHeaderInputStream(proc.getInputStream());
cgiHeaderReader =
new BufferedReader(new InputStreamReader(cgiHeaderStream));
while (isRunning) {
try {
//set headers
String line = null;
while (((line = cgiHeaderReader.readLine()) != null)
&& !("".equals(line))) {
if (debug >= 2) {
log("runCGI: addHeader(\"" + line + "\")");
}
if (line.startsWith("HTTP")) {
response.setStatus(getSCFromHttpStatusLine(line));
} else if (line.indexOf(":") >= 0) {
String header =
line.substring(0, line.indexOf(":")).trim();
String value =
line.substring(line.indexOf(":") + 1).trim();
if (header.equalsIgnoreCase("status")) {
response.setStatus(getSCFromCGIStatusHeader(value));
} else {
response.addHeader(header , value);
}
} else {
log("runCGI: bad header line \"" + line + "\"");
}
}
//write output
byte[] bBuf = new byte[2048];
OutputStream out = response.getOutputStream();
cgiOutput = proc.getInputStream();
try {
while ((bufRead = cgiOutput.read(bBuf)) != -1) {
if (debug >= 4) {
log("runCGI: output " + bufRead +
" bytes of data");
}
out.write(bBuf, 0, bufRead);
}
} finally {
// Attempt to consume any leftover byte if something bad happens,
// such as a socket disconnect on the servlet side; otherwise, the
// external process could hang
if (bufRead != -1) {
while ((bufRead = cgiOutput.read(bBuf)) != -1) {
// NOOP - just read the data
}
}
}
proc.exitValue(); // Throws exception if alive
isRunning = false;
} catch (IllegalThreadStateException e) {
try {
Thread.sleep(500);
} catch (InterruptedException ignored) {
// Ignore
}
}
} //replacement for Process.waitFor()
}
catch (IOException e){
log ("Caught exception " + e);
throw e;
}
finally{
// Close the header reader
if (cgiHeaderReader != null) {
try {
cgiHeaderReader.close();
} catch (IOException ioe) {
log ("Exception closing header reader " + ioe);
}
}
// Close the output stream if used
if (cgiOutput != null) {
try {
cgiOutput.close();
} catch (IOException ioe) {
log ("Exception closing output stream " + ioe);
}
}
// Make sure the error stream reader has finished
if (errReaderThread != null) {
try {
errReaderThread.join(stderrTimeout);
} catch (InterruptedException e) {
log ("Interupted waiting for stderr reader thread");
}
}
if (debug > 4) {
log ("Running finally block");
}
if (proc != null){
proc.destroy();
proc = null;
}
}
}
// in java/org/apache/catalina/servlets/CGIServlet.java
Override
public int read() throws IOException {
if (state == STATE_HEADER_END) {
return -1;
}
int i = input.read();
// Update the state
// State machine looks like this
//
// -------->--------
// | (CR) |
// | |
// CR1--->--- |
// | | |
// ^(CR) |(LF) |
// | | |
// CHAR--->--LF1--->--EOH
// (LF) | (LF) |
// |(CR) ^(LF)
// | |
// (CR2)-->---
if (i == 10) {
// LF
switch(state) {
case STATE_CHARACTER:
state = STATE_FIRST_LF;
break;
case STATE_FIRST_CR:
state = STATE_FIRST_LF;
break;
case STATE_FIRST_LF:
case STATE_SECOND_CR:
state = STATE_HEADER_END;
break;
}
} else if (i == 13) {
// CR
switch(state) {
case STATE_CHARACTER:
state = STATE_FIRST_CR;
break;
case STATE_FIRST_CR:
state = STATE_HEADER_END;
break;
case STATE_FIRST_LF:
state = STATE_SECOND_CR;
break;
}
} else {
state = STATE_CHARACTER;
}
return i;
}
// in java/org/apache/catalina/ha/session/SerializablePrincipal.java
public static GenericPrincipal readPrincipal(ObjectInput in)
throws IOException, ClassNotFoundException {
String name = in.readUTF();
boolean hasPwd = in.readBoolean();
String pwd = null;
if ( hasPwd ) pwd = in.readUTF();
int size = in.readInt();
String[] roles = new String[size];
for ( int i=0; i<size; i++ ) roles[i] = in.readUTF();
Principal userPrincipal = null;
boolean hasUserPrincipal = in.readBoolean();
if (hasUserPrincipal) {
try {
userPrincipal = (Principal) in.readObject();
} catch (ClassNotFoundException e) {
log.error(sm.getString(
"serializablePrincipal.readPrincipal.cnfe"), e);
throw e;
}
}
return new GenericPrincipal(name,pwd,Arrays.asList(roles),
userPrincipal);
}
// in java/org/apache/catalina/ha/session/SerializablePrincipal.java
public static void writePrincipal(GenericPrincipal p, ObjectOutput out)
throws IOException {
out.writeUTF(p.getName());
out.writeBoolean(p.getPassword()!=null);
if ( p.getPassword()!= null ) out.writeUTF(p.getPassword());
String[] roles = p.getRoles();
if ( roles == null ) roles = new String[0];
out.writeInt(roles.length);
for ( int i=0; i<roles.length; i++ ) out.writeUTF(roles[i]);
boolean hasUserPrincipal = (p != p.getUserPrincipal() &&
p.getUserPrincipal() instanceof Serializable);
out.writeBoolean(hasUserPrincipal);
if (hasUserPrincipal) out.writeObject(p.getUserPrincipal());
}
// in java/org/apache/catalina/ha/session/JvmRouteBinderValve.java
Override
public void invoke(Request request, Response response) throws IOException,
ServletException {
if (getEnabled() &&
request.getContext() != null &&
request.getContext().getDistributable() &&
!request.isAsyncDispatching()) {
// valve cluster can access manager - other cluster handle turnover
// at host level - hopefully!
Manager manager = request.getContext().getManager();
if (manager != null && (
(manager instanceof ClusterManager
&& getCluster() != null
&& getCluster().getManager(((ClusterManager)manager).getName()) != null)
||
(manager instanceof PersistentManager))) {
handlePossibleTurnover(request);
}
}
// Pass this request on to the next valve in our pipeline
getNext().invoke(request, response);
}
// in java/org/apache/catalina/ha/session/DeltaSession.java
Override
public byte[] getDiff() throws IOException {
try{
lock();
return getDeltaRequest().serialize();
}finally{
unlock();
}
}
// in java/org/apache/catalina/ha/session/DeltaSession.java
Override
public void applyDiff(byte[] diff, int offset, int length) throws IOException, ClassNotFoundException {
try {
lock();
ReplicationStream stream = ( (ClusterManager) getManager()).getReplicationStream(diff, offset, length);
ClassLoader contextLoader = Thread.currentThread().getContextClassLoader();
try {
ClassLoader[] loaders = getClassLoaders();
if (loaders != null && loaders.length > 0)
Thread.currentThread().setContextClassLoader(loaders[0]);
getDeltaRequest().readExternal(stream);
getDeltaRequest().execute(this, ((ClusterManager)getManager()).isNotifyListenersOnReplication());
} finally {
Thread.currentThread().setContextClassLoader(contextLoader);
}
}finally {
unlock();
}
}
// in java/org/apache/catalina/ha/session/DeltaSession.java
Override
public void readExternal(ObjectInput in) throws IOException,ClassNotFoundException {
try {
lock();
readObjectData(in);
}finally{
unlock();
}
}
// in java/org/apache/catalina/ha/session/DeltaSession.java
Override
public void readObjectData(ObjectInputStream stream) throws ClassNotFoundException, IOException {
readObject((ObjectInput)stream);
}
// in java/org/apache/catalina/ha/session/DeltaSession.java
public void readObjectData(ObjectInput stream) throws ClassNotFoundException, IOException {
readObject(stream);
}
// in java/org/apache/catalina/ha/session/DeltaSession.java
Override
public void writeObjectData(ObjectOutputStream stream) throws IOException {
writeObjectData((ObjectOutput)stream);
}
// in java/org/apache/catalina/ha/session/DeltaSession.java
public void writeObjectData(ObjectOutput stream) throws IOException {
writeObject(stream);
}
// in java/org/apache/catalina/ha/session/DeltaSession.java
Override
protected void readObject(ObjectInputStream stream) throws ClassNotFoundException, IOException {
readObject((ObjectInput)stream);
}
// in java/org/apache/catalina/ha/session/DeltaSession.java
private void readObject(ObjectInput stream) throws ClassNotFoundException, IOException {
// Deserialize the scalar instance variables (except Manager)
authType = null; // Transient only
creationTime = ( (Long) stream.readObject()).longValue();
lastAccessedTime = ( (Long) stream.readObject()).longValue();
maxInactiveInterval = ( (Integer) stream.readObject()).intValue();
isNew = ( (Boolean) stream.readObject()).booleanValue();
isValid = ( (Boolean) stream.readObject()).booleanValue();
thisAccessedTime = ( (Long) stream.readObject()).longValue();
version = ( (Long) stream.readObject()).longValue();
boolean hasPrincipal = stream.readBoolean();
principal = null;
if (hasPrincipal) {
principal = SerializablePrincipal.readPrincipal(stream);
}
// setId((String) stream.readObject());
id = (String) stream.readObject();
if (log.isDebugEnabled()) log.debug(sm.getString("deltaSession.readSession", id));
// Deserialize the attribute count and attribute values
if (attributes == null) attributes = new ConcurrentHashMap<String, Object>();
int n = ( (Integer) stream.readObject()).intValue();
boolean isValidSave = isValid;
isValid = true;
for (int i = 0; i < n; i++) {
String name = (String) stream.readObject();
Object value = stream.readObject();
if ( (value instanceof String) && (value.equals(NOT_SERIALIZED)))
continue;
attributes.put(name, value);
}
isValid = isValidSave;
if (listeners == null) {
ArrayList<SessionListener> arrayList =
new ArrayList<SessionListener>();
listeners = arrayList;
}
if (notes == null) {
notes = new Hashtable<String,Object>();
}
activate();
}
// in java/org/apache/catalina/ha/session/DeltaSession.java
Override
public void writeExternal(ObjectOutput out ) throws java.io.IOException {
try {
lock();
writeObject(out);
}finally {
unlock();
}
}
// in java/org/apache/catalina/ha/session/DeltaSession.java
Override
protected void writeObject(ObjectOutputStream stream) throws IOException {
writeObject((ObjectOutput)stream);
}
// in java/org/apache/catalina/ha/session/DeltaSession.java
private void writeObject(ObjectOutput stream) throws IOException {
// Write the scalar instance variables (except Manager)
stream.writeObject(Long.valueOf(creationTime));
stream.writeObject(Long.valueOf(lastAccessedTime));
stream.writeObject(Integer.valueOf(maxInactiveInterval));
stream.writeObject(Boolean.valueOf(isNew));
stream.writeObject(Boolean.valueOf(isValid));
stream.writeObject(Long.valueOf(thisAccessedTime));
stream.writeObject(Long.valueOf(version));
stream.writeBoolean(getPrincipal() != null);
if (getPrincipal() != null) {
SerializablePrincipal.writePrincipal((GenericPrincipal) principal,stream);
}
stream.writeObject(id);
if (log.isDebugEnabled()) log.debug(sm.getString("deltaSession.writeSession", id));
// Accumulate the names of serializable and non-serializable attributes
String keys[] = keys();
ArrayList<String> saveNames = new ArrayList<String>();
ArrayList<Object> saveValues = new ArrayList<Object>();
for (int i = 0; i < keys.length; i++) {
Object value = null;
value = attributes.get(keys[i]);
if (value == null || exclude(keys[i]))
continue;
else if (value instanceof Serializable) {
saveNames.add(keys[i]);
saveValues.add(value);
}
}
// Serialize the attribute count and the Serializable attributes
int n = saveNames.size();
stream.writeObject(Integer.valueOf(n));
for (int i = 0; i < n; i++) {
stream.writeObject( saveNames.get(i));
try {
stream.writeObject(saveValues.get(i));
} catch (NotSerializableException e) {
log.error(sm.getString("standardSession.notSerializable",saveNames.get(i), id), e);
stream.writeObject(NOT_SERIALIZED);
log.error(" storing attribute '" + saveNames.get(i)+ "' with value NOT_SERIALIZED");
}
}
}
// in java/org/apache/catalina/ha/session/ClusterManagerBase.java
Override
public ReplicationStream getReplicationStream(byte[] data) throws IOException {
return getReplicationStream(data,0,data.length);
}
// in java/org/apache/catalina/ha/session/ClusterManagerBase.java
Override
public ReplicationStream getReplicationStream(byte[] data, int offset, int length) throws IOException {
ByteArrayInputStream fis = new ByteArrayInputStream(data, offset, length);
return new ReplicationStream(fis, getClassLoaders());
}
// in java/org/apache/catalina/ha/session/DeltaRequest.java
Override
public void readExternal(java.io.ObjectInput in) throws IOException,ClassNotFoundException {
//sessionId - String
//recordAll - boolean
//size - int
//AttributeInfo - in an array
reset();
sessionId = in.readUTF();
recordAllActions = in.readBoolean();
int cnt = in.readInt();
if (actions == null)
actions = new LinkedList<AttributeInfo>();
else
actions.clear();
for (int i = 0; i < cnt; i++) {
AttributeInfo info = null;
if (this.actionPool.size() > 0) {
try {
info = actionPool.removeFirst();
} catch ( Exception x ) {
log.error("Unable to remove element",x);
info = new AttributeInfo();
}
}
else {
info = new AttributeInfo();
}
info.readExternal(in);
actions.addLast(info);
}//for
}
// in java/org/apache/catalina/ha/session/DeltaRequest.java
Override
public void writeExternal(java.io.ObjectOutput out ) throws java.io.IOException {
//sessionId - String
//recordAll - boolean
//size - int
//AttributeInfo - in an array
out.writeUTF(getSessionId());
out.writeBoolean(recordAllActions);
out.writeInt(getSize());
for ( int i=0; i<getSize(); i++ ) {
AttributeInfo info = actions.get(i);
info.writeExternal(out);
}
}
// in java/org/apache/catalina/ha/session/DeltaRequest.java
protected byte[] serialize() throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
writeExternal(oos);
oos.flush();
oos.close();
return bos.toByteArray();
}
// in java/org/apache/catalina/ha/session/DeltaRequest.java
Override
public void readExternal(java.io.ObjectInput in ) throws IOException,ClassNotFoundException {
//type - int
//action - int
//name - String
//hasvalue - boolean
//value - object
type = in.readInt();
action = in.readInt();
name = in.readUTF();
boolean hasValue = in.readBoolean();
if ( hasValue ) value = in.readObject();
}
// in java/org/apache/catalina/ha/session/DeltaRequest.java
Override
public void writeExternal(java.io.ObjectOutput out) throws IOException {
//type - int
//action - int
//name - String
//hasvalue - boolean
//value - object
out.writeInt(getType());
out.writeInt(getAction());
out.writeUTF(getName());
out.writeBoolean(getValue()!=null);
if (getValue()!=null) out.writeObject(getValue());
}
// in java/org/apache/catalina/ha/session/DeltaManager.java
protected byte[] serializeSessionId(String sessionId) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeUTF(sessionId);
oos.flush();
oos.close();
return bos.toByteArray();
}
// in java/org/apache/catalina/ha/session/DeltaManager.java
protected String deserializeSessionId(byte[] data) throws IOException {
ReplicationStream ois = getReplicationStream(data);
String sessionId = ois.readUTF();
ois.close();
return sessionId;
}
// in java/org/apache/catalina/ha/session/DeltaManager.java
protected DeltaRequest deserializeDeltaRequest(DeltaSession session, byte[] data) throws ClassNotFoundException, IOException {
try {
session.lock();
ReplicationStream ois = getReplicationStream(data);
session.getDeltaRequest().readExternal(ois);
ois.close();
return session.getDeltaRequest();
}finally {
session.unlock();
}
}
// in java/org/apache/catalina/ha/session/DeltaManager.java
protected byte[] serializeDeltaRequest(DeltaSession session, DeltaRequest deltaRequest) throws IOException {
try {
session.lock();
return deltaRequest.serialize();
}finally {
session.unlock();
}
}
// in java/org/apache/catalina/ha/session/DeltaManager.java
protected void deserializeSessions(byte[] data) throws ClassNotFoundException,IOException {
// Initialize our internal data structures
//sessions.clear(); //should not do this
// Open an input stream to the specified pathname, if any
ClassLoader originalLoader = Thread.currentThread().getContextClassLoader();
ObjectInputStream ois = null;
// Load the previously unloaded active sessions
try {
ois = getReplicationStream(data);
Integer count = (Integer) ois.readObject();
int n = count.intValue();
for (int i = 0; i < n; i++) {
DeltaSession session = (DeltaSession) createEmptySession();
session.readObjectData(ois);
session.setManager(this);
session.setValid(true);
session.setPrimarySession(false);
//in case the nodes in the cluster are out of
//time synch, this will make sure that we have the
//correct timestamp, isValid returns true, cause
// accessCount=1
session.access();
//make sure that the session gets ready to expire if
// needed
session.setAccessCount(0);
session.resetDeltaRequest();
// FIXME How inform other session id cache like SingleSignOn
// increment sessionCounter to correct stats report
if (findSession(session.getIdInternal()) == null ) {
sessionCounter++;
} else {
sessionReplaceCounter++;
// FIXME better is to grap this sessions again !
if (log.isWarnEnabled()) log.warn(sm.getString("deltaManager.loading.existing.session",session.getIdInternal()));
}
add(session);
if (notifySessionListenersOnReplication) {
session.tellNew();
}
}
} catch (ClassNotFoundException e) {
log.error(sm.getString("deltaManager.loading.cnfe", e), e);
throw e;
} catch (IOException e) {
log.error(sm.getString("deltaManager.loading.ioe", e), e);
throw e;
} finally {
// Close the input stream
try {
if (ois != null) ois.close();
} catch (IOException f) {
// ignored
}
ois = null;
if (originalLoader != null) Thread.currentThread().setContextClassLoader(originalLoader);
}
}
// in java/org/apache/catalina/ha/session/DeltaManager.java
protected byte[] serializeSessions(Session[] currentSessions) throws IOException {
// Open an output stream to the specified pathname, if any
ByteArrayOutputStream fos = null;
ObjectOutputStream oos = null;
try {
fos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(new BufferedOutputStream(fos));
oos.writeObject(Integer.valueOf(currentSessions.length));
for(int i=0 ; i < currentSessions.length;i++) {
((DeltaSession)currentSessions[i]).writeObjectData(oos);
}
// Flush and close the output stream
oos.flush();
} catch (IOException e) {
log.error(sm.getString("deltaManager.unloading.ioe", e), e);
throw e;
} finally {
if (oos != null) {
try {
oos.close();
} catch (IOException f) {
// Ignore
}
oos = null;
}
}
// send object data as byte[]
return fos.toByteArray();
}
// in java/org/apache/catalina/ha/session/DeltaManager.java
protected void handleSESSION_DELTA(SessionMessage msg, Member sender) throws IOException, ClassNotFoundException {
counterReceive_EVT_SESSION_DELTA++;
byte[] delta = msg.getSession();
DeltaSession session = (DeltaSession) findSession(msg.getSessionID());
if (session != null) {
if (log.isDebugEnabled()) log.debug(sm.getString("deltaManager.receiveMessage.delta",getName(), msg.getSessionID()));
try {
session.lock();
DeltaRequest dreq = deserializeDeltaRequest(session, delta);
dreq.execute(session, isNotifyListenersOnReplication());
session.setPrimarySession(false);
}finally {
session.unlock();
}
}
}
// in java/org/apache/catalina/ha/session/DeltaManager.java
protected void handleSESSION_ACCESSED(SessionMessage msg,Member sender) throws IOException {
counterReceive_EVT_SESSION_ACCESSED++;
DeltaSession session = (DeltaSession) findSession(msg.getSessionID());
if (session != null) {
if (log.isDebugEnabled()) log.debug(sm.getString("deltaManager.receiveMessage.accessed",getName(), msg.getSessionID()));
session.access();
session.setPrimarySession(false);
session.endAccess();
}
}
// in java/org/apache/catalina/ha/session/DeltaManager.java
protected void handleSESSION_EXPIRED(SessionMessage msg,Member sender) throws IOException {
counterReceive_EVT_SESSION_EXPIRED++;
DeltaSession session = (DeltaSession) findSession(msg.getSessionID());
if (session != null) {
if (log.isDebugEnabled()) log.debug(sm.getString("deltaManager.receiveMessage.expired",getName(), msg.getSessionID()));
session.expire(notifySessionListenersOnReplication, false);
}
}
// in java/org/apache/catalina/ha/session/DeltaManager.java
protected void handleALL_SESSION_DATA(SessionMessage msg,Member sender) throws ClassNotFoundException, IOException {
counterReceive_EVT_ALL_SESSION_DATA++;
if (log.isDebugEnabled()) log.debug(sm.getString("deltaManager.receiveMessage.allSessionDataBegin",getName()));
byte[] data = msg.getSession();
deserializeSessions(data);
if (log.isDebugEnabled()) log.debug(sm.getString("deltaManager.receiveMessage.allSessionDataAfter",getName()));
//stateTransferred = true;
}
// in java/org/apache/catalina/ha/session/DeltaManager.java
protected void handleGET_ALL_SESSIONS(SessionMessage msg, Member sender) throws IOException {
counterReceive_EVT_GET_ALL_SESSIONS++;
//get a list of all the session from this manager
if (log.isDebugEnabled()) log.debug(sm.getString("deltaManager.receiveMessage.unloadingBegin", getName()));
// Write the number of active sessions, followed by the details
// get all sessions and serialize without sync
Session[] currentSessions = findSessions();
long findSessionTimestamp = System.currentTimeMillis() ;
if (isSendAllSessions()) {
sendSessions(sender, currentSessions, findSessionTimestamp);
} else {
// send session at blocks
for (int i = 0; i < currentSessions.length; i += getSendAllSessionsSize()) {
int len = i + getSendAllSessionsSize() > currentSessions.length ? currentSessions.length - i : getSendAllSessionsSize();
Session[] sendSessions = new Session[len];
System.arraycopy(currentSessions, i, sendSessions, 0, len);
sendSessions(sender, sendSessions,findSessionTimestamp);
if (getSendAllSessionsWaitTime() > 0) {
try {
Thread.sleep(getSendAllSessionsWaitTime());
} catch (Exception sleep) {
}
}//end if
}//for
}//end if
SessionMessage newmsg = new SessionMessageImpl(name,SessionMessage.EVT_ALL_SESSION_TRANSFERCOMPLETE, null,"SESSION-STATE-TRANSFERED", "SESSION-STATE-TRANSFERED"+ getName());
newmsg.setTimestamp(findSessionTimestamp);
if (log.isDebugEnabled()) log.debug(sm.getString("deltaManager.createMessage.allSessionTransfered",getName()));
counterSend_EVT_ALL_SESSION_TRANSFERCOMPLETE++;
cluster.send(newmsg, sender);
}
// in java/org/apache/catalina/ha/session/DeltaManager.java
protected void handleCHANGE_SESSION_ID(SessionMessage msg,Member sender) throws IOException {
counterReceive_EVT_CHANGE_SESSION_ID++;
DeltaSession session = (DeltaSession) findSession(msg.getSessionID());
if (session != null) {
String newSessionID = deserializeSessionId(msg.getSession());
session.setPrimarySession(false);
session.setId(newSessionID, false);
if (notifyContainerListenersOnReplication) {
getContainer().fireContainerEvent(Context.CHANGE_SESSION_ID_EVENT,
new String[] {msg.getSessionID(), newSessionID});
}
}
}
// in java/org/apache/catalina/ha/session/DeltaManager.java
protected void sendSessions(Member sender, Session[] currentSessions,long sendTimestamp) throws IOException {
byte[] data = serializeSessions(currentSessions);
if (log.isDebugEnabled()) log.debug(sm.getString("deltaManager.receiveMessage.unloadingAfter",getName()));
SessionMessage newmsg = new SessionMessageImpl(name,SessionMessage.EVT_ALL_SESSION_DATA, data,"SESSION-STATE", "SESSION-STATE-" + getName());
newmsg.setTimestamp(sendTimestamp);
if (log.isDebugEnabled()) log.debug(sm.getString("deltaManager.createMessage.allSessionData",getName()));
counterSend_EVT_ALL_SESSION_DATA++;
cluster.send(newmsg, sender);
}
// in java/org/apache/catalina/ha/deploy/FileMessageFactory.java
public static FileMessageFactory getInstance(File f, boolean openForWrite)
throws FileNotFoundException, IOException {
return new FileMessageFactory(f, openForWrite);
}
// in java/org/apache/catalina/ha/deploy/FileMessageFactory.java
public FileMessage readMessage(FileMessage f)
throws IllegalArgumentException, IOException {
checkState(false);
int length = in.read(data);
if (length == -1) {
cleanup();
return null;
} else {
f.setData(data, length);
f.setTotalLength(size);
f.setTotalNrOfMsgs(totalNrOfMessages);
f.setMessageNumber(++nrOfMessagesProcessed);
return f;
}//end if
}
// in java/org/apache/catalina/ha/deploy/FileMessageFactory.java
public boolean writeMessage(FileMessage msg)
throws IllegalArgumentException, IOException {
if (!openForWrite)
throw new IllegalArgumentException(
"Can't write message, this factory is reading.");
if (log.isDebugEnabled())
log.debug("Message " + msg + " data " + HexUtils.toHexString(msg.getData())
+ " data length " + msg.getDataLength() + " out " + out);
if (msg.getMessageNumber() <= lastMessageProcessed.get()) {
// Duplicate of message already processed
log.warn("Receive Message again -- Sender ActTimeout too short [ name: "
+ msg.getContextName()
+ " war: "
+ msg.getFileName()
+ " data: "
+ HexUtils.toHexString(msg.getData())
+ " data length: " + msg.getDataLength() + " ]");
return false;
}
FileMessage previous =
msgBuffer.put(Long.valueOf(msg.getMessageNumber()), msg);
if (previous !=null) {
// Duplicate of message not yet processed
log.warn("Receive Message again -- Sender ActTimeout too short [ name: "
+ msg.getContextName()
+ " war: "
+ msg.getFileName()
+ " data: "
+ HexUtils.toHexString(msg.getData())
+ " data length: " + msg.getDataLength() + " ]");
return false;
}
FileMessage next = null;
synchronized (this) {
if (!isWriting) {
next = msgBuffer.get(Long.valueOf(lastMessageProcessed.get() + 1));
if (next != null) {
isWriting = true;
} else {
return false;
}
} else {
return false;
}
}
while (next != null) {
out.write(next.getData(), 0, next.getDataLength());
lastMessageProcessed.incrementAndGet();
out.flush();
if (next.getMessageNumber() == next.getTotalNrOfMsgs()) {
out.close();
cleanup();
return true;
}
synchronized(this) {
next =
msgBuffer.get(Long.valueOf(lastMessageProcessed.get() + 1));
if (next == null) {
isWriting = false;
}
}
}
return false;
}
// in java/org/apache/catalina/ha/deploy/FarmWarDeployer.java
public synchronized FileMessageFactory getFactory(FileMessage msg)
throws java.io.FileNotFoundException, java.io.IOException {
File writeToFile = new File(getTempDir(), msg.getFileName());
FileMessageFactory factory = fileFactories.get(msg.getFileName());
if (factory == null) {
factory = FileMessageFactory.getInstance(writeToFile, true);
fileFactories.put(msg.getFileName(), factory);
}
return factory;
}
// in java/org/apache/catalina/ha/deploy/FarmWarDeployer.java
Override
public void install(String contextName, File webapp) throws IOException {
Member[] members = getCluster().getMembers();
Member localMember = getCluster().getLocalMember();
FileMessageFactory factory =
FileMessageFactory.getInstance(webapp, false);
FileMessage msg = new FileMessage(localMember, webapp.getName(),
contextName);
if(log.isDebugEnabled())
log.debug(sm.getString("farmWarDeployer.sendStart", contextName,
webapp));
msg = factory.readMessage(msg);
while (msg != null) {
for (int i = 0; i < members.length; i++) {
if (log.isDebugEnabled())
log.debug(sm.getString("farmWarDeployer.sendFragment",
contextName, webapp, members[i]));
getCluster().send(msg, members[i]);
}
msg = factory.readMessage(msg);
}
if(log.isDebugEnabled())
log.debug(sm.getString(
"farmWarDeployer.sendEnd", contextName, webapp));
}
// in java/org/apache/catalina/ha/deploy/FarmWarDeployer.java
Override
public void remove(String contextName, boolean undeploy)
throws IOException {
if (log.isInfoEnabled())
log.info(sm.getString("farmWarDeployer.removeStart", contextName));
Member localMember = getCluster().getLocalMember();
UndeployMessage msg = new UndeployMessage(localMember, System
.currentTimeMillis(), "Undeploy:" + contextName + ":"
+ System.currentTimeMillis(), contextName, undeploy);
if (log.isDebugEnabled())
log.debug(sm.getString("farmWarDeployer.removeTxMsg", contextName));
cluster.send(msg);
// remove locally
if (undeploy) {
try {
if (!isServiced(contextName)) {
addServiced(contextName);
try {
remove(contextName);
} finally {
removeServiced(contextName);
}
} else
log.error(sm.getString("farmWarDeployer.removeFailRemote",
contextName));
} catch (Exception ex) {
log.error(sm.getString("farmWarDeployer.removeFailLocal",
contextName), ex);
}
}
}
// in java/org/apache/catalina/ha/tcp/ReplicationValve.java
Override
public void invoke(Request request, Response response)
throws IOException, ServletException
{
long totalstart = 0;
//this happens before the request
if(doStatistics()) {
totalstart = System.currentTimeMillis();
}
if (primaryIndicator) {
createPrimaryIndicator(request) ;
}
Context context = request.getContext();
boolean isCrossContext = context != null
&& context instanceof StandardContext
&& ((StandardContext) context).getCrossContext();
try {
if(isCrossContext) {
if(log.isDebugEnabled()) {
log.debug(sm.getString("ReplicationValve.crossContext.add"));
}
//FIXME add Pool of Arraylists
crossContextSessions.set(new ArrayList<DeltaSession>());
}
getNext().invoke(request, response);
if(context != null) {
Manager manager = context.getManager();
if (manager != null && manager instanceof ClusterManager) {
ClusterManager clusterManager = (ClusterManager) manager;
CatalinaCluster containerCluster = (CatalinaCluster) getContainer().getCluster();
if (containerCluster == null) {
if (log.isWarnEnabled()) {
log.warn(sm.getString("ReplicationValve.nocluster"));
}
return;
}
// valve cluster can access manager - other cluster handle replication
// at host level - hopefully!
if(containerCluster.getManager(clusterManager.getName()) == null) {
return ;
}
if(containerCluster.hasMembers()) {
sendReplicationMessage(request, totalstart, isCrossContext, clusterManager, containerCluster);
} else {
resetReplicationRequest(request,isCrossContext);
}
}
}
} finally {
// Array must be remove: Current master request send endAccess at recycle.
// Don't register this request session again!
if(isCrossContext) {
if(log.isDebugEnabled()) {
log.debug(sm.getString("ReplicationValve.crossContext.remove"));
}
// crossContextSessions.remove() only exist at Java 5
// register ArrayList at a pool
crossContextSessions.set(null);
}
}
}
// in java/org/apache/catalina/ha/tcp/ReplicationValve.java
protected void createPrimaryIndicator(Request request) throws IOException {
String id = request.getRequestedSessionId();
if ((id != null) && (id.length() > 0)) {
Manager manager = request.getContext().getManager();
Session session = manager.findSession(id);
if (session instanceof ClusterSession) {
ClusterSession cses = (ClusterSession) session;
if (log.isDebugEnabled()) {
log.debug(sm.getString(
"ReplicationValve.session.indicator", request.getContext().getName(),id,
primaryIndicatorName,
Boolean.valueOf(cses.isPrimarySession())));
}
request.setAttribute(primaryIndicatorName, cses.isPrimarySession()?Boolean.TRUE:Boolean.FALSE);
} else {
if (log.isDebugEnabled()) {
if (session != null) {
log.debug(sm.getString(
"ReplicationValve.session.found", request.getContext().getName(),id));
} else {
log.debug(sm.getString(
"ReplicationValve.session.invalid", request.getContext().getName(),id));
}
}
}
}
}
// in java/org/apache/catalina/ssi/SSIFilter.java
Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// cast once
HttpServletRequest req = (HttpServletRequest)request;
HttpServletResponse res = (HttpServletResponse)response;
// indicate that we're in SSI processing
req.setAttribute(Globals.SSI_FLAG_ATTR, "true");
// setup to capture output
ByteArrayServletOutputStream basos = new ByteArrayServletOutputStream();
ResponseIncludeWrapper responseIncludeWrapper =
new ResponseIncludeWrapper(config.getServletContext(),req, res, basos);
// process remainder of filter chain
chain.doFilter(req, responseIncludeWrapper);
// we can't assume the chain flushed its output
responseIncludeWrapper.flushOutputStreamOrWriter();
byte[] bytes = basos.toByteArray();
// get content type
String contentType = responseIncludeWrapper.getContentType();
// is this an allowed type for SSI processing?
if (contentTypeRegEx.matcher(contentType).matches()) {
String encoding = res.getCharacterEncoding();
// set up SSI processing
SSIExternalResolver ssiExternalResolver =
new SSIServletExternalResolver(config.getServletContext(), req,
res, isVirtualWebappRelative, debug, encoding);
SSIProcessor ssiProcessor = new SSIProcessor(ssiExternalResolver,
debug, allowExec);
// prepare readers/writers
Reader reader =
new InputStreamReader(new ByteArrayInputStream(bytes), encoding);
ByteArrayOutputStream ssiout = new ByteArrayOutputStream();
PrintWriter writer =
new PrintWriter(new OutputStreamWriter(ssiout, encoding));
// do SSI processing
long lastModified = ssiProcessor.process(reader,
responseIncludeWrapper.getLastModified(), writer);
// set output bytes
writer.flush();
bytes = ssiout.toByteArray();
// override headers
if (expires != null) {
res.setDateHeader("expires", (new java.util.Date()).getTime()
+ expires.longValue() * 1000);
}
if (lastModified > 0) {
res.setDateHeader("last-modified", lastModified);
}
res.setContentLength(bytes.length);
Matcher shtmlMatcher =
shtmlRegEx.matcher(responseIncludeWrapper.getContentType());
if (shtmlMatcher.matches()) {
// Convert shtml mime type to ordinary html mime type but preserve
// encoding, if any.
String enc = shtmlMatcher.group(1);
res.setContentType("text/html" + ((enc != null) ? enc : ""));
}
}
// write output
OutputStream out = null;
try {
out = res.getOutputStream();
} catch (IllegalStateException e) {
// Ignore, will try to use a writer
}
if (out == null) {
res.getWriter().write(new String(bytes));
} else {
out.write(bytes);
}
}
// in java/org/apache/catalina/ssi/SSIServletExternalResolver.java
protected String getAbsolutePath(String path) throws IOException {
String pathWithoutContext = SSIServletRequestUtil.getRelativePath(req);
String prefix = getPathWithoutFileName(pathWithoutContext);
if (prefix == null) {
throw new IOException("Couldn't remove filename from path: "
+ pathWithoutContext);
}
String fullPath = prefix + path;
String retVal = RequestUtil.normalize(fullPath);
if (retVal == null) {
throw new IOException("Normalization yielded null on path: "
+ fullPath);
}
return retVal;
}
// in java/org/apache/catalina/ssi/SSIServletExternalResolver.java
protected ServletContextAndPath getServletContextAndPathFromNonVirtualPath(
String nonVirtualPath) throws IOException {
if (nonVirtualPath.startsWith("/") || nonVirtualPath.startsWith("\\")) {
throw new IOException("A non-virtual path can't be absolute: "
+ nonVirtualPath);
}
if (nonVirtualPath.indexOf("../") >= 0) {
throw new IOException("A non-virtual path can't contain '../' : "
+ nonVirtualPath);
}
String path = getAbsolutePath(nonVirtualPath);
ServletContextAndPath csAndP = new ServletContextAndPath(
context, path);
return csAndP;
}
// in java/org/apache/catalina/ssi/SSIServletExternalResolver.java
protected ServletContextAndPath getServletContextAndPathFromVirtualPath(
String virtualPath) throws IOException {
if (!virtualPath.startsWith("/") && !virtualPath.startsWith("\\")) {
return new ServletContextAndPath(context,
getAbsolutePath(virtualPath));
}
String normalized = RequestUtil.normalize(virtualPath);
if (isVirtualWebappRelative) {
return new ServletContextAndPath(context, normalized);
}
ServletContext normContext = context.getContext(normalized);
if (normContext == null) {
throw new IOException("Couldn't get context for path: "
+ normalized);
}
//If it's the root context, then there is no context element
// to remove,
// ie:
// '/file1.shtml' vs '/appName1/file1.shtml'
if (!isRootContext(normContext)) {
String noContext = getPathWithoutContext(
normContext.getContextPath(), normalized);
if (noContext == null) {
throw new IOException(
"Couldn't remove context from path: "
+ normalized);
}
return new ServletContextAndPath(normContext, noContext);
}
return new ServletContextAndPath(normContext, normalized);
}
// in java/org/apache/catalina/ssi/SSIServletExternalResolver.java
protected ServletContextAndPath getServletContextAndPath(
String originalPath, boolean virtual) throws IOException {
ServletContextAndPath csAndP = null;
if (debug > 0) {
log("SSIServletExternalResolver.getServletContextAndPath( "
+ originalPath + ", " + virtual + ")", null);
}
if (virtual) {
csAndP = getServletContextAndPathFromVirtualPath(originalPath);
} else {
csAndP = getServletContextAndPathFromNonVirtualPath(originalPath);
}
return csAndP;
}
// in java/org/apache/catalina/ssi/SSIServletExternalResolver.java
protected URLConnection getURLConnection(String originalPath,
boolean virtual) throws IOException {
ServletContextAndPath csAndP = getServletContextAndPath(originalPath,
virtual);
ServletContext context = csAndP.getServletContext();
String path = csAndP.getPath();
URL url = context.getResource(path);
if (url == null) {
throw new IOException("Context did not contain resource: " + path);
}
URLConnection urlConnection = url.openConnection();
return urlConnection;
}
// in java/org/apache/catalina/ssi/SSIServletExternalResolver.java
Override
public long getFileLastModified(String path, boolean virtual)
throws IOException {
long lastModified = 0;
try {
URLConnection urlConnection = getURLConnection(path, virtual);
lastModified = urlConnection.getLastModified();
} catch (IOException e) {
// Ignore this. It will always fail for non-file based includes
}
return lastModified;
}
// in java/org/apache/catalina/ssi/SSIServletExternalResolver.java
Override
public long getFileSize(String path, boolean virtual) throws IOException {
long fileSize = -1;
try {
URLConnection urlConnection = getURLConnection(path, virtual);
fileSize = urlConnection.getContentLength();
} catch (IOException e) {
// Ignore this. It will always fail for non-file based includes
}
return fileSize;
}
// in java/org/apache/catalina/ssi/SSIServletExternalResolver.java
Override
public String getFileText(String originalPath, boolean virtual)
throws IOException {
try {
ServletContextAndPath csAndP = getServletContextAndPath(
originalPath, virtual);
ServletContext context = csAndP.getServletContext();
String path = csAndP.getPath();
RequestDispatcher rd = context.getRequestDispatcher(path);
if (rd == null) {
throw new IOException(
"Couldn't get request dispatcher for path: " + path);
}
ByteArrayServletOutputStream basos =
new ByteArrayServletOutputStream();
ResponseIncludeWrapper responseIncludeWrapper =
new ResponseIncludeWrapper(context, req, res, basos);
rd.include(req, responseIncludeWrapper);
//We can't assume the included servlet flushed its output
responseIncludeWrapper.flushOutputStreamOrWriter();
byte[] bytes = basos.toByteArray();
//Assume platform default encoding unless otherwise specified
String retVal;
if (inputEncoding == null) {
retVal = new String( bytes );
} else {
retVal = new String (bytes,
B2CConverter.getCharset(inputEncoding));
}
//make an assumption that an empty response is a failure. This is
// a problem
// if a truly empty file
//were included, but not sure how else to tell.
if (retVal.equals("") && !req.getMethod().equalsIgnoreCase(
org.apache.coyote.http11.Constants.HEAD)) {
throw new IOException("Couldn't find file: " + path);
}
return retVal;
} catch (ServletException e) {
throw new IOException("Couldn't include file: " + originalPath
+ " because of ServletException: " + e.getMessage());
}
}
// in java/org/apache/catalina/ssi/ResponseIncludeWrapper.java
public void flushOutputStreamOrWriter() throws IOException {
if (servletOutputStream != null) {
servletOutputStream.flush();
}
if (printWriter != null) {
printWriter.flush();
}
}
// in java/org/apache/catalina/ssi/ResponseIncludeWrapper.java
Override
public PrintWriter getWriter() throws java.io.IOException {
if (servletOutputStream == null) {
if (printWriter == null) {
setCharacterEncoding(getCharacterEncoding());
printWriter = new PrintWriter(
new OutputStreamWriter(captureServletOutputStream,
getCharacterEncoding()));
}
return printWriter;
}
throw new IllegalStateException();
}
// in java/org/apache/catalina/ssi/ResponseIncludeWrapper.java
Override
public ServletOutputStream getOutputStream() throws java.io.IOException {
if (printWriter == null) {
if (servletOutputStream == null) {
servletOutputStream = captureServletOutputStream;
}
return servletOutputStream;
}
throw new IllegalStateException();
}
// in java/org/apache/catalina/ssi/SSIServlet.java
Override
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
if (debug > 0) log("SSIServlet.doGet()");
requestHandler(req, res);
}
// in java/org/apache/catalina/ssi/SSIServlet.java
Override
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
if (debug > 0) log("SSIServlet.doPost()");
requestHandler(req, res);
}
// in java/org/apache/catalina/ssi/SSIServlet.java
protected void requestHandler(HttpServletRequest req,
HttpServletResponse res) throws IOException {
ServletContext servletContext = getServletContext();
String path = SSIServletRequestUtil.getRelativePath(req);
if (debug > 0)
log("SSIServlet.requestHandler()\n" + "Serving "
+ (buffered?"buffered ":"unbuffered ") + "resource '"
+ path + "'");
// Exclude any resource in the /WEB-INF and /META-INF subdirectories
// (the "toUpperCase()" avoids problems on Windows systems)
if (path == null || path.toUpperCase(Locale.ENGLISH).startsWith("/WEB-INF")
|| path.toUpperCase(Locale.ENGLISH).startsWith("/META-INF")) {
res.sendError(HttpServletResponse.SC_NOT_FOUND, path);
log("Can't serve file: " + path);
return;
}
URL resource = servletContext.getResource(path);
if (resource == null) {
res.sendError(HttpServletResponse.SC_NOT_FOUND, path);
log("Can't find file: " + path);
return;
}
String resourceMimeType = servletContext.getMimeType(path);
if (resourceMimeType == null) {
resourceMimeType = "text/html";
}
res.setContentType(resourceMimeType + ";charset=" + outputEncoding);
if (expires != null) {
res.setDateHeader("Expires", (new java.util.Date()).getTime()
+ expires.longValue() * 1000);
}
req.setAttribute(Globals.SSI_FLAG_ATTR, "true");
processSSI(req, res, resource);
}
// in java/org/apache/catalina/ssi/SSIServlet.java
protected void processSSI(HttpServletRequest req, HttpServletResponse res,
URL resource) throws IOException {
SSIExternalResolver ssiExternalResolver =
new SSIServletExternalResolver(getServletContext(), req, res,
isVirtualWebappRelative, debug, inputEncoding);
SSIProcessor ssiProcessor = new SSIProcessor(ssiExternalResolver,
debug, allowExec);
PrintWriter printWriter = null;
StringWriter stringWriter = null;
if (buffered) {
stringWriter = new StringWriter();
printWriter = new PrintWriter(stringWriter);
} else {
printWriter = res.getWriter();
}
URLConnection resourceInfo = resource.openConnection();
InputStream resourceInputStream = resourceInfo.getInputStream();
String encoding = resourceInfo.getContentEncoding();
if (encoding == null) {
encoding = inputEncoding;
}
InputStreamReader isr;
if (encoding == null) {
isr = new InputStreamReader(resourceInputStream);
} else {
isr = new InputStreamReader(resourceInputStream, encoding);
}
BufferedReader bufferedReader = new BufferedReader(isr);
long lastModified = ssiProcessor.process(bufferedReader,
resourceInfo.getLastModified(), printWriter);
if (lastModified > 0) {
res.setDateHeader("last-modified", lastModified);
}
if (buffered) {
printWriter.flush();
@SuppressWarnings("null")
String text = stringWriter.toString();
res.getWriter().write(text);
}
bufferedReader.close();
}
// in java/org/apache/catalina/ssi/SSIProcessor.java
public long process(Reader reader, long lastModifiedDate,
PrintWriter writer) throws IOException {
SSIMediator ssiMediator = new SSIMediator(ssiExternalResolver,
lastModifiedDate, debug);
StringWriter stringWriter = new StringWriter();
IOTools.flow(reader, stringWriter);
String fileContents = stringWriter.toString();
stringWriter = null;
int index = 0;
boolean inside = false;
StringBuilder command = new StringBuilder();
try {
while (index < fileContents.length()) {
char c = fileContents.charAt(index);
if (!inside) {
if (c == COMMAND_START.charAt(0)
&& charCmp(fileContents, index, COMMAND_START)) {
inside = true;
index += COMMAND_START.length();
command.setLength(0); //clear the command string
} else {
if (!ssiMediator.getConditionalState().processConditionalCommandsOnly) {
writer.write(c);
}
index++;
}
} else {
if (c == COMMAND_END.charAt(0)
&& charCmp(fileContents, index, COMMAND_END)) {
inside = false;
index += COMMAND_END.length();
String strCmd = parseCmd(command);
if (debug > 0) {
ssiExternalResolver.log(
"SSIProcessor.process -- processing command: "
+ strCmd, null);
}
String[] paramNames = parseParamNames(command, strCmd
.length());
String[] paramValues = parseParamValues(command,
strCmd.length(), paramNames.length);
//We need to fetch this value each time, since it may
// change
// during the loop
String configErrMsg = ssiMediator.getConfigErrMsg();
SSICommand ssiCommand =
commands.get(strCmd.toLowerCase(Locale.ENGLISH));
String errorMessage = null;
if (ssiCommand == null) {
errorMessage = "Unknown command: " + strCmd;
} else if (paramValues == null) {
errorMessage = "Error parsing directive parameters.";
} else if (paramNames.length != paramValues.length) {
errorMessage = "Parameter names count does not match parameter values count on command: "
+ strCmd;
} else {
// don't process the command if we are processing
// conditional
// commands only and the
// command is not conditional
if (!ssiMediator.getConditionalState().processConditionalCommandsOnly
|| ssiCommand instanceof SSIConditional) {
long lmd = ssiCommand.process(ssiMediator, strCmd,
paramNames, paramValues, writer);
if (lmd > lastModifiedDate) {
lastModifiedDate = lmd;
}
}
}
if (errorMessage != null) {
ssiExternalResolver.log(errorMessage, null);
writer.write(configErrMsg);
}
} else {
command.append(c);
index++;
}
}
}
} catch (SSIStopProcessingException e) {
//If we are here, then we have already stopped processing, so all
// is good
}
return lastModifiedDate;
}
// in java/org/apache/catalina/ssi/SSIMediator.java
public long getFileSize(String path, boolean virtual) throws IOException {
return ssiExternalResolver.getFileSize(path, virtual);
}
// in java/org/apache/catalina/ssi/SSIMediator.java
public long getFileLastModified(String path, boolean virtual)
throws IOException {
return ssiExternalResolver.getFileLastModified(path, virtual);
}
// in java/org/apache/catalina/ssi/SSIMediator.java
public String getFileText(String path, boolean virtual) throws IOException {
return ssiExternalResolver.getFileText(path, virtual);
}
// in java/org/apache/catalina/connector/OutputBuffer.java
Override
public void close()
throws IOException {
if (closed) {
return;
}
if (suspended) {
return;
}
// Flush the convertor if one is in use
if (gotEnc && conv != null) {
conv.flushBuffer();
}
if ((!coyoteResponse.isCommitted())
&& (coyoteResponse.getContentLengthLong() == -1)) {
// If this didn't cause a commit of the response, the final content
// length can be calculated
if (!coyoteResponse.isCommitted()) {
coyoteResponse.setContentLength(bb.getLength());
}
}
doFlush(false);
closed = true;
// The request should have been completely read by the time the response
// is closed. Further reads of the input a) are pointless and b) really
// confuse AJP (bug 50189) so close the input buffer to prevent them.
Request req = (Request) coyoteResponse.getRequest().getNote(
CoyoteAdapter.ADAPTER_NOTES);
req.inputBuffer.close();
coyoteResponse.finish();
}
// in java/org/apache/catalina/connector/OutputBuffer.java
Override
public void flush()
throws IOException {
doFlush(true);
}
// in java/org/apache/catalina/connector/OutputBuffer.java
protected void doFlush(boolean realFlush)
throws IOException {
if (suspended) {
return;
}
// Flush the convertor if one is in use
if (gotEnc && conv != null) {
conv.flushBuffer();
}
try {
doFlush = true;
if (initial) {
coyoteResponse.sendHeaders();
initial = false;
}
if (bb.getLength() > 0) {
bb.flushBuffer();
}
} finally {
doFlush = false;
}
if (realFlush) {
coyoteResponse.action(ActionCode.CLIENT_FLUSH,
coyoteResponse);
// If some exception occurred earlier, or if some IOE occurred
// here, notify the servlet with an IOE
if (coyoteResponse.isExceptionPresent()) {
throw new ClientAbortException
(coyoteResponse.getErrorException());
}
}
}
// in java/org/apache/catalina/connector/OutputBuffer.java
Override
public void realWriteBytes(byte buf[], int off, int cnt)
throws IOException {
if (closed) {
return;
}
if (coyoteResponse == null) {
return;
}
// If we really have something to write
if (cnt > 0) {
// real write to the adapter
outputChunk.setBytes(buf, off, cnt);
try {
coyoteResponse.doWrite(outputChunk);
} catch (IOException e) {
// An IOException on a write is almost always due to
// the remote client aborting the request. Wrap this
// so that it can be handled better by the error dispatcher.
throw new ClientAbortException(e);
}
}
}
// in java/org/apache/catalina/connector/OutputBuffer.java
public void write(byte b[], int off, int len) throws IOException {
if (suspended) {
return;
}
writeBytes(b, off, len);
}
// in java/org/apache/catalina/connector/OutputBuffer.java
private void writeBytes(byte b[], int off, int len)
throws IOException {
if (closed) {
return;
}
bb.append(b, off, len);
bytesWritten += len;
// if called from within flush(), then immediately flush
// remaining bytes
if (doFlush) {
bb.flushBuffer();
}
}
// in java/org/apache/catalina/connector/OutputBuffer.java
public void writeByte(int b)
throws IOException {
if (suspended) {
return;
}
bb.append((byte) b);
bytesWritten++;
}
// in java/org/apache/catalina/connector/OutputBuffer.java
Override
public void write(int c)
throws IOException {
if (suspended) {
return;
}
conv.convert((char) c);
charsWritten++;
}
// in java/org/apache/catalina/connector/OutputBuffer.java
Override
public void write(char c[])
throws IOException {
if (suspended) {
return;
}
write(c, 0, c.length);
}
// in java/org/apache/catalina/connector/OutputBuffer.java
Override
public void write(char c[], int off, int len)
throws IOException {
if (suspended) {
return;
}
conv.convert(c, off, len);
charsWritten += len;
}
// in java/org/apache/catalina/connector/OutputBuffer.java
Override
public void write(String s, int off, int len)
throws IOException {
if (suspended) {
return;
}
charsWritten += len;
if (s == null) {
s = "null";
}
conv.convert(s, off, len);
}
// in java/org/apache/catalina/connector/OutputBuffer.java
Override
public void write(String s)
throws IOException {
if (suspended) {
return;
}
if (s == null) {
s = "null";
}
conv.convert(s);
}
// in java/org/apache/catalina/connector/OutputBuffer.java
public void checkConverter()
throws IOException {
if (!gotEnc) {
setConverter();
}
}
// in java/org/apache/catalina/connector/OutputBuffer.java
protected void setConverter()
throws IOException {
if (coyoteResponse != null) {
enc = coyoteResponse.getCharacterEncoding();
}
gotEnc = true;
if (enc == null) {
enc = DEFAULT_ENCODING;
}
conv = encoders.get(enc);
if (conv == null) {
if (Globals.IS_SECURITY_ENABLED){
try{
conv = AccessController.doPrivileged(
new PrivilegedExceptionAction<C2BConverter>(){
@Override
public C2BConverter run() throws IOException{
return new C2BConverter(bb, enc);
}
}
);
}catch(PrivilegedActionException ex){
Exception e = ex.getException();
if (e instanceof IOException) {
throw (IOException)e;
}
}
} else {
conv = new C2BConverter(bb, enc);
}
encoders.put(enc, conv);
}
// in java/org/apache/catalina/connector/OutputBuffer.java
Override
public C2BConverter run() throws IOException{
return new C2BConverter(bb, enc);
}
// in java/org/apache/catalina/connector/Request.java
public boolean read()
throws IOException {
return (inputBuffer.realReadBytes(null, 0, 0) > 0);
}
// in java/org/apache/catalina/connector/Request.java
public ServletInputStream createInputStream()
throws IOException {
if (inputStream == null) {
inputStream = new CoyoteInputStream(inputBuffer);
}
return inputStream;
}
// in java/org/apache/catalina/connector/Request.java
public void finishRequest() throws IOException {
// Optionally disable swallowing of additional request data.
Context context = getContext();
if (context != null &&
response.getStatus() == HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE &&
!context.getSwallowAbortedUploads()) {
coyoteRequest.action(ActionCode.DISABLE_SWALLOW_INPUT, null);
}
}
// in java/org/apache/catalina/connector/Request.java
Override
public ServletInputStream getInputStream() throws IOException {
if (usingReader) {
throw new IllegalStateException
(sm.getString("coyoteRequest.getInputStream.ise"));
}
usingInputStream = true;
if (inputStream == null) {
inputStream = new CoyoteInputStream(inputBuffer);
}
return inputStream;
}
// in java/org/apache/catalina/connector/Request.java
Override
public BufferedReader getReader() throws IOException {
if (usingInputStream) {
throw new IllegalStateException
(sm.getString("coyoteRequest.getReader.ise"));
}
usingReader = true;
inputBuffer.checkConverter();
if (reader == null) {
reader = new CoyoteReader(inputBuffer);
}
return reader;
}
// in java/org/apache/catalina/connector/Request.java
Override
public boolean authenticate(HttpServletResponse response)
throws IOException, ServletException {
if (response.isCommitted()) {
throw new IllegalStateException(
sm.getString("coyoteRequest.authenticate.ise"));
}
return context.getAuthenticator().authenticate(this, response);
}
// in java/org/apache/catalina/connector/Request.java
Override
public Collection<Part> getParts() throws IOException, IllegalStateException,
ServletException {
parseParts();
if (partsParseException != null) {
if (partsParseException instanceof IOException) {
throw (IOException) partsParseException;
} else if (partsParseException instanceof IllegalStateException) {
throw (IllegalStateException) partsParseException;
} else if (partsParseException instanceof ServletException) {
throw (ServletException) partsParseException;
}
}
return parts;
}
// in java/org/apache/catalina/connector/Request.java
Override
public Part getPart(String name) throws IOException, IllegalStateException,
ServletException {
Collection<Part> c = getParts();
Iterator<Part> iterator = c.iterator();
while (iterator.hasNext()) {
Part part = iterator.next();
if (name.equals(part.getName())) {
return part;
}
}
return null;
}
// in java/org/apache/catalina/connector/Request.java
public void doUpgrade(UpgradeInbound inbound)
throws IOException {
coyoteRequest.action(ActionCode.UPGRADE, inbound);
// Output required by RFC2616. Protocol specific headers should have
// already been set.
response.setStatus(HttpServletResponse.SC_SWITCHING_PROTOCOLS);
response.flushBuffer();
}
// in java/org/apache/catalina/connector/Request.java
protected int readPostBody(byte body[], int len)
throws IOException {
int offset = 0;
do {
int inputLen = getStream().read(body, offset, len - offset);
if (inputLen <= 0) {
return offset;
}
offset += inputLen;
} while ((len - offset) > 0);
return len;
}
// in java/org/apache/catalina/connector/Request.java
protected byte[] readChunkedPostBody() throws IOException {
ByteChunk body = new ByteChunk();
byte[] buffer = new byte[CACHED_POST_LEN];
int len = 0;
while (len > -1) {
len = getStream().read(buffer, 0, CACHED_POST_LEN);
if (connector.getMaxPostSize() > 0 &&
(body.getLength() + len) > connector.getMaxPostSize()) {
// Too much data
checkSwallowInput();
throw new IOException(
sm.getString("coyoteRequest.chunkedPostTooLarge"));
}
if (len > 0) {
body.append(buffer, 0, len);
}
}
if (body.getLength() == 0) {
return null;
}
if (body.getLength() < body.getBuffer().length) {
int length = body.getLength();
byte[] result = new byte[length];
System.arraycopy(body.getBuffer(), 0, result, 0, length);
return result;
}
return body.getBuffer();
}
// in java/org/apache/catalina/connector/CoyoteOutputStream.java
Override
public void write(int i)
throws IOException {
ob.writeByte(i);
}
// in java/org/apache/catalina/connector/CoyoteOutputStream.java
Override
public void write(byte[] b)
throws IOException {
write(b, 0, b.length);
}
// in java/org/apache/catalina/connector/CoyoteOutputStream.java
Override
public void write(byte[] b, int off, int len)
throws IOException {
ob.write(b, off, len);
}
// in java/org/apache/catalina/connector/CoyoteOutputStream.java
Override
public void flush()
throws IOException {
ob.flush();
}
// in java/org/apache/catalina/connector/CoyoteOutputStream.java
Override
public void close()
throws IOException {
ob.close();
}
// in java/org/apache/catalina/connector/Response.java
public void finishResponse()
throws IOException {
// Writing leftover bytes
outputBuffer.close();
}
// in java/org/apache/catalina/connector/Response.java
public PrintWriter getReporter() throws IOException {
if (outputBuffer.isNew()) {
outputBuffer.checkConverter();
if (writer == null) {
writer = new CoyoteWriter(outputBuffer);
}
return writer;
} else {
return null;
}
}
// in java/org/apache/catalina/connector/Response.java
Override
public void flushBuffer()
throws IOException {
outputBuffer.flush();
}
// in java/org/apache/catalina/connector/Response.java
Override
public ServletOutputStream getOutputStream()
throws IOException {
if (usingWriter) {
throw new IllegalStateException
(sm.getString("coyoteResponse.getOutputStream.ise"));
}
usingOutputStream = true;
if (outputStream == null) {
outputStream = new CoyoteOutputStream(outputBuffer);
}
return outputStream;
}
// in java/org/apache/catalina/connector/Response.java
Override
public PrintWriter getWriter()
throws IOException {
if (usingOutputStream) {
throw new IllegalStateException
(sm.getString("coyoteResponse.getWriter.ise"));
}
if (ENFORCE_ENCODING_IN_GET_WRITER) {
/*
* If the response's character encoding has not been specified as
* described in <code>getCharacterEncoding</code> (i.e., the method
* just returns the default value <code>ISO-8859-1</code>),
* <code>getWriter</code> updates it to <code>ISO-8859-1</code>
* (with the effect that a subsequent call to getContentType() will
* include a charset=ISO-8859-1 component which will also be
* reflected in the Content-Type response header, thereby satisfying
* the Servlet spec requirement that containers must communicate the
* character encoding used for the servlet response's writer to the
* client).
*/
setCharacterEncoding(getCharacterEncoding());
}
usingWriter = true;
outputBuffer.checkConverter();
if (writer == null) {
writer = new CoyoteWriter(outputBuffer);
}
return writer;
}
// in java/org/apache/catalina/connector/Response.java
public void sendAcknowledgement()
throws IOException {
if (isCommitted()) {
return;
}
// Ignore any call from an included servlet
if (included) {
return;
}
coyoteResponse.acknowledge();
}
// in java/org/apache/catalina/connector/Response.java
Override
public void sendError(int status)
throws IOException {
sendError(status, null);
}
// in java/org/apache/catalina/connector/Response.java
Override
public void sendError(int status, String message)
throws IOException {
if (isCommitted()) {
throw new IllegalStateException
(sm.getString("coyoteResponse.sendError.ise"));
}
// Ignore any call from an included servlet
if (included) {
return;
}
Wrapper wrapper = getRequest().getWrapper();
if (wrapper != null) {
wrapper.incrementErrorCount();
}
setError();
coyoteResponse.setStatus(status);
coyoteResponse.setMessage(message);
// Clear any data content that has been buffered
resetBuffer();
// Cause the response to be finished (from the application perspective)
setSuspended(true);
}
// in java/org/apache/catalina/connector/Response.java
Override
public void sendRedirect(String location)
throws IOException {
if (isCommitted()) {
throw new IllegalStateException
(sm.getString("coyoteResponse.sendRedirect.ise"));
}
// Ignore any call from an included servlet
if (included) {
return;
}
// Clear any data content that has been buffered
resetBuffer(true);
// Generate a temporary redirect to the specified location
try {
String absolute = toAbsolute(location);
setStatus(SC_FOUND);
setHeader("Location", absolute);
if (getContext().getSendRedirectBody()) {
PrintWriter writer = getWriter();
writer.print(sm.getString("coyoteResponse.sendRedirect.note",
RequestUtil.filter(absolute)));
flushBuffer();
}
} catch (IllegalArgumentException e) {
setStatus(SC_NOT_FOUND);
}
// Cause the response to be finished (from the application perspective)
setSuspended(true);
}
// in java/org/apache/catalina/connector/Response.java
protected String toAbsolute(String location) {
if (location == null) {
return (location);
}
boolean leadingSlash = location.startsWith("/");
if (location.startsWith("//")) {
// Scheme relative
redirectURLCC.recycle();
// Add the scheme
String scheme = request.getScheme();
try {
redirectURLCC.append(scheme, 0, scheme.length());
redirectURLCC.append(':');
redirectURLCC.append(location, 0, location.length());
return redirectURLCC.toString();
} catch (IOException e) {
IllegalArgumentException iae =
new IllegalArgumentException(location);
iae.initCause(e);
throw iae;
}
} else if (leadingSlash || !hasScheme(location)) {
redirectURLCC.recycle();
String scheme = request.getScheme();
String name = request.getServerName();
int port = request.getServerPort();
try {
redirectURLCC.append(scheme, 0, scheme.length());
redirectURLCC.append("://", 0, 3);
redirectURLCC.append(name, 0, name.length());
if ((scheme.equals("http") && port != 80)
|| (scheme.equals("https") && port != 443)) {
redirectURLCC.append(':');
String portS = port + "";
redirectURLCC.append(portS, 0, portS.length());
}
if (!leadingSlash) {
String relativePath = request.getDecodedRequestURI();
int pos = relativePath.lastIndexOf('/');
relativePath = relativePath.substring(0, pos);
String encodedURI = null;
final String frelativePath = relativePath;
if (SecurityUtil.isPackageProtectionEnabled() ){
try{
encodedURI = AccessController.doPrivileged(
new PrivilegedExceptionAction<String>(){
@Override
public String run() throws IOException{
return urlEncoder.encodeURL(frelativePath);
}
});
} catch (PrivilegedActionException pae){
IllegalArgumentException iae =
new IllegalArgumentException(location);
iae.initCause(pae.getException());
throw iae;
}
} else {
encodedURI = urlEncoder.encodeURL(relativePath);
}
redirectURLCC.append(encodedURI, 0, encodedURI.length());
redirectURLCC.append('/');
}
redirectURLCC.append(location, 0, location.length());
normalize(redirectURLCC);
} catch (IOException e) {
IllegalArgumentException iae =
new IllegalArgumentException(location);
iae.initCause(e);
throw iae;
}
return redirectURLCC.toString();
}
// in java/org/apache/catalina/connector/Response.java
Override
public String run() throws IOException{
return urlEncoder.encodeURL(frelativePath);
}
// in java/org/apache/catalina/connector/RequestFacade.java
Override
public ServletInputStream getInputStream() throws IOException {
if (request == null) {
throw new IllegalStateException(
sm.getString("requestFacade.nullRequest"));
}
return request.getInputStream();
}
// in java/org/apache/catalina/connector/RequestFacade.java
Override
public BufferedReader getReader() throws IOException {
if (request == null) {
throw new IllegalStateException(
sm.getString("requestFacade.nullRequest"));
}
return request.getReader();
}
// in java/org/apache/catalina/connector/RequestFacade.java
Override
public boolean authenticate(HttpServletResponse response)
throws IOException, ServletException {
return request.authenticate(response);
}
// in java/org/apache/catalina/connector/RequestFacade.java
Override
public Collection<Part> getParts() throws IllegalStateException,
IOException, ServletException {
return request.getParts();
}
// in java/org/apache/catalina/connector/RequestFacade.java
Override
public Part getPart(String name) throws IllegalStateException, IOException,
ServletException {
return request.getPart(name);
}
// in java/org/apache/catalina/connector/RequestFacade.java
public void doUpgrade(UpgradeInbound inbound)
throws IOException {
request.doUpgrade(inbound);
}
// in java/org/apache/catalina/connector/CometEventImpl.java
Override
public void close() throws IOException {
if (request == null) {
throw new IllegalStateException(sm.getString("cometEvent.nullRequest"));
}
request.finishRequest();
response.finishResponse();
if (request.isComet()) {
request.cometClose();
}
}
// in java/org/apache/catalina/connector/CometEventImpl.java
Override
public void setTimeout(int timeout) throws IOException, ServletException,
UnsupportedOperationException {
if (request.getAttribute(Globals.COMET_TIMEOUT_SUPPORTED_ATTR) ==
Boolean.TRUE) {
request.setAttribute(Globals.COMET_TIMEOUT_ATTR,
Integer.valueOf(timeout));
if (request.isComet()) {
request.setCometTimeout(timeout);
}
} else {
throw new UnsupportedOperationException();
}
}
// in java/org/apache/catalina/connector/CoyoteInputStream.java
Override
public int read()
throws IOException {
if (SecurityUtil.isPackageProtectionEnabled()){
try{
Integer result =
AccessController.doPrivileged(
new PrivilegedExceptionAction<Integer>(){
@Override
public Integer run() throws IOException{
Integer integer = Integer.valueOf(ib.readByte());
return integer;
}
});
return result.intValue();
} catch(PrivilegedActionException pae){
Exception e = pae.getException();
if (e instanceof IOException){
throw (IOException)e;
} else {
throw new RuntimeException(e.getMessage(), e);
}
}
}
// in java/org/apache/catalina/connector/CoyoteInputStream.java
Override
public Integer run() throws IOException{
Integer integer = Integer.valueOf(ib.readByte());
return integer;
}
// in java/org/apache/catalina/connector/CoyoteInputStream.java
Override
public int available() throws IOException {
if (SecurityUtil.isPackageProtectionEnabled()){
try{
Integer result =
AccessController.doPrivileged(
new PrivilegedExceptionAction<Integer>(){
@Override
public Integer run() throws IOException{
Integer integer = Integer.valueOf(ib.available());
return integer;
}
});
return result.intValue();
} catch(PrivilegedActionException pae){
Exception e = pae.getException();
if (e instanceof IOException){
throw (IOException)e;
} else {
throw new RuntimeException(e.getMessage(), e);
}
}
}
// in java/org/apache/catalina/connector/CoyoteInputStream.java
Override
public Integer run() throws IOException{
Integer integer = Integer.valueOf(ib.available());
return integer;
}
// in java/org/apache/catalina/connector/CoyoteInputStream.java
Override
public int read(final byte[] b) throws IOException {
if (SecurityUtil.isPackageProtectionEnabled()){
try{
Integer result =
AccessController.doPrivileged(
new PrivilegedExceptionAction<Integer>(){
@Override
public Integer run() throws IOException{
Integer integer =
Integer.valueOf(ib.read(b, 0, b.length));
return integer;
}
});
return result.intValue();
} catch(PrivilegedActionException pae){
Exception e = pae.getException();
if (e instanceof IOException){
throw (IOException)e;
} else {
throw new RuntimeException(e.getMessage() ,e);
}
}
}
// in java/org/apache/catalina/connector/CoyoteInputStream.java
Override
public Integer run() throws IOException{
Integer integer =
Integer.valueOf(ib.read(b, 0, b.length));
return integer;
}
// in java/org/apache/catalina/connector/CoyoteInputStream.java
Override
public int read(final byte[] b, final int off, final int len)
throws IOException {
if (SecurityUtil.isPackageProtectionEnabled()){
try{
Integer result =
AccessController.doPrivileged(
new PrivilegedExceptionAction<Integer>(){
@Override
public Integer run() throws IOException{
Integer integer =
Integer.valueOf(ib.read(b, off, len));
return integer;
}
});
return result.intValue();
} catch(PrivilegedActionException pae){
Exception e = pae.getException();
if (e instanceof IOException){
throw (IOException)e;
} else {
throw new RuntimeException(e.getMessage(), e);
}
}
}
// in java/org/apache/catalina/connector/CoyoteInputStream.java
Override
public Integer run() throws IOException{
Integer integer =
Integer.valueOf(ib.read(b, off, len));
return integer;
}
// in java/org/apache/catalina/connector/CoyoteInputStream.java
Override
public int readLine(byte[] b, int off, int len) throws IOException {
return super.readLine(b, off, len);
}
// in java/org/apache/catalina/connector/CoyoteInputStream.java
Override
public void close() throws IOException {
if (SecurityUtil.isPackageProtectionEnabled()){
try{
AccessController.doPrivileged(
new PrivilegedExceptionAction<Void>(){
@Override
public Void run() throws IOException{
ib.close();
return null;
}
});
} catch(PrivilegedActionException pae){
Exception e = pae.getException();
if (e instanceof IOException){
throw (IOException)e;
} else {
throw new RuntimeException(e.getMessage(), e);
}
}
}
// in java/org/apache/catalina/connector/CoyoteInputStream.java
Override
public Void run() throws IOException{
ib.close();
return null;
}
// in java/org/apache/catalina/connector/InputBuffer.java
Override
public void close()
throws IOException {
closed = true;
}
// in java/org/apache/catalina/connector/InputBuffer.java
Override
public int realReadBytes(byte cbuf[], int off, int len)
throws IOException {
if (closed) {
return -1;
}
if (coyoteRequest == null) {
return -1;
}
if(state == INITIAL_STATE) {
state = BYTE_STATE;
}
int result = coyoteRequest.doRead(bb);
return result;
}
// in java/org/apache/catalina/connector/InputBuffer.java
public int readByte()
throws IOException {
if (closed) {
throw new IOException(sm.getString("inputBuffer.streamClosed"));
}
return bb.substract();
}
// in java/org/apache/catalina/connector/InputBuffer.java
public int read(byte[] b, int off, int len)
throws IOException {
if (closed) {
throw new IOException(sm.getString("inputBuffer.streamClosed"));
}
return bb.substract(b, off, len);
}
// in java/org/apache/catalina/connector/InputBuffer.java
Override
public void realWriteChars(char c[], int off, int len)
throws IOException {
markPos = -1;
cb.setOffset(0);
cb.setEnd(0);
}
// in java/org/apache/catalina/connector/InputBuffer.java
Override
public int realReadChars(char cbuf[], int off, int len)
throws IOException {
if (!gotEnc) {
setConverter();
}
if (bb.getLength() <= 0) {
int nRead = realReadBytes(bb.getBytes(), 0, bb.getBytes().length);
if (nRead < 0) {
return -1;
}
}
if (markPos == -1) {
cb.setOffset(0);
cb.setEnd(0);
}
int limit = bb.getLength()+cb.getStart();
if ( cb.getLimit() < limit ) {
cb.setLimit(limit);
}
state = CHAR_STATE;
conv.convert(bb, cb, bb.getLength());
bb.setOffset(bb.getEnd());
return cb.getLength();
}
// in java/org/apache/catalina/connector/InputBuffer.java
Override
public int read()
throws IOException {
if (closed) {
throw new IOException(sm.getString("inputBuffer.streamClosed"));
}
return cb.substract();
}
// in java/org/apache/catalina/connector/InputBuffer.java
Override
public int read(char[] cbuf)
throws IOException {
if (closed) {
throw new IOException(sm.getString("inputBuffer.streamClosed"));
}
return read(cbuf, 0, cbuf.length);
}
// in java/org/apache/catalina/connector/InputBuffer.java
Override
public int read(char[] cbuf, int off, int len)
throws IOException {
if (closed) {
throw new IOException(sm.getString("inputBuffer.streamClosed"));
}
return cb.substract(cbuf, off, len);
}
// in java/org/apache/catalina/connector/InputBuffer.java
Override
public long skip(long n)
throws IOException {
if (closed) {
throw new IOException(sm.getString("inputBuffer.streamClosed"));
}
if (n < 0) {
throw new IllegalArgumentException();
}
long nRead = 0;
while (nRead < n) {
if (cb.getLength() >= n) {
cb.setOffset(cb.getStart() + (int) n);
nRead = n;
} else {
nRead += cb.getLength();
cb.setOffset(cb.getEnd());
int toRead = 0;
if (cb.getChars().length < (n - nRead)) {
toRead = cb.getChars().length;
} else {
toRead = (int) (n - nRead);
}
int nb = realReadChars(cb.getChars(), 0, toRead);
if (nb < 0) {
break;
}
}
}
return nRead;
}
// in java/org/apache/catalina/connector/InputBuffer.java
Override
public boolean ready()
throws IOException {
if (closed) {
throw new IOException(sm.getString("inputBuffer.streamClosed"));
}
return (available() > 0);
}
// in java/org/apache/catalina/connector/InputBuffer.java
Override
public void mark(int readAheadLimit)
throws IOException {
if (closed) {
throw new IOException(sm.getString("inputBuffer.streamClosed"));
}
if (cb.getLength() <= 0) {
cb.setOffset(0);
cb.setEnd(0);
} else {
if ((cb.getBuffer().length > (2 * size))
&& (cb.getLength()) < (cb.getStart())) {
System.arraycopy(cb.getBuffer(), cb.getStart(),
cb.getBuffer(), 0, cb.getLength());
cb.setEnd(cb.getLength());
cb.setOffset(0);
}
}
cb.setLimit(cb.getStart() + readAheadLimit + size);
markPos = cb.getStart();
}
// in java/org/apache/catalina/connector/InputBuffer.java
Override
public void reset()
throws IOException {
if (closed) {
throw new IOException(sm.getString("inputBuffer.streamClosed"));
}
if (state == CHAR_STATE) {
if (markPos < 0) {
cb.recycle();
markPos = -1;
throw new IOException();
} else {
cb.setOffset(markPos);
}
} else {
bb.recycle();
}
}
// in java/org/apache/catalina/connector/InputBuffer.java
public void checkConverter()
throws IOException {
if (!gotEnc) {
setConverter();
}
}
// in java/org/apache/catalina/connector/InputBuffer.java
protected void setConverter()
throws IOException {
if (coyoteRequest != null) {
enc = coyoteRequest.getCharacterEncoding();
}
gotEnc = true;
if (enc == null) {
enc = DEFAULT_ENCODING;
}
conv = encoders.get(enc);
if (conv == null) {
if (SecurityUtil.isPackageProtectionEnabled()){
try{
conv = AccessController.doPrivileged(
new PrivilegedExceptionAction<B2CConverter>(){
@Override
public B2CConverter run() throws IOException {
return new B2CConverter(enc);
}
}
);
}catch(PrivilegedActionException ex){
Exception e = ex.getException();
if (e instanceof IOException) {
throw (IOException)e;
}
}
} else {
conv = new B2CConverter(enc);
}
encoders.put(enc, conv);
}
// in java/org/apache/catalina/connector/InputBuffer.java
Override
public B2CConverter run() throws IOException {
return new B2CConverter(enc);
}
// in java/org/apache/catalina/connector/ResponseFacade.java
Override
public ServletOutputStream getOutputStream()
throws IOException {
// if (isFinished())
// throw new IllegalStateException
// (/*sm.getString("responseFacade.finished")*/);
ServletOutputStream sos = response.getOutputStream();
if (isFinished()) {
response.setSuspended(true);
}
return (sos);
}
// in java/org/apache/catalina/connector/ResponseFacade.java
Override
public PrintWriter getWriter()
throws IOException {
// if (isFinished())
// throw new IllegalStateException
// (/*sm.getString("responseFacade.finished")*/);
PrintWriter writer = response.getWriter();
if (isFinished()) {
response.setSuspended(true);
}
return (writer);
}
// in java/org/apache/catalina/connector/ResponseFacade.java
Override
public void flushBuffer()
throws IOException {
if (isFinished()) {
// throw new IllegalStateException
// (/*sm.getString("responseFacade.finished")*/);
return;
}
if (SecurityUtil.isPackageProtectionEnabled()){
try{
AccessController.doPrivileged(
new PrivilegedExceptionAction<Void>(){
@Override
public Void run() throws IOException{
response.setAppCommitted(true);
response.flushBuffer();
return null;
}
});
} catch(PrivilegedActionException e){
Exception ex = e.getException();
if (ex instanceof IOException){
throw (IOException)ex;
}
}
}
// in java/org/apache/catalina/connector/ResponseFacade.java
Override
public Void run() throws IOException{
response.setAppCommitted(true);
response.flushBuffer();
return null;
}
// in java/org/apache/catalina/connector/ResponseFacade.java
Override
public void sendError(int sc, String msg)
throws IOException {
if (isCommitted()) {
throw new IllegalStateException
(sm.getString("coyoteResponse.sendError.ise"));
}
response.setAppCommitted(true);
response.sendError(sc, msg);
}
// in java/org/apache/catalina/connector/ResponseFacade.java
Override
public void sendError(int sc)
throws IOException {
if (isCommitted()) {
throw new IllegalStateException
(sm.getString("coyoteResponse.sendError.ise"));
}
response.setAppCommitted(true);
response.sendError(sc);
}
// in java/org/apache/catalina/connector/ResponseFacade.java
Override
public void sendRedirect(String location)
throws IOException {
if (isCommitted()) {
throw new IllegalStateException
(sm.getString("coyoteResponse.sendRedirect.ise"));
}
response.setAppCommitted(true);
response.sendRedirect(location);
}
// in java/org/apache/catalina/connector/CoyoteReader.java
Override
public void close()
throws IOException {
ib.close();
}
// in java/org/apache/catalina/connector/CoyoteReader.java
Override
public int read()
throws IOException {
return ib.read();
}
// in java/org/apache/catalina/connector/CoyoteReader.java
Override
public int read(char[] cbuf)
throws IOException {
return ib.read(cbuf, 0, cbuf.length);
}
// in java/org/apache/catalina/connector/CoyoteReader.java
Override
public int read(char[] cbuf, int off, int len)
throws IOException {
return ib.read(cbuf, off, len);
}
// in java/org/apache/catalina/connector/CoyoteReader.java
Override
public long skip(long n)
throws IOException {
return ib.skip(n);
}
// in java/org/apache/catalina/connector/CoyoteReader.java
Override
public boolean ready()
throws IOException {
return ib.ready();
}
// in java/org/apache/catalina/connector/CoyoteReader.java
Override
public void mark(int readAheadLimit)
throws IOException {
ib.mark(readAheadLimit);
}
// in java/org/apache/catalina/connector/CoyoteReader.java
Override
public void reset()
throws IOException {
ib.reset();
}
// in java/org/apache/catalina/connector/CoyoteReader.java
Override
public String readLine()
throws IOException {
if (lineBuffer == null) {
lineBuffer = new char[MAX_LINE_LENGTH];
}
String result = null;
int pos = 0;
int end = -1;
int skip = -1;
StringBuilder aggregator = null;
while (end < 0) {
mark(MAX_LINE_LENGTH);
while ((pos < MAX_LINE_LENGTH) && (end < 0)) {
int nRead = read(lineBuffer, pos, MAX_LINE_LENGTH - pos);
if (nRead < 0) {
if (pos == 0 && aggregator == null) {
return null;
}
end = pos;
skip = pos;
}
for (int i = pos; (i < (pos + nRead)) && (end < 0); i++) {
if (lineBuffer[i] == LINE_SEP[0]) {
end = i;
skip = i + 1;
char nextchar;
if (i == (pos + nRead - 1)) {
nextchar = (char) read();
} else {
nextchar = lineBuffer[i+1];
}
if (nextchar == LINE_SEP[1]) {
skip++;
}
} else if (lineBuffer[i] == LINE_SEP[1]) {
end = i;
skip = i + 1;
}
}
if (nRead > 0) {
pos += nRead;
}
}
if (end < 0) {
if (aggregator == null) {
aggregator = new StringBuilder();
}
aggregator.append(lineBuffer);
pos = 0;
} else {
reset();
skip(skip);
}
}
// in java/org/apache/catalina/core/ApplicationFilterChain.java
Override
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
if( Globals.IS_SECURITY_ENABLED ) {
final ServletRequest req = request;
final ServletResponse res = response;
try {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedExceptionAction<Void>() {
@Override
public Void run()
throws ServletException, IOException {
internalDoFilter(req,res);
return null;
}
}
);
} catch( PrivilegedActionException pe) {
Exception e = pe.getException();
if (e instanceof ServletException)
throw (ServletException) e;
else if (e instanceof IOException)
throw (IOException) e;
else if (e instanceof RuntimeException)
throw (RuntimeException) e;
else
throw new ServletException(e.getMessage(), e);
}
}
// in java/org/apache/catalina/core/ApplicationFilterChain.java
Override
public Void run()
throws ServletException, IOException {
internalDoFilter(req,res);
return null;
}
// in java/org/apache/catalina/core/ApplicationFilterChain.java
private void internalDoFilter(ServletRequest request,
ServletResponse response)
throws IOException, ServletException {
// Call the next filter if there is one
if (pos < n) {
ApplicationFilterConfig filterConfig = filters[pos++];
Filter filter = null;
try {
filter = filterConfig.getFilter();
support.fireInstanceEvent(InstanceEvent.BEFORE_FILTER_EVENT,
filter, request, response);
if (request.isAsyncSupported() && "false".equalsIgnoreCase(
filterConfig.getFilterDef().getAsyncSupported())) {
request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR,
Boolean.FALSE);
}
if( Globals.IS_SECURITY_ENABLED ) {
final ServletRequest req = request;
final ServletResponse res = response;
Principal principal =
((HttpServletRequest) req).getUserPrincipal();
Object[] args = new Object[]{req, res, this};
SecurityUtil.doAsPrivilege
("doFilter", filter, classType, args, principal);
} else {
filter.doFilter(request, response, this);
}
support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
filter, request, response);
} catch (IOException e) {
if (filter != null)
support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
filter, request, response, e);
throw e;
} catch (ServletException e) {
if (filter != null)
support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
filter, request, response, e);
throw e;
} catch (RuntimeException e) {
if (filter != null)
support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
filter, request, response, e);
throw e;
} catch (Throwable e) {
e = ExceptionUtils.unwrapInvocationTargetException(e);
ExceptionUtils.handleThrowable(e);
if (filter != null)
support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
filter, request, response, e);
throw new ServletException
(sm.getString("filterChain.filter"), e);
}
return;
}
// We fell off the end of the chain -- call the servlet instance
try {
if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
lastServicedRequest.set(request);
lastServicedResponse.set(response);
}
support.fireInstanceEvent(InstanceEvent.BEFORE_SERVICE_EVENT,
servlet, request, response);
if (request.isAsyncSupported()
&& !support.getWrapper().isAsyncSupported()) {
request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR,
Boolean.FALSE);
}
// Use potentially wrapped request from this point
if ((request instanceof HttpServletRequest) &&
(response instanceof HttpServletResponse)) {
if( Globals.IS_SECURITY_ENABLED ) {
final ServletRequest req = request;
final ServletResponse res = response;
Principal principal =
((HttpServletRequest) req).getUserPrincipal();
Object[] args = new Object[]{req, res};
SecurityUtil.doAsPrivilege("service",
servlet,
classTypeUsedInService,
args,
principal);
} else {
servlet.service(request, response);
}
} else {
servlet.service(request, response);
}
support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
servlet, request, response);
} catch (IOException e) {
support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
servlet, request, response, e);
throw e;
} catch (ServletException e) {
support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
servlet, request, response, e);
throw e;
} catch (RuntimeException e) {
support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
servlet, request, response, e);
throw e;
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
servlet, request, response, e);
throw new ServletException
(sm.getString("filterChain.servlet"), e);
} finally {
if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
lastServicedRequest.set(null);
lastServicedResponse.set(null);
}
}
}
// in java/org/apache/catalina/core/ApplicationFilterChain.java
Override
public void doFilterEvent(CometEvent event)
throws IOException, ServletException {
if( Globals.IS_SECURITY_ENABLED ) {
final CometEvent ev = event;
try {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedExceptionAction<Void>() {
@Override
public Void run()
throws ServletException, IOException {
internalDoFilterEvent(ev);
return null;
}
}
);
} catch( PrivilegedActionException pe) {
Exception e = pe.getException();
if (e instanceof ServletException)
throw (ServletException) e;
else if (e instanceof IOException)
throw (IOException) e;
else if (e instanceof RuntimeException)
throw (RuntimeException) e;
else
throw new ServletException(e.getMessage(), e);
}
}
// in java/org/apache/catalina/core/ApplicationFilterChain.java
Override
public Void run()
throws ServletException, IOException {
internalDoFilterEvent(ev);
return null;
}
// in java/org/apache/catalina/core/ApplicationFilterChain.java
private void internalDoFilterEvent(CometEvent event)
throws IOException, ServletException {
// Call the next filter if there is one
if (pos < n) {
ApplicationFilterConfig filterConfig = filters[pos++];
CometFilter filter = null;
try {
filter = (CometFilter) filterConfig.getFilter();
// FIXME: No instance listener processing for events for now
/*
support.fireInstanceEvent(InstanceEvent.BEFORE_FILTER_EVENT,
filter, event);
*/
if( Globals.IS_SECURITY_ENABLED ) {
final CometEvent ev = event;
Principal principal =
ev.getHttpServletRequest().getUserPrincipal();
Object[] args = new Object[]{ev, this};
SecurityUtil.doAsPrivilege("doFilterEvent", filter,
cometClassType, args, principal);
} else {
filter.doFilterEvent(event, this);
}
/*support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
filter, event);*/
} catch (IOException e) {
/*
if (filter != null)
support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
filter, event, e);
*/
throw e;
} catch (ServletException e) {
/*
if (filter != null)
support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
filter, event, e);
*/
throw e;
} catch (RuntimeException e) {
/*
if (filter != null)
support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
filter, event, e);
*/
throw e;
} catch (Throwable e) {
e = ExceptionUtils.unwrapInvocationTargetException(e);
ExceptionUtils.handleThrowable(e);
/*if (filter != null)
support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
filter, event, e);*/
throw new ServletException
(sm.getString("filterChain.filter"), e);
}
return;
}
// We fell off the end of the chain -- call the servlet instance
try {
/*
support.fireInstanceEvent(InstanceEvent.BEFORE_SERVICE_EVENT,
servlet, request, response);
*/
if( Globals.IS_SECURITY_ENABLED ) {
final CometEvent ev = event;
Principal principal =
ev.getHttpServletRequest().getUserPrincipal();
Object[] args = new Object[]{ ev };
SecurityUtil.doAsPrivilege("event",
servlet,
classTypeUsedInEvent,
args,
principal);
} else {
((CometProcessor) servlet).event(event);
}
/*
support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
servlet, request, response);*/
} catch (IOException e) {
/*
support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
servlet, request, response, e);
*/
throw e;
} catch (ServletException e) {
/*
support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
servlet, request, response, e);
*/
throw e;
} catch (RuntimeException e) {
/*
support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
servlet, request, response, e);
*/
throw e;
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
/*
support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
servlet, request, response, e);
*/
throw new ServletException
(sm.getString("filterChain.servlet"), e);
}
}
// in java/org/apache/catalina/core/StandardWrapperValve.java
Override
public final void invoke(Request request, Response response)
throws IOException, ServletException {
// Initialize local variables we may need
boolean unavailable = false;
Throwable throwable = null;
// This should be a Request attribute...
long t1=System.currentTimeMillis();
requestCount++;
StandardWrapper wrapper = (StandardWrapper) getContainer();
Servlet servlet = null;
Context context = (Context) wrapper.getParent();
// Check for the application being marked unavailable
if (!context.getAvailable()) {
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
sm.getString("standardContext.isUnavailable"));
unavailable = true;
}
// Check for the servlet being marked unavailable
if (!unavailable && wrapper.isUnavailable()) {
container.getLogger().info(sm.getString("standardWrapper.isUnavailable",
wrapper.getName()));
long available = wrapper.getAvailable();
if ((available > 0L) && (available < Long.MAX_VALUE)) {
response.setDateHeader("Retry-After", available);
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
sm.getString("standardWrapper.isUnavailable",
wrapper.getName()));
} else if (available == Long.MAX_VALUE) {
response.sendError(HttpServletResponse.SC_NOT_FOUND,
sm.getString("standardWrapper.notFound",
wrapper.getName()));
}
unavailable = true;
}
// Allocate a servlet instance to process this request
try {
if (!unavailable) {
servlet = wrapper.allocate();
}
} catch (UnavailableException e) {
container.getLogger().error(
sm.getString("standardWrapper.allocateException",
wrapper.getName()), e);
long available = wrapper.getAvailable();
if ((available > 0L) && (available < Long.MAX_VALUE)) {
response.setDateHeader("Retry-After", available);
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
sm.getString("standardWrapper.isUnavailable",
wrapper.getName()));
} else if (available == Long.MAX_VALUE) {
response.sendError(HttpServletResponse.SC_NOT_FOUND,
sm.getString("standardWrapper.notFound",
wrapper.getName()));
}
} catch (ServletException e) {
container.getLogger().error(sm.getString("standardWrapper.allocateException",
wrapper.getName()), StandardWrapper.getRootCause(e));
throwable = e;
exception(request, response, e);
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
container.getLogger().error(sm.getString("standardWrapper.allocateException",
wrapper.getName()), e);
throwable = e;
exception(request, response, e);
servlet = null;
}
// Identify if the request is Comet related now that the servlet has been allocated
boolean comet = false;
if (servlet instanceof CometProcessor && request.getAttribute(
Globals.COMET_SUPPORTED_ATTR) == Boolean.TRUE) {
comet = true;
request.setComet(true);
}
MessageBytes requestPathMB = request.getRequestPathMB();
DispatcherType dispatcherType = DispatcherType.REQUEST;
if (request.getDispatcherType()==DispatcherType.ASYNC) dispatcherType = DispatcherType.ASYNC;
request.setAttribute
(ApplicationFilterFactory.DISPATCHER_TYPE_ATTR,
dispatcherType);
request.setAttribute
(ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR,
requestPathMB);
// Create the filter chain for this request
ApplicationFilterFactory factory =
ApplicationFilterFactory.getInstance();
ApplicationFilterChain filterChain =
factory.createFilterChain(request, wrapper, servlet);
// Reset comet flag value after creating the filter chain
request.setComet(false);
// Call the filter chain for this request
// NOTE: This also calls the servlet's service() method
try {
if ((servlet != null) && (filterChain != null)) {
// Swallow output if needed
if (context.getSwallowOutput()) {
try {
SystemLogHandler.startCapture();
if (request.isAsyncDispatching()) {
//TODO SERVLET3 - async
((AsyncContextImpl)request.getAsyncContext()).doInternalDispatch();
} else if (comet) {
filterChain.doFilterEvent(request.getEvent());
request.setComet(true);
} else {
filterChain.doFilter(request.getRequest(),
response.getResponse());
}
} finally {
String log = SystemLogHandler.stopCapture();
if (log != null && log.length() > 0) {
context.getLogger().info(log);
}
}
} else {
if (request.isAsyncDispatching()) {
//TODO SERVLET3 - async
((AsyncContextImpl)request.getAsyncContext()).doInternalDispatch();
} else if (comet) {
request.setComet(true);
filterChain.doFilterEvent(request.getEvent());
} else {
filterChain.doFilter
(request.getRequest(), response.getResponse());
}
}
}
} catch (ClientAbortException e) {
throwable = e;
exception(request, response, e);
} catch (IOException e) {
container.getLogger().error(sm.getString(
"standardWrapper.serviceException", wrapper.getName(),
context.getName()), e);
throwable = e;
exception(request, response, e);
} catch (UnavailableException e) {
container.getLogger().error(sm.getString(
"standardWrapper.serviceException", wrapper.getName(),
context.getName()), e);
// throwable = e;
// exception(request, response, e);
wrapper.unavailable(e);
long available = wrapper.getAvailable();
if ((available > 0L) && (available < Long.MAX_VALUE)) {
response.setDateHeader("Retry-After", available);
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
sm.getString("standardWrapper.isUnavailable",
wrapper.getName()));
} else if (available == Long.MAX_VALUE) {
response.sendError(HttpServletResponse.SC_NOT_FOUND,
sm.getString("standardWrapper.notFound",
wrapper.getName()));
}
// Do not save exception in 'throwable', because we
// do not want to do exception(request, response, e) processing
} catch (ServletException e) {
Throwable rootCause = StandardWrapper.getRootCause(e);
if (!(rootCause instanceof ClientAbortException)) {
container.getLogger().error(sm.getString(
"standardWrapper.serviceExceptionRoot",
wrapper.getName(), context.getName(), e.getMessage()),
rootCause);
}
throwable = e;
exception(request, response, e);
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
container.getLogger().error(sm.getString(
"standardWrapper.serviceException", wrapper.getName(),
context.getName()), e);
throwable = e;
exception(request, response, e);
}
// Release the filter chain (if any) for this request
if (filterChain != null) {
if (request.isComet()) {
// If this is a Comet request, then the same chain will be used for the
// processing of all subsequent events.
filterChain.reuse();
} else {
filterChain.release();
}
}
// Deallocate the allocated servlet instance
try {
if (servlet != null) {
wrapper.deallocate(servlet);
}
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
container.getLogger().error(sm.getString("standardWrapper.deallocateException",
wrapper.getName()), e);
if (throwable == null) {
throwable = e;
exception(request, response, e);
}
}
// If this servlet has been marked permanently unavailable,
// unload it and release this instance
try {
if ((servlet != null) &&
(wrapper.getAvailable() == Long.MAX_VALUE)) {
wrapper.unload();
}
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
container.getLogger().error(sm.getString("standardWrapper.unloadException",
wrapper.getName()), e);
if (throwable == null) {
throwable = e;
exception(request, response, e);
}
}
long t2=System.currentTimeMillis();
long time=t2-t1;
processingTime += time;
if( time > maxTime) maxTime=time;
if( time < minTime) minTime=time;
}
// in java/org/apache/catalina/core/StandardWrapperValve.java
Override
public void event(Request request, Response response, CometEvent event)
throws IOException, ServletException {
// Initialize local variables we may need
Throwable throwable = null;
// This should be a Request attribute...
long t1=System.currentTimeMillis();
// FIXME: Add a flag to count the total amount of events processed ? requestCount++;
StandardWrapper wrapper = (StandardWrapper) getContainer();
if (wrapper == null) {
// Context has been shutdown. Nothing to do here.
return;
}
Servlet servlet = null;
Context context = (Context) wrapper.getParent();
// Check for the application being marked unavailable
boolean unavailable = !context.getAvailable() || wrapper.isUnavailable();
// Allocate a servlet instance to process this request
try {
if (!unavailable) {
servlet = wrapper.allocate();
}
} catch (UnavailableException e) {
// The response is already committed, so it's not possible to do anything
} catch (ServletException e) {
container.getLogger().error(sm.getString("standardWrapper.allocateException",
wrapper.getName()), StandardWrapper.getRootCause(e));
throwable = e;
exception(request, response, e);
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
container.getLogger().error(sm.getString("standardWrapper.allocateException",
wrapper.getName()), e);
throwable = e;
exception(request, response, e);
servlet = null;
}
MessageBytes requestPathMB = request.getRequestPathMB();
request.setAttribute
(ApplicationFilterFactory.DISPATCHER_TYPE_ATTR,
DispatcherType.REQUEST);
request.setAttribute
(ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR,
requestPathMB);
// Get the current (unchanged) filter chain for this request
ApplicationFilterChain filterChain =
(ApplicationFilterChain) request.getFilterChain();
// Call the filter chain for this request
// NOTE: This also calls the servlet's event() method
try {
if ((servlet != null) && (filterChain != null)) {
// Swallow output if needed
if (context.getSwallowOutput()) {
try {
SystemLogHandler.startCapture();
filterChain.doFilterEvent(request.getEvent());
} finally {
String log = SystemLogHandler.stopCapture();
if (log != null && log.length() > 0) {
context.getLogger().info(log);
}
}
} else {
filterChain.doFilterEvent(request.getEvent());
}
}
} catch (ClientAbortException e) {
throwable = e;
exception(request, response, e);
} catch (IOException e) {
container.getLogger().error(sm.getString(
"standardWrapper.serviceException", wrapper.getName(),
context.getName()), e);
throwable = e;
exception(request, response, e);
} catch (UnavailableException e) {
container.getLogger().error(sm.getString(
"standardWrapper.serviceException", wrapper.getName(),
context.getName()), e);
// Do not save exception in 'throwable', because we
// do not want to do exception(request, response, e) processing
} catch (ServletException e) {
Throwable rootCause = StandardWrapper.getRootCause(e);
if (!(rootCause instanceof ClientAbortException)) {
container.getLogger().error(sm.getString(
"standardWrapper.serviceExceptionRoot",
wrapper.getName(), context.getName(), e.getMessage()),
rootCause);
}
throwable = e;
exception(request, response, e);
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
container.getLogger().error(sm.getString(
"standardWrapper.serviceException", wrapper.getName(),
context.getName()), e);
throwable = e;
exception(request, response, e);
}
// Release the filter chain (if any) for this request
if (filterChain != null) {
filterChain.reuse();
}
// Deallocate the allocated servlet instance
try {
if (servlet != null) {
wrapper.deallocate(servlet);
}
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
container.getLogger().error(sm.getString("standardWrapper.deallocateException",
wrapper.getName()), e);
if (throwable == null) {
throwable = e;
exception(request, response, e);
}
}
// If this servlet has been marked permanently unavailable,
// unload it and release this instance
try {
if ((servlet != null) &&
(wrapper.getAvailable() == Long.MAX_VALUE)) {
wrapper.unload();
}
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
container.getLogger().error(sm.getString("standardWrapper.unloadException",
wrapper.getName()), e);
if (throwable == null) {
throwable = e;
exception(request, response, e);
}
}
long t2=System.currentTimeMillis();
long time=t2-t1;
processingTime += time;
if( time > maxTime) maxTime=time;
if( time < minTime) minTime=time;
}
// in java/org/apache/catalina/core/ApplicationHttpResponse.java
Override
public void sendError(int sc) throws IOException {
if (!included)
((HttpServletResponse) getResponse()).sendError(sc);
}
// in java/org/apache/catalina/core/ApplicationHttpResponse.java
Override
public void sendError(int sc, String msg) throws IOException {
if (!included)
((HttpServletResponse) getResponse()).sendError(sc, msg);
}
// in java/org/apache/catalina/core/ApplicationHttpResponse.java
Override
public void sendRedirect(String location) throws IOException {
if (!included)
((HttpServletResponse) getResponse()).sendRedirect(location);
}
// in java/org/apache/catalina/core/AsyncListenerWrapper.java
public void fireOnStartAsync(AsyncEvent event) throws IOException {
listener.onStartAsync(event);
}
// in java/org/apache/catalina/core/AsyncListenerWrapper.java
public void fireOnComplete(AsyncEvent event) throws IOException {
listener.onComplete(event);
}
// in java/org/apache/catalina/core/AsyncListenerWrapper.java
public void fireOnTimeout(AsyncEvent event) throws IOException {
listener.onTimeout(event);
}
// in java/org/apache/catalina/core/AsyncListenerWrapper.java
public void fireOnError(AsyncEvent event) throws IOException {
listener.onError(event);
}
// in java/org/apache/catalina/core/AsyncContextImpl.java
public boolean timeout() throws IOException {
AtomicBoolean result = new AtomicBoolean();
request.getCoyoteRequest().action(ActionCode.ASYNC_TIMEOUT, result);
if (result.get()) {
boolean listenerInvoked = false;
List<AsyncListenerWrapper> listenersCopy =
new ArrayList<AsyncListenerWrapper>();
listenersCopy.addAll(listeners);
for (AsyncListenerWrapper listener : listenersCopy) {
listener.fireOnTimeout(event);
listenerInvoked = true;
}
if (listenerInvoked) {
request.getCoyoteRequest().action(
ActionCode.ASYNC_IS_TIMINGOUT, result);
return !result.get();
} else {
// No listeners, container calls complete
complete();
}
}
return true;
}
// in java/org/apache/catalina/core/AsyncContextImpl.java
protected void doInternalDispatch() throws ServletException, IOException {
if (log.isDebugEnabled()) {
logDebug("intDispatch");
}
try {
dispatch.run();
if (!request.isAsync()) {
fireOnComplete();
}
} catch (RuntimeException x) {
// doInternalComplete(true);
if (x.getCause() instanceof ServletException) {
throw (ServletException)x.getCause();
}
if (x.getCause() instanceof IOException) {
throw (IOException)x.getCause();
}
throw new ServletException(x);
}
}
// in java/org/apache/catalina/core/StandardContextValve.java
Override
public final void invoke(Request request, Response response)
throws IOException, ServletException {
// Disallow any direct access to resources under WEB-INF or META-INF
MessageBytes requestPathMB = request.getRequestPathMB();
if ((requestPathMB.startsWithIgnoreCase("/META-INF/", 0))
|| (requestPathMB.equalsIgnoreCase("/META-INF"))
|| (requestPathMB.startsWithIgnoreCase("/WEB-INF/", 0))
|| (requestPathMB.equalsIgnoreCase("/WEB-INF"))) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
// Select the Wrapper to be used for this Request
Wrapper wrapper = request.getWrapper();
if (wrapper == null || wrapper.isUnavailable()) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
// Acknowledge the request
try {
response.sendAcknowledgement();
} catch (IOException ioe) {
container.getLogger().error(sm.getString(
"standardContextValve.acknowledgeException"), ioe);
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, ioe);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
}
if (request.isAsyncSupported()) {
request.setAsyncSupported(wrapper.getPipeline().isAsyncSupported());
}
wrapper.getPipeline().getFirst().invoke(request, response);
}
// in java/org/apache/catalina/core/StandardContextValve.java
Override
public final void event(Request request, Response response, CometEvent event)
throws IOException, ServletException {
// Select the Wrapper to be used for this Request
Wrapper wrapper = request.getWrapper();
wrapper.getPipeline().getFirst().event(request, response, event);
}
// in java/org/apache/catalina/core/StandardEngineValve.java
Override
public final void invoke(Request request, Response response)
throws IOException, ServletException {
// Select the Host to be used for this Request
Host host = request.getHost();
if (host == null) {
response.sendError
(HttpServletResponse.SC_BAD_REQUEST,
sm.getString("standardEngine.noHost",
request.getServerName()));
return;
}
if (request.isAsyncSupported()) {
request.setAsyncSupported(host.getPipeline().isAsyncSupported());
}
// Ask this Host to process this request
host.getPipeline().getFirst().invoke(request, response);
}
// in java/org/apache/catalina/core/StandardEngineValve.java
Override
public final void event(Request request, Response response, CometEvent event)
throws IOException, ServletException {
// Ask this Host to process this request
request.getHost().getPipeline().getFirst().event(request, response, event);
}
// in java/org/apache/catalina/core/StandardHostValve.java
Override
public final void invoke(Request request, Response response)
throws IOException, ServletException {
// Select the Context to be used for this Request
Context context = request.getContext();
if (context == null) {
response.sendError
(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
sm.getString("standardHost.noContext"));
return;
}
// Bind the context CL to the current thread
if( context.getLoader() != null ) {
// Not started - it should check for availability first
// This should eventually move to Engine, it's generic.
if (Globals.IS_SECURITY_ENABLED) {
PrivilegedAction<Void> pa = new PrivilegedSetTccl(
context.getLoader().getClassLoader());
AccessController.doPrivileged(pa);
} else {
Thread.currentThread().setContextClassLoader
(context.getLoader().getClassLoader());
}
}
if (request.isAsyncSupported()) {
request.setAsyncSupported(context.getPipeline().isAsyncSupported());
}
// Don't fire listeners during async processing
// If a request init listener throws an exception, the request is
// aborted
boolean asyncAtStart = request.isAsync();
if (asyncAtStart || context.fireRequestInitEvent(request)) {
// Ask this Context to process this request
try {
context.getPipeline().getFirst().invoke(request, response);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t);
throwable(request, response, t);
}
// If the request was async at the start and an error occurred then
// the async error handling will kick-in and that will fire the
// request destroyed event *after* the error handling has taken
// place
if (!(request.isAsync() || (asyncAtStart && request.getAttribute(
RequestDispatcher.ERROR_EXCEPTION) != null))) {
// Protect against NPEs if context was destroyed during a long
// running request.
if (context.getState().isAvailable()) {
// Error page processing
response.setSuspended(false);
Throwable t = (Throwable) request.getAttribute(
RequestDispatcher.ERROR_EXCEPTION);
if (t != null) {
throwable(request, response, t);
} else {
status(request, response);
}
context.fireRequestDestroyEvent(request);
}
}
}
// Access a session (if present) to update last accessed time, based on a
// strict interpretation of the specification
if (ACCESS_SESSION) {
request.getSession(false);
}
// Restore the context classloader
if (Globals.IS_SECURITY_ENABLED) {
PrivilegedAction<Void> pa = new PrivilegedSetTccl(
StandardHostValve.class.getClassLoader());
AccessController.doPrivileged(pa);
} else {
Thread.currentThread().setContextClassLoader
(StandardHostValve.class.getClassLoader());
}
}
// in java/org/apache/catalina/core/StandardHostValve.java
Override
public final void event(Request request, Response response, CometEvent event)
throws IOException, ServletException {
// Select the Context to be used for this Request
Context context = request.getContext();
// Bind the context CL to the current thread
if( context.getLoader() != null ) {
// Not started - it should check for availability first
// This should eventually move to Engine, it's generic.
Thread.currentThread().setContextClassLoader
(context.getLoader().getClassLoader());
}
// Ask this Context to process this request
context.getPipeline().getFirst().event(request, response, event);
// Error page processing
response.setSuspended(false);
Throwable t = (Throwable) request.getAttribute(
RequestDispatcher.ERROR_EXCEPTION);
if (t != null) {
throwable(request, response, t);
} else {
status(request, response);
}
// Access a session (if present) to update last accessed time, based on a
// strict interpretation of the specification
if (ACCESS_SESSION) {
request.getSession(false);
}
// Restore the context classloader
Thread.currentThread().setContextClassLoader
(StandardHostValve.class.getClassLoader());
}
// in java/org/apache/catalina/core/ApplicationPart.java
Override
public void delete() throws IOException {
fileItem.delete();
}
// in java/org/apache/catalina/core/ApplicationPart.java
Override
public InputStream getInputStream() throws IOException {
return fileItem.getInputStream();
}
// in java/org/apache/catalina/core/ApplicationPart.java
Override
public void write(String fileName) throws IOException {
File file = new File(fileName);
if (!file.isAbsolute()) {
file = new File(mce.getLocation(), fileName);
}
try {
fileItem.write(file);
} catch (Exception e) {
throw new IOException(e);
}
}
// in java/org/apache/catalina/core/ApplicationDispatcher.java
Override
public Void run() throws ServletException, IOException {
DispatcherType type = DispatcherType.INCLUDE;
if (request.getDispatcherType()==DispatcherType.ASYNC) type = DispatcherType.ASYNC;
doInclude(request,response,type);
return null;
}
// in java/org/apache/catalina/core/ApplicationDispatcher.java
Override
public void forward(ServletRequest request, ServletResponse response)
throws ServletException, IOException
{
if (Globals.IS_SECURITY_ENABLED) {
try {
PrivilegedForward dp = new PrivilegedForward(request,response);
AccessController.doPrivileged(dp);
} catch (PrivilegedActionException pe) {
Exception e = pe.getException();
if (e instanceof ServletException)
throw (ServletException) e;
throw (IOException) e;
}
} else {
doForward(request,response);
}
}
// in java/org/apache/catalina/core/ApplicationDispatcher.java
private void doForward(ServletRequest request, ServletResponse response)
throws ServletException, IOException
{
// Reset any output that has been buffered, but keep headers/cookies
if (response.isCommitted()) {
throw new IllegalStateException
(sm.getString("applicationDispatcher.forward.ise"));
}
try {
response.resetBuffer();
} catch (IllegalStateException e) {
throw e;
}
// Set up to handle the specified request and response
State state = new State(request, response, false);
if (WRAP_SAME_OBJECT) {
// Check SRV.8.2 / SRV.14.2.5.1 compliance
checkSameObjects(request, response);
}
wrapResponse(state);
// Handle an HTTP named dispatcher forward
if ((servletPath == null) && (pathInfo == null)) {
ApplicationHttpRequest wrequest =
(ApplicationHttpRequest) wrapRequest(state);
HttpServletRequest hrequest = state.hrequest;
wrequest.setRequestURI(hrequest.getRequestURI());
wrequest.setContextPath(hrequest.getContextPath());
wrequest.setServletPath(hrequest.getServletPath());
wrequest.setPathInfo(hrequest.getPathInfo());
wrequest.setQueryString(hrequest.getQueryString());
processRequest(request,response,state);
}
// Handle an HTTP path-based forward
else {
ApplicationHttpRequest wrequest =
(ApplicationHttpRequest) wrapRequest(state);
String contextPath = context.getPath();
HttpServletRequest hrequest = state.hrequest;
if (hrequest.getAttribute(
RequestDispatcher.FORWARD_REQUEST_URI) == null) {
wrequest.setAttribute(RequestDispatcher.FORWARD_REQUEST_URI,
hrequest.getRequestURI());
wrequest.setAttribute(RequestDispatcher.FORWARD_CONTEXT_PATH,
hrequest.getContextPath());
wrequest.setAttribute(RequestDispatcher.FORWARD_SERVLET_PATH,
hrequest.getServletPath());
wrequest.setAttribute(RequestDispatcher.FORWARD_PATH_INFO,
hrequest.getPathInfo());
wrequest.setAttribute(RequestDispatcher.FORWARD_QUERY_STRING,
hrequest.getQueryString());
}
wrequest.setContextPath(contextPath);
wrequest.setRequestURI(requestURI);
wrequest.setServletPath(servletPath);
wrequest.setPathInfo(pathInfo);
if (queryString != null) {
wrequest.setQueryString(queryString);
wrequest.setQueryParams(queryString);
}
processRequest(request,response,state);
}
// This is not a real close in order to support error processing
if (wrapper.getLogger().isDebugEnabled() )
wrapper.getLogger().debug(" Disabling the response for futher output");
if (response instanceof ResponseFacade) {
((ResponseFacade) response).finish();
} else {
// Servlet SRV.6.2.2. The Request/Response may have been wrapped
// and may no longer be instance of RequestFacade
if (wrapper.getLogger().isDebugEnabled()){
wrapper.getLogger().debug( " The Response is vehiculed using a wrapper: "
+ response.getClass().getName() );
}
// Close anyway
try {
PrintWriter writer = response.getWriter();
writer.close();
} catch (IllegalStateException e) {
try {
ServletOutputStream stream = response.getOutputStream();
stream.close();
} catch (IllegalStateException f) {
// Ignore
} catch (IOException f) {
// Ignore
}
} catch (IOException e) {
// Ignore
}
}
}
// in java/org/apache/catalina/core/ApplicationDispatcher.java
private void processRequest(ServletRequest request,
ServletResponse response,
State state)
throws IOException, ServletException {
DispatcherType disInt = (DispatcherType) request.getAttribute(ApplicationFilterFactory.DISPATCHER_TYPE_ATTR);
if (disInt != null) {
boolean doInvoke = true;
if (context.getFireRequestListenersOnForwards() &&
!context.fireRequestInitEvent(request)) {
doInvoke = false;
}
if (doInvoke) {
if (disInt != DispatcherType.ERROR) {
state.outerRequest.setAttribute
(ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR,
getCombinedPath());
state.outerRequest.setAttribute
(ApplicationFilterFactory.DISPATCHER_TYPE_ATTR,
DispatcherType.FORWARD);
invoke(state.outerRequest, response, state);
} else {
invoke(state.outerRequest, response, state);
}
if (context.getFireRequestListenersOnForwards()) {
context.fireRequestDestroyEvent(request);
}
}
}
}
// in java/org/apache/catalina/core/ApplicationDispatcher.java
Override
public void include(ServletRequest request, ServletResponse response)
throws ServletException, IOException
{
if (Globals.IS_SECURITY_ENABLED) {
try {
PrivilegedInclude dp = new PrivilegedInclude(request,response);
AccessController.doPrivileged(dp);
} catch (PrivilegedActionException pe) {
Exception e = pe.getException();
if (e instanceof ServletException)
throw (ServletException) e;
throw (IOException) e;
}
} else {
DispatcherType type = DispatcherType.INCLUDE;
if (request.getDispatcherType()==DispatcherType.ASYNC) type = DispatcherType.ASYNC;
doInclude(request,response,type);
}
}
// in java/org/apache/catalina/core/ApplicationDispatcher.java
private void doInclude(ServletRequest request, ServletResponse response, DispatcherType type)
throws ServletException, IOException
{
// Set up to handle the specified request and response
State state = new State(request, response, true);
if (WRAP_SAME_OBJECT) {
// Check SRV.8.2 / SRV.14.2.5.1 compliance
checkSameObjects(request, response);
}
// Create a wrapped response to use for this request
wrapResponse(state);
// Handle an HTTP named dispatcher include
if (name != null) {
ApplicationHttpRequest wrequest =
(ApplicationHttpRequest) wrapRequest(state);
wrequest.setAttribute(Globals.NAMED_DISPATCHER_ATTR, name);
if (servletPath != null)
wrequest.setServletPath(servletPath);
wrequest.setAttribute(ApplicationFilterFactory.DISPATCHER_TYPE_ATTR,
type);
wrequest.setAttribute(
ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR,
getCombinedPath());
invoke(state.outerRequest, state.outerResponse, state);
}
// Handle an HTTP path based include
else {
ApplicationHttpRequest wrequest =
(ApplicationHttpRequest) wrapRequest(state);
String contextPath = context.getPath();
if (requestURI != null)
wrequest.setAttribute(RequestDispatcher.INCLUDE_REQUEST_URI,
requestURI);
if (contextPath != null)
wrequest.setAttribute(RequestDispatcher.INCLUDE_CONTEXT_PATH,
contextPath);
if (servletPath != null)
wrequest.setAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH,
servletPath);
if (pathInfo != null)
wrequest.setAttribute(RequestDispatcher.INCLUDE_PATH_INFO,
pathInfo);
if (queryString != null) {
wrequest.setAttribute(RequestDispatcher.INCLUDE_QUERY_STRING,
queryString);
wrequest.setQueryParams(queryString);
}
wrequest.setAttribute(ApplicationFilterFactory.DISPATCHER_TYPE_ATTR,
type);
wrequest.setAttribute(
ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR,
getCombinedPath());
invoke(state.outerRequest, state.outerResponse, state);
}
}
// in java/org/apache/catalina/core/ApplicationDispatcher.java
private void invoke(ServletRequest request, ServletResponse response,
State state) throws IOException, ServletException {
// Checking to see if the context classloader is the current context
// classloader. If it's not, we're saving it, and setting the context
// classloader to the Context classloader
ClassLoader oldCCL = Thread.currentThread().getContextClassLoader();
ClassLoader contextClassLoader = context.getLoader().getClassLoader();
if (oldCCL != contextClassLoader) {
Thread.currentThread().setContextClassLoader(contextClassLoader);
} else {
oldCCL = null;
}
// Initialize local variables we may need
HttpServletResponse hresponse = state.hresponse;
Servlet servlet = null;
IOException ioException = null;
ServletException servletException = null;
RuntimeException runtimeException = null;
boolean unavailable = false;
// Check for the servlet being marked unavailable
if (wrapper.isUnavailable()) {
wrapper.getLogger().warn(
sm.getString("applicationDispatcher.isUnavailable",
wrapper.getName()));
long available = wrapper.getAvailable();
if ((available > 0L) && (available < Long.MAX_VALUE))
hresponse.setDateHeader("Retry-After", available);
hresponse.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm
.getString("applicationDispatcher.isUnavailable", wrapper
.getName()));
unavailable = true;
}
// Allocate a servlet instance to process this request
try {
if (!unavailable) {
servlet = wrapper.allocate();
}
} catch (ServletException e) {
wrapper.getLogger().error(sm.getString("applicationDispatcher.allocateException",
wrapper.getName()), StandardWrapper.getRootCause(e));
servletException = e;
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
wrapper.getLogger().error(sm.getString("applicationDispatcher.allocateException",
wrapper.getName()), e);
servletException = new ServletException
(sm.getString("applicationDispatcher.allocateException",
wrapper.getName()), e);
servlet = null;
}
// Get the FilterChain Here
ApplicationFilterFactory factory = ApplicationFilterFactory.getInstance();
ApplicationFilterChain filterChain = factory.createFilterChain(request,
wrapper,servlet);
// Call the service() method for the allocated servlet instance
try {
support.fireInstanceEvent(InstanceEvent.BEFORE_DISPATCH_EVENT,
servlet, request, response);
// for includes/forwards
if ((servlet != null) && (filterChain != null)) {
filterChain.doFilter(request, response);
}
// Servlet Service Method is called by the FilterChain
support.fireInstanceEvent(InstanceEvent.AFTER_DISPATCH_EVENT,
servlet, request, response);
} catch (ClientAbortException e) {
support.fireInstanceEvent(InstanceEvent.AFTER_DISPATCH_EVENT,
servlet, request, response);
ioException = e;
} catch (IOException e) {
support.fireInstanceEvent(InstanceEvent.AFTER_DISPATCH_EVENT,
servlet, request, response);
wrapper.getLogger().error(sm.getString("applicationDispatcher.serviceException",
wrapper.getName()), e);
ioException = e;
} catch (UnavailableException e) {
support.fireInstanceEvent(InstanceEvent.AFTER_DISPATCH_EVENT,
servlet, request, response);
wrapper.getLogger().error(sm.getString("applicationDispatcher.serviceException",
wrapper.getName()), e);
servletException = e;
wrapper.unavailable(e);
} catch (ServletException e) {
support.fireInstanceEvent(InstanceEvent.AFTER_DISPATCH_EVENT,
servlet, request, response);
Throwable rootCause = StandardWrapper.getRootCause(e);
if (!(rootCause instanceof ClientAbortException)) {
wrapper.getLogger().error(sm.getString("applicationDispatcher.serviceException",
wrapper.getName()), rootCause);
}
servletException = e;
} catch (RuntimeException e) {
support.fireInstanceEvent(InstanceEvent.AFTER_DISPATCH_EVENT,
servlet, request, response);
wrapper.getLogger().error(sm.getString("applicationDispatcher.serviceException",
wrapper.getName()), e);
runtimeException = e;
}
// Release the filter chain (if any) for this request
try {
if (filterChain != null)
filterChain.release();
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
wrapper.getLogger().error(sm.getString("standardWrapper.releaseFilters",
wrapper.getName()), e);
// FIXME: Exception handling needs to be similar to what is in the StandardWrapperValue
}
// Deallocate the allocated servlet instance
try {
if (servlet != null) {
wrapper.deallocate(servlet);
}
} catch (ServletException e) {
wrapper.getLogger().error(sm.getString("applicationDispatcher.deallocateException",
wrapper.getName()), e);
servletException = e;
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
wrapper.getLogger().error(sm.getString("applicationDispatcher.deallocateException",
wrapper.getName()), e);
servletException = new ServletException
(sm.getString("applicationDispatcher.deallocateException",
wrapper.getName()), e);
}
// Reset the old context class loader
if (oldCCL != null)
Thread.currentThread().setContextClassLoader(oldCCL);
// Unwrap request/response if needed
// See Bugzilla 30949
unwrapRequest(state);
unwrapResponse(state);
// Recycle request if necessary (also BZ 30949)
recycleRequestWrapper(state);
// Rethrow an exception if one was thrown by the invoked servlet
if (ioException != null)
throw ioException;
if (servletException != null)
throw servletException;
if (runtimeException != null)
throw runtimeException;
}
// in java/org/apache/catalina/util/CustomObjectInputStream.java
Override
public Class<?> resolveClass(ObjectStreamClass classDesc)
throws ClassNotFoundException, IOException {
try {
return Class.forName(classDesc.getName(), false, classLoader);
} catch (ClassNotFoundException e) {
try {
// Try also the superclass because of primitive types
return super.resolveClass(classDesc);
} catch (ClassNotFoundException e2) {
// Rethrow original exception, as it can have more information
// about why the class was not found. BZ 48007
throw e;
}
}
}
// in java/org/apache/catalina/util/CustomObjectInputStream.java
Override
protected Class<?> resolveProxyClass(String[] interfaces)
throws IOException, ClassNotFoundException {
Class<?>[] cinterfaces = new Class[interfaces.length];
for (int i = 0; i < interfaces.length; i++)
cinterfaces[i] = classLoader.loadClass(interfaces[i]);
try {
return Proxy.getProxyClass(classLoader, cinterfaces);
} catch (IllegalArgumentException e) {
throw new ClassNotFoundException(null, e);
}
}
// in java/org/apache/catalina/util/XMLWriter.java
public void sendData()
throws IOException {
if (writer != null) {
writer.write(buffer.toString());
buffer = new StringBuilder();
}
}
// in java/org/apache/catalina/util/Conversions.java
public static long byteArrayToLong(byte[] input) throws IOException {
if (input.length > 8) {
// TODO: Better message
throw new IOException();
}
int shift = 0;
long result = 0;
for (int i = input.length - 1; i >= 0; i--) {
result = result + ((input[i] & 0xFF) << shift);
shift += 8;
}
return result;
}
// in java/org/apache/catalina/util/IOTools.java
public static void flow( Reader reader, Writer writer, char[] buf )
throws IOException {
int numRead;
while ( (numRead = reader.read(buf) ) >= 0) {
writer.write(buf, 0, numRead);
}
}
// in java/org/apache/catalina/util/IOTools.java
public static void flow( Reader reader, Writer writer )
throws IOException {
char[] buf = new char[DEFAULT_BUFFER_SIZE];
flow( reader, writer, buf );
}
// in java/org/apache/catalina/util/IOTools.java
public static void flow( InputStream is, OutputStream os, byte[] buf )
throws IOException {
int numRead;
while ( (numRead = is.read(buf) ) >= 0) {
os.write(buf, 0, numRead);
}
}
// in java/org/apache/catalina/util/IOTools.java
public static void flow( InputStream is, OutputStream os )
throws IOException {
byte[] buf = new byte[DEFAULT_BUFFER_SIZE];
flow( is, os, buf );
}
// in java/org/apache/catalina/util/ExtensionValidator.java
public static synchronized boolean validateApplication(
DirContext dirContext,
Context context)
throws IOException {
String appName = context.getName();
ArrayList<ManifestResource> appManifestResources =
new ArrayList<ManifestResource>();
// If the application context is null it does not exist and
// therefore is not valid
if (dirContext == null) return false;
// Find the Manifest for the Web Application
InputStream inputStream = null;
try {
NamingEnumeration<Binding> wne =
dirContext.listBindings("/META-INF/");
Binding binding = wne.nextElement();
if (binding.getName().toUpperCase(Locale.ENGLISH).equals("MANIFEST.MF")) {
Resource resource = (Resource)dirContext.lookup
("/META-INF/" + binding.getName());
inputStream = resource.streamContent();
Manifest manifest = new Manifest(inputStream);
inputStream.close();
inputStream = null;
ManifestResource mre = new ManifestResource
(sm.getString("extensionValidator.web-application-manifest"),
manifest, ManifestResource.WAR);
appManifestResources.add(mre);
}
} catch (NamingException nex) {
// Application does not contain a MANIFEST.MF file
} catch (NoSuchElementException nse) {
// Application does not contain a MANIFEST.MF file
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
}
}
}
// Locate the Manifests for all bundled JARs
NamingEnumeration<Binding> ne = null;
try {
ne = dirContext.listBindings("WEB-INF/lib/");
while ((ne != null) && ne.hasMoreElements()) {
Binding binding = ne.nextElement();
if (!binding.getName().toLowerCase(Locale.ENGLISH).endsWith(".jar")) {
continue;
}
Object obj =
dirContext.lookup("/WEB-INF/lib/" + binding.getName());
if (!(obj instanceof Resource)) {
// Probably a directory named xxx.jar - ignore it
continue;
}
Resource resource = (Resource) obj;
inputStream = resource.streamContent();
Manifest jmanifest = getManifest(inputStream);
if (jmanifest != null) {
ManifestResource mre = new ManifestResource(
binding.getName(),
jmanifest,
ManifestResource.APPLICATION);
appManifestResources.add(mre);
}
}
} catch (NamingException nex) {
// Jump out of the check for this application because it
// has no resources
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
}
}
}
return validateManifestResources(appName, appManifestResources);
}
// in java/org/apache/catalina/util/ExtensionValidator.java
public static void addSystemResource(File jarFile) throws IOException {
Manifest manifest = getManifest(new FileInputStream(jarFile));
if (manifest != null) {
ManifestResource mre
= new ManifestResource(jarFile.getAbsolutePath(),
manifest,
ManifestResource.SYSTEM);
containerManifestResources.add(mre);
}
}
// in java/org/apache/catalina/util/ExtensionValidator.java
private static Manifest getManifest(InputStream inStream)
throws IOException {
Manifest manifest = null;
JarInputStream jin = null;
try {
jin = new JarInputStream(inStream);
manifest = jin.getManifest();
jin.close();
jin = null;
} finally {
if (jin != null) {
try {
jin.close();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
}
}
}
return manifest;
}
// in java/javax/servlet/jsp/tagext/SimpleTagSupport.java
Override
public void doTag() throws JspException, IOException {
// NOOP by default
}
// in java/javax/servlet/jsp/tagext/BodyContent.java
Override
public void flush() throws IOException {
throw new IOException("Illegal to flush within a custom tag");
}
// in java/javax/servlet/ServletInputStream.java
public int readLine(byte[] b, int off, int len) throws IOException {
if (len <= 0) {
return 0;
}
int count = 0, c;
while ((c = read()) != -1) {
b[off++] = (byte) c;
count++;
if (c == '\n' || count == len) {
break;
}
}
return count > 0 ? count : -1;
}
// in java/javax/servlet/http/HttpServletRequestWrapper.java
Override
public boolean authenticate(HttpServletResponse response)
throws IOException, ServletException {
return this._getHttpServletRequest().authenticate(response);
}
// in java/javax/servlet/http/HttpServletRequestWrapper.java
Override
public Collection<Part> getParts() throws IllegalStateException,
IOException, ServletException {
return this._getHttpServletRequest().getParts();
}
// in java/javax/servlet/http/HttpServletRequestWrapper.java
Override
public Part getPart(String name) throws IllegalStateException, IOException,
ServletException {
return this._getHttpServletRequest().getPart(name);
}
// in java/javax/servlet/http/HttpServletResponseWrapper.java
Override
public void sendError(int sc, String msg) throws IOException {
this._getHttpServletResponse().sendError(sc, msg);
}
// in java/javax/servlet/http/HttpServletResponseWrapper.java
Override
public void sendError(int sc) throws IOException {
this._getHttpServletResponse().sendError(sc);
}
// in java/javax/servlet/http/HttpServletResponseWrapper.java
Override
public void sendRedirect(String location) throws IOException {
this._getHttpServletResponse().sendRedirect(location);
}
// in java/javax/servlet/http/HttpServlet.java
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method_get_not_supported");
if (protocol.endsWith("1.1")) {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
} else {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
}
}
// in java/javax/servlet/http/HttpServlet.java
protected void doHead(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
NoBodyResponse response = new NoBodyResponse(resp);
doGet(req, response);
response.setContentLength();
}
// in java/javax/servlet/http/HttpServlet.java
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method_post_not_supported");
if (protocol.endsWith("1.1")) {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
} else {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
}
}
// in java/javax/servlet/http/HttpServlet.java
protected void doPut(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method_put_not_supported");
if (protocol.endsWith("1.1")) {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
} else {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
}
}
// in java/javax/servlet/http/HttpServlet.java
protected void doDelete(HttpServletRequest req,
HttpServletResponse resp)
throws ServletException, IOException {
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method_delete_not_supported");
if (protocol.endsWith("1.1")) {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
} else {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
}
}
// in java/javax/servlet/http/HttpServlet.java
protected void doOptions(HttpServletRequest req,
HttpServletResponse resp)
throws ServletException, IOException {
Method[] methods = getAllDeclaredMethods(this.getClass());
boolean ALLOW_GET = false;
boolean ALLOW_HEAD = false;
boolean ALLOW_POST = false;
boolean ALLOW_PUT = false;
boolean ALLOW_DELETE = false;
boolean ALLOW_TRACE = true;
boolean ALLOW_OPTIONS = true;
for (int i=0; i<methods.length; i++) {
Method m = methods[i];
if (m.getName().equals("doGet")) {
ALLOW_GET = true;
ALLOW_HEAD = true;
}
if (m.getName().equals("doPost"))
ALLOW_POST = true;
if (m.getName().equals("doPut"))
ALLOW_PUT = true;
if (m.getName().equals("doDelete"))
ALLOW_DELETE = true;
}
String allow = null;
if (ALLOW_GET)
allow=METHOD_GET;
if (ALLOW_HEAD)
if (allow==null) allow=METHOD_HEAD;
else allow += ", " + METHOD_HEAD;
if (ALLOW_POST)
if (allow==null) allow=METHOD_POST;
else allow += ", " + METHOD_POST;
if (ALLOW_PUT)
if (allow==null) allow=METHOD_PUT;
else allow += ", " + METHOD_PUT;
if (ALLOW_DELETE)
if (allow==null) allow=METHOD_DELETE;
else allow += ", " + METHOD_DELETE;
if (ALLOW_TRACE)
if (allow==null) allow=METHOD_TRACE;
else allow += ", " + METHOD_TRACE;
if (ALLOW_OPTIONS)
if (allow==null) allow=METHOD_OPTIONS;
else allow += ", " + METHOD_OPTIONS;
resp.setHeader("Allow", allow);
}
// in java/javax/servlet/http/HttpServlet.java
protected void doTrace(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
int responseLength;
String CRLF = "\r\n";
StringBuilder buffer = new StringBuilder("TRACE ").append(req.getRequestURI())
.append(" ").append(req.getProtocol());
Enumeration<String> reqHeaderEnum = req.getHeaderNames();
while( reqHeaderEnum.hasMoreElements() ) {
String headerName = reqHeaderEnum.nextElement();
buffer.append(CRLF).append(headerName).append(": ")
.append(req.getHeader(headerName));
}
buffer.append(CRLF);
responseLength = buffer.length();
resp.setContentType("message/http");
resp.setContentLength(responseLength);
ServletOutputStream out = resp.getOutputStream();
out.print(buffer.toString());
out.close();
return;
}
// in java/javax/servlet/http/HttpServlet.java
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String method = req.getMethod();
if (method.equals(METHOD_GET)) {
long lastModified = getLastModified(req);
if (lastModified == -1) {
// servlet doesn't support if-modified-since, no reason
// to go through further expensive logic
doGet(req, resp);
} else {
long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
if (ifModifiedSince < (lastModified / 1000 * 1000)) {
// If the servlet mod time is later, call doGet()
// Round down to the nearest second for a proper compare
// A ifModifiedSince of -1 will always be less
maybeSetLastModified(resp, lastModified);
doGet(req, resp);
} else {
resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
}
}
} else if (method.equals(METHOD_HEAD)) {
long lastModified = getLastModified(req);
maybeSetLastModified(resp, lastModified);
doHead(req, resp);
} else if (method.equals(METHOD_POST)) {
doPost(req, resp);
} else if (method.equals(METHOD_PUT)) {
doPut(req, resp);
} else if (method.equals(METHOD_DELETE)) {
doDelete(req, resp);
} else if (method.equals(METHOD_OPTIONS)) {
doOptions(req,resp);
} else if (method.equals(METHOD_TRACE)) {
doTrace(req,resp);
} else {
//
// Note that this means NO servlet supports whatever
// method was requested, anywhere on this server.
//
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[1];
errArgs[0] = method;
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
}
}
// in java/javax/servlet/http/HttpServlet.java
Override
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
HttpServletRequest request;
HttpServletResponse response;
try {
request = (HttpServletRequest) req;
response = (HttpServletResponse) res;
} catch (ClassCastException e) {
throw new ServletException("non-HTTP request or response");
}
service(request, response);
}
// in java/javax/servlet/http/HttpServlet.java
Override
public ServletOutputStream getOutputStream() throws IOException {
return noBody;
}
// in java/javax/servlet/http/HttpServlet.java
Override
public void write(byte buf[], int offset, int len)
throws IOException
{
if (len >= 0) {
contentLength += len;
} else {
// XXX
// isn't this really an IllegalArgumentException?
String msg = lStrings.getString("err.io.negativelength");
throw new IOException(msg);
}
}
// in java/javax/servlet/ServletResponseWrapper.java
Override
public ServletOutputStream getOutputStream() throws IOException {
return this.response.getOutputStream();
}
// in java/javax/servlet/ServletResponseWrapper.java
Override
public PrintWriter getWriter() throws IOException {
return this.response.getWriter();
}
// in java/javax/servlet/ServletResponseWrapper.java
Override
public void flushBuffer() throws IOException {
this.response.flushBuffer();
}
// in java/javax/servlet/ServletOutputStream.java
public void print(String s) throws IOException {
if (s == null)
s = "null";
int len = s.length();
for (int i = 0; i < len; i++) {
char c = s.charAt(i);
//
// XXX NOTE: This is clearly incorrect for many strings,
// but is the only consistent approach within the current
// servlet framework. It must suffice until servlet output
// streams properly encode their output.
//
if ((c & 0xff00) != 0) { // high order byte must be zero
String errMsg = lStrings.getString("err.not_iso8859_1");
Object[] errArgs = new Object[1];
errArgs[0] = Character.valueOf(c);
errMsg = MessageFormat.format(errMsg, errArgs);
throw new CharConversionException(errMsg);
}
write(c);
}
}
// in java/javax/servlet/ServletOutputStream.java
public void print(boolean b) throws IOException {
String msg;
if (b) {
msg = lStrings.getString("value.true");
} else {
msg = lStrings.getString("value.false");
}
print(msg);
}
// in java/javax/servlet/ServletOutputStream.java
public void print(char c) throws IOException {
print(String.valueOf(c));
}
// in java/javax/servlet/ServletOutputStream.java
public void print(int i) throws IOException {
print(String.valueOf(i));
}
// in java/javax/servlet/ServletOutputStream.java
public void print(long l) throws IOException {
print(String.valueOf(l));
}
// in java/javax/servlet/ServletOutputStream.java
public void print(float f) throws IOException {
print(String.valueOf(f));
}
// in java/javax/servlet/ServletOutputStream.java
public void print(double d) throws IOException {
print(String.valueOf(d));
}
// in java/javax/servlet/ServletOutputStream.java
public void println() throws IOException {
print("\r\n");
}
// in java/javax/servlet/ServletOutputStream.java
public void println(String s) throws IOException {
print(s);
println();
}
// in java/javax/servlet/ServletOutputStream.java
public void println(boolean b) throws IOException {
print(b);
println();
}
// in java/javax/servlet/ServletOutputStream.java
public void println(char c) throws IOException {
print(c);
println();
}
// in java/javax/servlet/ServletOutputStream.java
public void println(int i) throws IOException {
print(i);
println();
}
// in java/javax/servlet/ServletOutputStream.java
public void println(long l) throws IOException {
print(l);
println();
}
// in java/javax/servlet/ServletOutputStream.java
public void println(float f) throws IOException {
print(f);
println();
}
// in java/javax/servlet/ServletOutputStream.java
public void println(double d) throws IOException {
print(d);
println();
}
// in java/javax/servlet/ServletRequestWrapper.java
Override
public ServletInputStream getInputStream() throws IOException {
return this.request.getInputStream();
}
// in java/javax/servlet/ServletRequestWrapper.java
Override
public BufferedReader getReader() throws IOException {
return this.request.getReader();
}