diff options
author | Peter Nehrer | 2017-04-27 17:35:44 +0000 |
---|---|---|
committer | Raymond Auge | 2018-01-22 15:55:42 +0000 |
commit | 4e6efcf250b2ce6dbde81d8c5f4c46382bbf086f (patch) | |
tree | ca4844d62abd75199100d58d6e527731423a92e3 | |
parent | 0537d998171c333d7450eaf0df7a5d2b999a328a (diff) | |
download | rt.equinox.bundles-4e6efcf250b2ce6dbde81d8c5f4c46382bbf086f.tar.gz rt.equinox.bundles-4e6efcf250b2ce6dbde81d8c5f4c46382bbf086f.tar.xz rt.equinox.bundles-4e6efcf250b2ce6dbde81d8c5f4c46382bbf086f.zip |
Bug 515912 - IllegalStateException when using WriteListener
- delegate all write() calls to original output stream
Change-Id: Ia630af93bc1e8e3a97bc4a876c8407516ba6d32f
Signed-off-by: Peter Nehrer <pnehrer@eclipticalsoftware.com>
3 files changed, 133 insertions, 1 deletions
diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/ServletTest.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/ServletTest.java index fd226000b..2a422b046 100644 --- a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/ServletTest.java +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/ServletTest.java @@ -9,6 +9,7 @@ * IBM Corporation - initial API and implementation * Raymond Augé - bug fixes and enhancements * Juan Gonzalez <juan.gonzalez@liferay.com> - Bug 486412 + * Peter Nehrer <pnehrer@eclipticalsoftware.com> - Bug 515912 *******************************************************************************/ package org.eclipse.equinox.http.servlet.tests; @@ -21,7 +22,6 @@ import java.io.PrintWriter; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; - import java.net.CookieHandler; import java.net.CookieManager; import java.net.CookiePolicy; @@ -79,6 +79,7 @@ import org.eclipse.equinox.http.servlet.ExtendedHttpService; import org.eclipse.equinox.http.servlet.context.ContextPathCustomizer; import org.eclipse.equinox.http.servlet.session.HttpSessionInvalidator; import org.eclipse.equinox.http.servlet.testbase.BaseTest; +import org.eclipse.equinox.http.servlet.tests.util.AsyncOutputServlet; import org.eclipse.equinox.http.servlet.tests.util.BaseAsyncServlet; import org.eclipse.equinox.http.servlet.tests.util.BaseChangeSessionIdServlet; import org.eclipse.equinox.http.servlet.tests.util.BaseHttpContext; @@ -3550,6 +3551,7 @@ public class ServletTest extends BaseTest { Assert.assertEquals(0, listenerBalance.get()); } + @Test public void test_Async1() throws Exception { Servlet s1 = new BaseAsyncServlet("test_Listener8"); @@ -3573,6 +3575,31 @@ public class ServletTest extends BaseTest { } @Test + public void test_AsyncOutput1() throws Exception { + Servlet s1 = new AsyncOutputServlet(); + Collection<ServiceRegistration<?>> registrations = new ArrayList<ServiceRegistration<?>>(); + try { + Dictionary<String, Object> servletProps1 = new Hashtable<String, Object>(); + servletProps1.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, "AsyncOutputServlet"); + servletProps1.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/asyncOutput"); + servletProps1.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_ASYNC_SUPPORTED, true); + registrations.add(getBundleContext().registerService(Servlet.class, s1, servletProps1)); + + String output1 = requestAdvisor.request("asyncOutput"); + + Assert.assertTrue("write(int)", output1.startsWith("0123456789")); + + String output2 = requestAdvisor.request("asyncOutput?bytes=true"); + + Assert.assertTrue("write(byte[], int, int)", output2.startsWith("0123456789")); + } finally { + for (ServiceRegistration<?> registration : registrations) { + registration.unregister(); + } + } + } + + @Test public void test_WBServlet1() throws Exception { String expected = "a"; String actual; diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/util/AsyncOutputServlet.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/util/AsyncOutputServlet.java new file mode 100644 index 000000000..7f1d71a98 --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/util/AsyncOutputServlet.java @@ -0,0 +1,89 @@ +/******************************************************************************* + * Copyright (c) 2017 Ecliptical Software Inc. 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ecliptical Software Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.http.servlet.tests.util; + +import java.io.IOException; + +import javax.servlet.AsyncContext; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.WriteListener; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +public class AsyncOutputServlet extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + resp.setStatus(HttpServletResponse.SC_OK); + resp.setContentType("text/plain"); + resp.setBufferSize(16); + resp.flushBuffer(); + AsyncContext async = req.startAsync(req, resp); + ServletOutputStream out = resp.getOutputStream(); + out.setWriteListener(new AsyncWriter(async, Boolean.parseBoolean(req.getParameter("bytes")))); + } + + private class AsyncWriter implements WriteListener { + + private final AsyncContext async; + + private final boolean writeBytes; + + private boolean eof; + + public AsyncWriter(AsyncContext async, boolean writeBytes) { + this.async = async; + this.writeBytes = writeBytes; + } + + @Override + public void onWritePossible() throws IOException { + HttpServletResponse resp = (HttpServletResponse) async.getResponse(); + ServletOutputStream out = resp.getOutputStream(); + if (eof) { + out.close(); + async.complete(); + return; + } + + if (writeBytes) { + byte[] buf = new byte[10]; + for (int i = 0; i < buf.length; ++i) { + buf[i] = (byte) ('0' + i); + } + + do { + out.write(buf); + } while (out.isReady()); + } else { + int i = -1; + do { + out.write('0' + (++i % 10)); + } while (out.isReady()); + } + + eof = true; + } + + @Override + public void onError(Throwable t) { + try { + async.complete(); + } finally { + getServletContext().log("Error writing response.", t); + } + } + } +} 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 a7c5f5f17..db9841e29 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 @@ -126,6 +126,22 @@ public class HttpServletResponseWrapperImpl extends HttpServletResponseWrapper { originalOutputStream.write(b); } + @Override + public void write(byte[] b) throws IOException { + if (isCompleted()) { + return; + } + originalOutputStream.write(b); + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + if (isCompleted()) { + return; + } + originalOutputStream.write(b, off, len); + } + private final ServletOutputStream originalOutputStream; } |