Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaymond Auge2016-02-14 18:15:24 +0000
committerRaymond Auge2016-02-14 18:15:24 +0000
commitd2b8f80db99d33e78315fb7943a4ba01d9b7ebfd (patch)
tree9151f55dc491375f6beae63e73676a3f007ce46d /bundles/org.eclipse.equinox.http.servlet
parent609f393435ae36521fbe514e52ffa6b96b2bc7f8 (diff)
downloadrt.equinox.bundles-d2b8f80db99d33e78315fb7943a4ba01d9b7ebfd.tar.gz
rt.equinox.bundles-d2b8f80db99d33e78315fb7943a4ba01d9b7ebfd.tar.xz
rt.equinox.bundles-d2b8f80db99d33e78315fb7943a4ba01d9b7ebfd.zip
Bug 487627 - [http] IllegalStateException in DispatchTargets
Be friendlier to those cases where the stream/writer is not flushed or closed (I think most implementations do this also). Also make a general cleanup and improvement in dispatching, particularly in forward. Signed-off-by: Raymond Auge <raymond.auge@liferay.com>
Diffstat (limited to 'bundles/org.eclipse.equinox.http.servlet')
-rw-r--r--bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/DispatchTargets.java36
-rw-r--r--bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/HttpServletRequestWrapperImpl.java14
-rw-r--r--bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/HttpServletResponseWrapperImpl.java157
-rw-r--r--bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/RequestDispatcherAdaptor.java4
-rw-r--r--bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/ResponseStateHandler.java112
5 files changed, 232 insertions, 91 deletions
diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/DispatchTargets.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/DispatchTargets.java
index cf18d82a..a082e27d 100644
--- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/DispatchTargets.java
+++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/DispatchTargets.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2014, 2015 Raymond Augé and others.
+ * Copyright (c) 2014, 2016 Raymond Augé and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -65,41 +65,31 @@ public class DispatchTargets {
String path, DispatcherType dispatcherType)
throws ServletException, IOException {
- HttpServletRequestWrapperImpl httpRuntimeRequest = HttpServletRequestWrapperImpl.findHttpRuntimeRequest(request);
- boolean pushedState = false;
+ HttpServletRequestWrapperImpl requestWrapper = HttpServletRequestWrapperImpl.findHttpRuntimeRequest(request);
+ HttpServletResponse responseWrapper = HttpServletResponseWrapperImpl.findHttpRuntimeResponse(response);
try {
- if (httpRuntimeRequest == null) {
- httpRuntimeRequest = new HttpServletRequestWrapperImpl(request, this, dispatcherType);
- request = httpRuntimeRequest;
- response = new HttpServletResponseWrapperImpl(response);
+ if (requestWrapper == null) {
+ requestWrapper = new HttpServletRequestWrapperImpl(request);
+ request = requestWrapper;
}
- else {
- httpRuntimeRequest.push(this, dispatcherType);
- pushedState = true;
+
+ if (responseWrapper == null) {
+ responseWrapper = new HttpServletResponseWrapperImpl(response);
+ response = responseWrapper;
}
+ requestWrapper.push(this, dispatcherType);
+
ResponseStateHandler responseStateHandler = new ResponseStateHandler(
request, response, this, dispatcherType);
responseStateHandler.processRequest();
- if ((dispatcherType == DispatcherType.FORWARD) &&
- !response.isCommitted()) {
-
- response.flushBuffer();
- response.getWriter().close();
- }
-
return true;
}
finally {
- if (pushedState) {
- httpRuntimeRequest.pop();
- }
- else {
- httpRuntimeRequest.destroy();
- }
+ requestWrapper.pop();
}
}
diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/HttpServletRequestWrapperImpl.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/HttpServletRequestWrapperImpl.java
index c7b88d09..25ae2593 100644
--- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/HttpServletRequestWrapperImpl.java
+++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/HttpServletRequestWrapperImpl.java
@@ -132,6 +132,7 @@ public class HttpServletRequestWrapperImpl extends HttpServletRequestWrapper {
private final Deque<State> state = new ArrayDeque<State>();
private final HttpServletRequest request;
+ private final Map<String, Object> attributes;
public static HttpServletRequestWrapperImpl findHttpRuntimeRequest(
HttpServletRequest request) {
@@ -147,7 +148,7 @@ public class HttpServletRequestWrapperImpl extends HttpServletRequestWrapper {
return null;
}
- public HttpServletRequestWrapperImpl(HttpServletRequest request, DispatchTargets dispatchTargets, DispatcherType dispatcherType) {
+ public HttpServletRequestWrapperImpl(HttpServletRequest request) {
super(request);
this.request = request;
@@ -158,7 +159,7 @@ public class HttpServletRequestWrapperImpl extends HttpServletRequestWrapper {
attributes.put(name, request.getAttribute(name));
}
- this.getState().push(new State(dispatchTargets, dispatcherType, attributes, request.getParameterMap(), request.getQueryString()));
+ this.attributes = attributes;
}
public void destroy() {
@@ -368,8 +369,13 @@ public class HttpServletRequestWrapperImpl extends HttpServletRequestWrapper {
}
public synchronized void push(DispatchTargets dispatchTargets, DispatcherType dispatcherType) {
- State previous = getState().peek();
- getState().push(new State(dispatchTargets, dispatcherType, previous.getAttributes(), previous.getParameterMap(), previous.getQueryString()));
+ Deque<State> curState = getState();
+ State previous = curState.peek();
+ if (previous == null) {
+ curState.push(new State(dispatchTargets, dispatcherType, attributes, request.getParameterMap(), request.getQueryString()));
+ return;
+ }
+ curState.push(new State(dispatchTargets, dispatcherType, previous.getAttributes(), previous.getParameterMap(), previous.getQueryString()));
}
public void removeAttribute(String name) {
diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/HttpServletResponseWrapperImpl.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/HttpServletResponseWrapperImpl.java
index 89287d81..0b7518d0 100644
--- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/HttpServletResponseWrapperImpl.java
+++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/HttpServletResponseWrapperImpl.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2014 Raymond Augé and others.
+ * Copyright (c) 2014, 2016 Raymond Augé and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -11,6 +11,11 @@
package org.eclipse.equinox.http.servlet.internal.servlet;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Locale;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
@@ -24,15 +29,6 @@ public class HttpServletResponseWrapperImpl extends HttpServletResponseWrapper {
}
@Override
- public boolean isCommitted() {
- if (this.status != -1) {
- return true;
- }
-
- return super.isCommitted();
- }
-
- @Override
public void sendError(int status) {
this.status = status;
}
@@ -52,7 +48,148 @@ public class HttpServletResponseWrapperImpl extends HttpServletResponseWrapper {
return status;
}
+ @Override
+ public ServletOutputStream getOutputStream() throws IOException {
+ if (outputStream == null) {
+ outputStream = new InternalOutputStream(super.getOutputStream());
+ }
+ return outputStream;
+ }
+
+ @Override
+ public PrintWriter getWriter() throws IOException {
+ if (writer == null) {
+ writer = new InternalWriter(super.getWriter());
+ }
+ return writer;
+ }
+
+ public boolean isCompleted() {
+ return completed;
+ }
+
+ public void setCompleted(boolean completed) {
+ this.completed = completed;
+ }
+
+ public static HttpServletResponseWrapperImpl findHttpRuntimeResponse(
+ HttpServletResponse response) {
+
+ while (response instanceof HttpServletResponseWrapper) {
+ if (response instanceof HttpServletResponseWrapperImpl) {
+ return (HttpServletResponseWrapperImpl)response;
+ }
+
+ response = (HttpServletResponse)((HttpServletResponseWrapper)response).getResponse();
+ }
+
+ return null;
+ }
+
private int status = -1;
private String message;
+ private boolean completed;
+ private InternalOutputStream outputStream;
+ private InternalWriter writer;
+
+ private class InternalOutputStream extends ServletOutputStream {
+
+ public InternalOutputStream(ServletOutputStream originalOutputStream) {
+ this.originalOutputStream = originalOutputStream;
+ }
+
+ @Override
+ public boolean isReady() {
+ return originalOutputStream.isReady();
+ }
+
+ @Override
+ public void setWriteListener(WriteListener writeListener) {
+ originalOutputStream.setWriteListener(writeListener);
+ }
+
+ @Override
+ public void write(int b) throws IOException {
+ if (isCompleted()) {
+ return;
+ }
+ originalOutputStream.write(b);
+ }
+
+ private final ServletOutputStream originalOutputStream;
+
+ }
+
+ private class InternalWriter extends PrintWriter {
+
+ public InternalWriter(PrintWriter originalWriter) {
+ super(originalWriter);
+ }
+
+ @Override
+ public PrintWriter format(Locale l, String format, Object... args) {
+ if (!isCompleted()) {
+ super.format(l, format, args);
+ }
+ return this;
+ }
+
+ @Override
+ public PrintWriter format(String format, Object... args) {
+ if (!isCompleted()) {
+ super.format(format, args);
+ }
+ return this;
+ }
+
+ @Override
+ public void println() {
+ if (isCompleted()) {
+ return;
+ }
+ super.println();
+ }
+
+ @Override
+ public void write(int c) {
+ if (isCompleted()) {
+ return;
+ }
+ super.write(c);
+ }
+
+ @Override
+ public void write(char[] buf, int off, int len) {
+ if (isCompleted()) {
+ return;
+ }
+ super.write(buf, off, len);
+ }
+
+ @Override
+ public void write(char[] buf) {
+ if (isCompleted()) {
+ return;
+ }
+ super.write(buf);
+ }
+
+ @Override
+ public void write(String s, int off, int len) {
+ if (isCompleted()) {
+ return;
+ }
+ super.write(s, off, len);
+ }
+
+ @Override
+ public void write(String s) {
+ if (isCompleted()) {
+ return;
+ }
+ super.write(s);
+ }
+
+ }
} \ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/RequestDispatcherAdaptor.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/RequestDispatcherAdaptor.java
index 093c8ba8..c3791adf 100644
--- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/RequestDispatcherAdaptor.java
+++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/RequestDispatcherAdaptor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2015 Cognos Incorporated, IBM Corporation and others.
+ * Copyright (c) 2005, 2016 Cognos Incorporated, IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -37,8 +37,6 @@ public class RequestDispatcherAdaptor implements RequestDispatcher {
public void forward(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
- response.resetBuffer();
-
dispatchTargets.doDispatch(
(HttpServletRequest)request, (HttpServletResponse)response,
path, DispatcherType.FORWARD);
diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/ResponseStateHandler.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/ResponseStateHandler.java
index 7b3b4761..fad2c498 100644
--- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/ResponseStateHandler.java
+++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/ResponseStateHandler.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2014, 2015 Raymond Augé and others.
+ * Copyright (c) 2014, 2016 Raymond Augé and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -12,6 +12,7 @@
package org.eclipse.equinox.http.servlet.internal.servlet;
import java.io.IOException;
+import java.io.PrintWriter;
import java.util.Collections;
import java.util.List;
import javax.servlet.*;
@@ -50,6 +51,13 @@ public class ResponseStateHandler {
ServletRequestEvent servletRequestEvent = null;
try {
+ if (dispatcherType == DispatcherType.FORWARD) {
+ if (response.isCommitted()) {
+ throw new IllegalStateException("Response is committed"); //$NON-NLS-1$
+ }
+
+ response.resetBuffer();
+ }
if ((dispatcherType == DispatcherType.REQUEST) && !servletRequestListeners.isEmpty()) {
servletRequestEvent = new ServletRequestEvent(endpoint.getServletContext(), request);
@@ -93,6 +101,37 @@ public class ResponseStateHandler {
filterRegistration.removeReference();
}
+ if (dispatcherType == DispatcherType.FORWARD) {
+ response.flushBuffer();
+
+ HttpServletResponseWrapperImpl responseWrapper = HttpServletResponseWrapperImpl.findHttpRuntimeResponse(response);
+
+ if (responseWrapper != null) {
+ responseWrapper.setCompleted(true);
+ }
+ else {
+ try {
+ PrintWriter writer = response.getWriter();
+ writer.close();
+ }
+ catch (IllegalStateException ise1) {
+ try {
+ ServletOutputStream outputStream = response.getOutputStream();
+ outputStream.close();
+ }
+ catch (IllegalStateException ise2) {
+ // ignore
+ }
+ catch (IOException ioe) {
+ // ignore
+ }
+ }
+ catch (IOException ioe) {
+ // ignore
+ }
+ }
+ }
+
if (dispatcherType == DispatcherType.REQUEST) {
handleErrors();
@@ -125,28 +164,13 @@ public class ResponseStateHandler {
throw new IllegalStateException("Response isn't a wrapper"); //$NON-NLS-1$
}
- HttpServletResponseWrapper wrapper = (HttpServletResponseWrapper)response;
-
- HttpServletResponseWrapperImpl wrapperImpl = null;
-
- while (true) {
- if (wrapper instanceof HttpServletResponseWrapperImpl) {
- wrapperImpl = (HttpServletResponseWrapperImpl)wrapper;
- }
- else if (wrapper.getResponse() instanceof HttpServletResponseWrapper) {
- wrapper = (HttpServletResponseWrapper)wrapper.getResponse();
-
- continue;
- }
-
- break;
- }
+ HttpServletResponseWrapperImpl responseWrapper = HttpServletResponseWrapperImpl.findHttpRuntimeResponse(response);
- if (wrapperImpl == null) {
+ if (responseWrapper == null) {
throw new IllegalStateException("Can't locate response impl"); //$NON-NLS-1$
}
- HttpServletResponse wrappedResponse = (HttpServletResponse)wrapperImpl.getResponse();
+ HttpServletResponse wrappedResponse = (HttpServletResponse)responseWrapper.getResponse();
if (wrappedResponse.isCommitted()) {
throwException(exception);
@@ -175,11 +199,11 @@ public class ResponseStateHandler {
RequestDispatcher.ERROR_STATUS_CODE,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
- HttpServletResponseWrapper wrapperResponse =
- new HttpServletResponseWrapperImpl(wrappedResponse);
+ responseWrapper.setCompleted(false);
+ //responseWrapper = new HttpServletResponseWrapperImpl(wrappedResponse);
ResponseStateHandler responseStateHandler = new ResponseStateHandler(
- request, wrapperResponse, errorDispatchTargets, DispatcherType.ERROR);
+ request, responseWrapper, errorDispatchTargets, DispatcherType.ERROR);
responseStateHandler.processRequest();
@@ -191,42 +215,28 @@ public class ResponseStateHandler {
throw new IllegalStateException("Response isn't a wrapper"); //$NON-NLS-1$
}
- HttpServletResponseWrapper wrapper = (HttpServletResponseWrapper)response;
+ HttpServletResponseWrapperImpl responseWrapper = HttpServletResponseWrapperImpl.findHttpRuntimeResponse(response);
- int status = wrapper.getStatus();
-
- if (status < HttpServletResponse.SC_BAD_REQUEST) {
- return;
+ if (responseWrapper == null) {
+ throw new IllegalStateException("Can't locate response impl"); //$NON-NLS-1$
}
- HttpServletResponseWrapperImpl wrapperImpl = null;
-
- while (true) {
- if (wrapper instanceof HttpServletResponseWrapperImpl) {
- wrapperImpl = (HttpServletResponseWrapperImpl)wrapper;
- }
- else if (wrapper.getResponse() instanceof HttpServletResponseWrapper) {
- wrapper = (HttpServletResponseWrapper)wrapper.getResponse();
-
- continue;
- }
-
- break;
- }
+ int status = responseWrapper.getStatus();
- if (wrapperImpl == null) {
- throw new IllegalStateException("Can't locate response impl"); //$NON-NLS-1$
+ if (status < HttpServletResponse.SC_BAD_REQUEST) {
+ return;
}
- HttpServletResponse wrappedResponse = (HttpServletResponse)wrapperImpl.getResponse();
-
if (status == -1) {
// There's nothing more we can do here.
return;
}
+
+ HttpServletResponse wrappedResponse = (HttpServletResponse)responseWrapper.getResponse();
+
if (wrappedResponse.isCommitted()) {
// the response is committed already, but we need to propagate the error code anyway
- wrappedResponse.sendError(status, wrapperImpl.getMessage());
+ wrappedResponse.sendError(status, responseWrapper.getMessage());
// There's nothing more we can do here.
return;
}
@@ -237,13 +247,13 @@ public class ResponseStateHandler {
String.valueOf(status), null, null, null, null, null, Match.EXACT, null);
if (errorDispatchTargets == null) {
- wrappedResponse.sendError(status, wrapperImpl.getMessage());
+ wrappedResponse.sendError(status, responseWrapper.getMessage());
return;
}
request.setAttribute(
- RequestDispatcher.ERROR_MESSAGE, wrapperImpl.getMessage());
+ RequestDispatcher.ERROR_MESSAGE, responseWrapper.getMessage());
request.setAttribute(
RequestDispatcher.ERROR_REQUEST_URI, request.getRequestURI());
request.setAttribute(
@@ -251,11 +261,11 @@ public class ResponseStateHandler {
errorDispatchTargets.getServletRegistration().getName());
request.setAttribute(RequestDispatcher.ERROR_STATUS_CODE, status);
- HttpServletResponseWrapper wrapperResponse =
- new HttpServletResponseWrapperImpl(wrappedResponse);
+ responseWrapper.setCompleted(false);
+ //responseWrapper = new HttpServletResponseWrapperImpl(wrappedResponse);
ResponseStateHandler responseStateHandler = new ResponseStateHandler(
- request, wrapperResponse, errorDispatchTargets, DispatcherType.ERROR);
+ request, responseWrapper, errorDispatchTargets, DispatcherType.ERROR);
wrappedResponse.setStatus(status);

Back to the top