Initial Contribution
Signed-off-by: Vinay Vishal <vinay.vishal@oracle.com>
diff --git a/appserver/tests/appserv-tests/devtests/web/servlet-3.1/nonBlockingInputOutput/WebTest.java b/appserver/tests/appserv-tests/devtests/web/servlet-3.1/nonBlockingInputOutput/WebTest.java
new file mode 100644
index 0000000..f36a7ba
--- /dev/null
+++ b/appserver/tests/appserv-tests/devtests/web/servlet-3.1/nonBlockingInputOutput/WebTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+import java.io.*;
+import java.net.*;
+import java.util.List;
+import java.util.Map;
+import com.sun.ejte.ccl.reporter.*;
+
+/*
+ * Unit test for Non blocking Input and then non blocking Output
+ */
+public class WebTest {
+
+ private static String TEST_NAME = "servlet-3.1-non-blocking-Input-Output";
+ private static String EXPECTED_RESPONSE = "HelloWorld";
+
+ private static SimpleReporterAdapter stat
+ = new SimpleReporterAdapter("appserv-tests");
+
+ public static void main(String[] args) {
+ String host = args[0];
+ int port = Integer.parseInt(args[1]);
+ String contextRoot = args[2];
+ stat.addDescription("Unit test for non blocking read and then non blocking write");
+
+ try {
+ URL url = new URL("http://" + host + ":" + port + "/" + contextRoot + "/test?testname=abc&data=1");
+ HttpURLConnection conn = (HttpURLConnection)url.openConnection();
+ conn.setRequestMethod("POST");
+ conn.setRequestProperty("Content-type", "text/plain; charset=utf-8");
+ conn.setChunkedStreamingMode(5);
+ conn.setDoOutput(true);
+ conn.connect();
+
+ BufferedReader input = null;
+ BufferedWriter output = null;
+ boolean expected = false;
+ try {
+ output = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream()));
+ try {
+ String data = "Hello";
+ output.write(data);
+ output.flush();
+ int sleepInSeconds = 3;
+ System.out.format("Sleeping %d sec\n", sleepInSeconds);
+ Thread.sleep(sleepInSeconds * 1000);
+ data = "World";
+ output.write(data);
+ output.flush();
+ output.close();
+ } catch(Exception ex) {
+ ex.printStackTrace();
+ }
+ input = new BufferedReader(new InputStreamReader(conn.getInputStream()));
+ String line = null;
+ while ((line = input.readLine()) != null) {
+ System.out.println(line);
+ int slashInd = line.indexOf("/", 1);
+ expected = line.replace("/", "").equals(EXPECTED_RESPONSE);
+ if (expected) {
+ break;
+ }
+ }
+ } finally {
+ try {
+ if (input != null) {
+ input.close();
+ }
+ } catch(Exception ex) {
+ }
+
+ try {
+ if (output != null) {
+ output.close();
+ }
+ } catch(Exception ex) {
+ }
+ }
+
+ stat.addStatus(TEST_NAME, ((expected) ? stat.PASS : stat.FAIL));
+ } catch(Exception ex) {
+ ex.printStackTrace();
+ stat.addStatus(TEST_NAME, stat.FAIL);
+ }
+
+ stat.printSummary();
+ }
+}
diff --git a/appserver/tests/appserv-tests/devtests/web/servlet-3.1/nonBlockingInputOutput/build.properties b/appserver/tests/appserv-tests/devtests/web/servlet-3.1/nonBlockingInputOutput/build.properties
new file mode 100644
index 0000000..1a41e29
--- /dev/null
+++ b/appserver/tests/appserv-tests/devtests/web/servlet-3.1/nonBlockingInputOutput/build.properties
@@ -0,0 +1,23 @@
+<!--
+
+ Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+
+<property name="module" value="web"/>
+<property name="appname" value="${module}-servlet-3.1-non-blocking-input"/>
+<property name="assemble" value="${build.classes.dir}/archive"/>
+<property name="contextroot" value="/${appname}"/>
diff --git a/appserver/tests/appserv-tests/devtests/web/servlet-3.1/nonBlockingInputOutput/build.xml b/appserver/tests/appserv-tests/devtests/web/servlet-3.1/nonBlockingInputOutput/build.xml
new file mode 100644
index 0000000..997beda
--- /dev/null
+++ b/appserver/tests/appserv-tests/devtests/web/servlet-3.1/nonBlockingInputOutput/build.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+
+ Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<!DOCTYPE project [
+<!ENTITY commonSetup SYSTEM "./../../../../config/properties.xml">
+<!ENTITY commonBuild SYSTEM "./../../../../config/common.xml">
+<!ENTITY run SYSTEM "./../../../../config/run.xml">
+<!ENTITY testproperties SYSTEM "./build.properties">
+]>
+
+<project name="webcontainer_unittest" default="all" basedir=".">
+
+ &commonSetup;
+ &commonBuild;
+ &testproperties;
+ &run;
+
+ <target name="all" depends="build,deploy,run,undeploy"/>
+
+ <target name="clean" depends="init-common">
+ <antcall target="clean-common"/>
+ <delete>
+ <fileset dir="." includes="*.class"/>
+ </delete>
+ </target>
+
+ <target name="compile" depends="clean">
+ <antcall target="compile-common">
+ <param name="src" value="servlet"/>
+ </antcall>
+ </target>
+
+ <target name="build" depends="compile">
+ <antcall target="webclient-war-common">
+ <param name="hasWebclient" value="yes"/>
+ </antcall>
+
+ <javac srcdir="." classpath="${env.APS_HOME}/lib/reportbuilder.jar"
+ includes="WebTest.java">
+ <classpath>
+ <pathelement location="${env.APS_HOME}/lib/reportbuilder.jar"/>
+ </classpath>
+ </javac>
+ </target>
+
+ <target name="deploy" depends="init-common">
+ <antcall target="deploy-war-common"/>
+ </target>
+
+ <target name="run" depends="init-common">
+ <java classname="WebTest">
+ <sysproperty key="debug" value="true"/>
+ <arg value="${http.host}"/>
+ <arg value="${http.port}"/>
+ <arg value="${contextroot}"/>
+ <classpath>
+ <pathelement location="${env.APS_HOME}/lib/reportbuilder.jar"/>
+ <pathelement location="."/>
+ </classpath>
+ </java>
+ </target>
+
+ <target name="undeploy" depends="init-common">
+ <antcall target="undeploy-war-common"/>
+ </target>
+
+ <target name="usage">
+ <antcall target="usage-common"/>
+ </target>
+
+</project>
diff --git a/appserver/tests/appserv-tests/devtests/web/servlet-3.1/nonBlockingInputOutput/servlet/test/TestServlet.java b/appserver/tests/appserv-tests/devtests/web/servlet-3.1/nonBlockingInputOutput/servlet/test/TestServlet.java
new file mode 100644
index 0000000..f7be1b7
--- /dev/null
+++ b/appserver/tests/appserv-tests/devtests/web/servlet-3.1/nonBlockingInputOutput/servlet/test/TestServlet.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package test;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Queue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import javax.servlet.AsyncContext;
+import javax.servlet.AsyncEvent;
+import javax.servlet.AsyncListener;
+import javax.servlet.ReadListener;
+import javax.servlet.ServletException;
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.WriteListener;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@WebServlet(urlPatterns="/test", asyncSupported=true)
+public class TestServlet extends HttpServlet {
+
+ @Override
+ protected void doPost(HttpServletRequest req, HttpServletResponse res)
+ throws IOException, ServletException {
+
+ AsyncContext ac = req.startAsync();
+ ac.addListener(new AsyncListener() {
+ public void onComplete(AsyncEvent event) throws IOException {
+ System.out.println("my asyncListener.onComplete");
+ }
+ public void onError(AsyncEvent event) {
+ System.out.println("my asyncListener.onError: " + event.getThrowable());
+ }
+ public void onStartAsync(AsyncEvent event) {
+ System.out.println("my asyncListener.onStartAsync");
+ }
+ public void onTimeout(AsyncEvent event) {
+ System.out.println("my asyncListener.onTimeout");
+ }
+ });
+
+ ServletInputStream input = req.getInputStream();
+ // read all data first
+ ReadListener readListener = new ReadListenerImpl(input, res, ac);
+ input.setReadListener(readListener);
+ }
+
+ static class ReadListenerImpl implements ReadListener {
+ private ServletInputStream input = null;
+ private HttpServletResponse res = null;
+ private AsyncContext ac = null;
+ private Queue<String> queue = new LinkedBlockingQueue<String>();
+
+ ReadListenerImpl(ServletInputStream in, HttpServletResponse r,
+ AsyncContext c) {
+ input = in;
+ res = r;
+ ac = c;
+ }
+
+ public void onDataAvailable() throws IOException {
+ StringBuilder sb = new StringBuilder();
+ System.out.println("--> onDataAvailable");
+ int len = -1;
+ byte b[] = new byte[1024];
+ while (input.isReady()
+ && (len = input.read(b)) != -1) {
+ String data = new String(b, 0, len);
+ System.out.println("--> " + data);
+ sb.append(data);
+ }
+ queue.add(sb.toString());
+ }
+
+ public void onAllDataRead() throws IOException {
+ System.out.println("--> onAllDataRead");
+ // now all data are read, write the result
+ ServletOutputStream output = res.getOutputStream();
+ WriteListener writeListener = new WriteListenerImpl(output, queue, ac);
+ output.setWriteListener(writeListener);
+ }
+
+ public void onError(final Throwable t) {
+ ac.complete();
+ t.printStackTrace();
+ }
+ }
+
+ static class WriteListenerImpl implements WriteListener {
+ private ServletOutputStream output = null;
+ private Queue<String> queue = null;
+ private AsyncContext ac = null;
+
+ WriteListenerImpl(ServletOutputStream sos, Queue<String> q,
+ AsyncContext c) {
+ output = sos;
+ queue = q;
+ ac = c;
+ }
+
+ public void onWritePossible() throws IOException {
+ System.out.println("--> onWritePossible");
+ System.out.println("--> queue: " + queue);
+ while (queue.peek() != null && output.isReady()) {
+ String data = queue.poll();
+ System.out.println("--> data = " + data);
+ output.print(data);
+ }
+ System.out.println("--> ac.complete");
+ if (queue.peek() == null) {
+ ac.complete();
+ }
+ }
+
+ public void onError(final Throwable t) {
+ ac.complete();
+ t.printStackTrace();
+ }
+ }
+}