Author: jochen
Date: Wed Oct 11 18:03:54 2006
New Revision: 463093
URL: http://svn.apache.org/viewvc?view=rev&rev=463093
Log:
Rework of the WebServer/ThreadPool framework, in order to overcome an
unreliable Shutdown, as detected by Stanislav Miklik.
Added:
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/ShutdownTest.java
Modified:
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/util/ThreadPool.java
webservices/xmlrpc/trunk/pom.xml
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/Connection.java
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/HttpServletResponseImpl.java
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/ServletConnection.java
webservices/xmlrpc/trunk/src/changes/changes.xml
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/AuthenticationTest.java
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/ClientProvider.java
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/JiraTest.java
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/LocalTransportProvider.java
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/ParserTest.java
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/ServletWebServerProvider.java
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/WebServerProvider.java
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/XmlRpcTestCase.java
Modified:
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/util/ThreadPool.java
URL:
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/util/ThreadPool.java?view=diff&rev=463093&r1=463092&r2=463093
==============================================================================
---
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/util/ThreadPool.java
(original)
+++
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/util/ThreadPool.java
Wed Oct 11 18:03:54 2006
@@ -32,63 +32,77 @@
void run() throws Throwable;
}
- private class MyThread extends Thread {
- private boolean shuttingDown;
- private int numTasks;
- private Task task;
- MyThread() {
- super(threadGroup, threadGroup.getName() + "-" + num++);
- setDaemon(true);
- }
- synchronized void shutdown() {
- shuttingDown = true;
- notify();
- }
- synchronized boolean isShuttingDown() { return shuttingDown; }
- synchronized void waitForNotification() {
- if (getTask() != null) { return; }
- try {
- wait();
- } catch (InterruptedException e) {
- }
- }
- synchronized int getNumTasks() { return numTasks; }
- synchronized Task getTask() { return task; }
- synchronized void setTask(Task pTask) {
- task = pTask;
- if (task != null) {
- notify();
- }
- }
- synchronized void runTask() {
- Task tsk = getTask();
- if (tsk == null) {
- return;
- }
- ++numTasks;
- Throwable t;
- try {
- tsk.run();
- t = null;
- } catch (Throwable th) {
- t = th;
- }
- if (t == null) {
- repool(this);
- } else {
- discard(this);
- }
- }
- public void run() {
- while (!isShuttingDown()) {
- if (getTask() == null) {
- waitForNotification();
- } else {
- runTask();
- }
- }
- }
- }
+ /** A task, which may be interrupted, if the pool is shutting down.
+ */
+ public interface InterruptableTask extends Task {
+ /** Interrupts the task.
+ * @throws Throwable Shutting down the task failed.
+ */
+ void shutdown() throws Throwable;
+ }
+
+ private class Poolable {
+ private boolean shuttingDown;
+ private Task task;
+ private Thread thread;
+ Poolable(ThreadGroup pGroup, int pNum) {
+ thread = new Thread(pGroup, pGroup.getName() + "-" + pNum){
+ public void run() {
+ while (!isShuttingDown()) {
+ final Task t = getTask();
+ if (t == null) {
+ try {
+ synchronized (this) {
+ wait();
+ }
+ } catch (InterruptedException e) {
+ // Do nothing
+ }
+ } else {
+ try {
+ t.run();
+ resetTask();
+ repool(Poolable.this);
+ } catch (Throwable e) {
+ discard(Poolable.this);
+ resetTask();
+ }
+ }
+ }
+ }
+ };
+ thread.start();
+ }
+ synchronized void shutdown() {
+ shuttingDown = true;
+ final Task t = getTask();
+ if (t != null && t instanceof InterruptableTask) {
+ try {
+ ((InterruptableTask) t).shutdown();
+ } catch (Throwable th) {
+ // Ignore me
+ }
+ }
+ task = null;
+ synchronized (thread) {
+ thread.notify();
+ }
+ }
+ private synchronized boolean isShuttingDown() { return shuttingDown; }
+ String getName() { return thread.getName(); }
+ private synchronized Task getTask() {
+ return task;
+ }
+ private synchronized void resetTask() {
+ task = null;
+ }
+ synchronized void start(Task pTask) {
+ task = pTask;
+ synchronized (thread) {
+ thread.notify();
+ }
+ }
+ }
private final ThreadGroup threadGroup;
private final int maxSize;
@@ -107,25 +121,26 @@
threadGroup = new ThreadGroup(pName);
}
- synchronized void discard(MyThread pThread) {
- pThread.shutdown();
- if (!runningThreads.remove(pThread)) {
- throw new IllegalStateException("The list of running
threads didn't contain the thread " + pThread.getName());
- }
- }
-
- synchronized void repool(MyThread pThread) {
- if (maxSize != 0 && (runningThreads.size() +
waitingThreads.size()) > maxSize) {
- discard(pThread);
- } else if (waitingTasks.size() > 0) {
- pThread.setTask((Task) waitingTasks.remove(0));
- } else {
- pThread.setTask(null);
- if (!runningThreads.remove(pThread)) {
- throw new IllegalStateException("The list of
running threads didn't contain the thread " + pThread.getName());
- }
- waitingThreads.add(pThread);
- }
+ synchronized void discard(Poolable pPoolable) {
+ pPoolable.shutdown();
+ runningThreads.remove(pPoolable);
+ waitingThreads.remove(pPoolable);
+ }
+
+ synchronized void repool(Poolable pPoolable) {
+ if (runningThreads.remove(pPoolable)) {
+ if (maxSize != 0 && runningThreads.size() +
waitingThreads.size() >= maxSize) {
+ discard(pPoolable);
+ } else {
+ waitingThreads.add(pPoolable);
+ if (waitingTasks.size() > 0) {
+ Task task = (Task) waitingTasks.remove(waitingTasks.size()
- 1);
+ startTask(task);
+ }
+ }
+ } else {
+ discard(pPoolable);
+ }
}
/** Starts a task immediately.
@@ -138,15 +153,14 @@
if (maxSize != 0 && runningThreads.size() > maxSize) {
return false;
}
- MyThread t;
+ Poolable poolable;
if (waitingThreads.size() > 0) {
- t = (MyThread)
waitingThreads.remove(waitingThreads.size()-1);
+ poolable = (Poolable)
waitingThreads.remove(waitingThreads.size()-1);
} else {
- t = new MyThread();
- t.start();
+ poolable = new Poolable(threadGroup, num++);
}
- runningThreads.add(t);
- t.setTask(pTask);
+ runningThreads.add(poolable);
+ poolable.start(pTask);
return true;
}
@@ -166,14 +180,14 @@
/** Closes the pool.
*/
public synchronized void shutdown() {
- for (int i = 0; i < waitingThreads.size(); i++) {
- MyThread t = (MyThread) waitingThreads.get(i);
- t.shutdown();
- }
- for (int i = 0; i < runningThreads.size(); i++) {
- MyThread t = (MyThread) runningThreads.get(i);
- t.shutdown();
- }
+ while (!waitingThreads.isEmpty()) {
+ Poolable poolable = (Poolable)
waitingThreads.remove(waitingThreads.size()-1);
+ poolable.shutdown();
+ }
+ while (!runningThreads.isEmpty()) {
+ Poolable poolable = (Poolable)
runningThreads.remove(runningThreads.size()-1);
+ poolable.shutdown();
+ }
}
/** Returns the maximum number of concurrent threads.
@@ -184,5 +198,5 @@
/** Returns the number of threads, which have actually been created,
* as opposed to the number of currently running threads.
*/
- public int getNumThreads() { return num; }
+ public synchronized int getNumThreads() { return num; }
}
Modified: webservices/xmlrpc/trunk/pom.xml
URL:
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/pom.xml?view=diff&rev=463093&r1=463092&r2=463093
==============================================================================
--- webservices/xmlrpc/trunk/pom.xml (original)
+++ webservices/xmlrpc/trunk/pom.xml Wed Oct 11 18:03:54 2006
@@ -236,7 +236,7 @@
<artifactId>commons-httpclient</artifactId>
<version>3.0.1</version>
<type>jar</type>
- <scope>optional</scope>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
@@ -253,7 +253,7 @@
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
- <scope>optional</scope>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
@@ -270,7 +270,7 @@
<groupId>jaxme</groupId>
<artifactId>jaxmeapi</artifactId>
<version>0.5.1</version>
- <scope>optional</scope>
+ <scope>provided</scope>
</dependency>
</dependencies>
</dependencyManagement>
Modified:
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/Connection.java
URL:
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/Connection.java?view=diff&rev=463093&r1=463092&r2=463093
==============================================================================
---
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/Connection.java
(original)
+++
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/Connection.java
Wed Oct 11 18:03:54 2006
@@ -23,6 +23,7 @@
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
+import java.net.SocketException;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;
@@ -42,7 +43,7 @@
* is able to do HTTP keepalive. In other words, it can serve
* multiple requests via a single, physical connection.
*/
-public class Connection implements ThreadPool.Task, ServerStreamConnection {
+public class Connection implements ThreadPool.InterruptableTask,
ServerStreamConnection {
private static final String US_ASCII = "US-ASCII";
private static final byte[] ctype = toHTTPBytes("Content-Type:
text/xml\r\n");
private static final byte[] clength = toHTTPBytes("Content-Length: ");
@@ -97,6 +98,8 @@
private byte[] buffer;
private Map headers;
private RequestData requestData;
+ private boolean shuttingDown;
+ private boolean firstByte;
/** Creates a new webserver connection on the given socket.
* @param pWebServer The webserver maintaining this connection.
@@ -133,6 +136,7 @@
if (headers != null) {
headers.clear();
}
+ firstByte = true;
XmlRpcHttpServerConfig serverConfig = (XmlRpcHttpServerConfig)
server.getConfig();
requestData.setBasicEncoding(serverConfig.getBasicEncoding());
requestData.setContentLengthOptional(serverConfig.isContentLengthOptional());
@@ -141,6 +145,9 @@
// reset user authentication
String line = readLine();
+ if (line == null && firstByte) {
+ return null;
+ }
// Netscape sends an extra \n\r after bodypart, swallow it
if (line != null && line.length() == 0) {
line = readLine();
@@ -210,7 +217,9 @@
/* Ignore me */
}
} catch (Throwable t) {
- webServer.log(t);
+ if (!shuttingDown) {
+ webServer.log(t);
+ }
} finally {
try { output.close(); } catch (Throwable ignore) {}
try { input.close(); } catch (Throwable ignore) {}
@@ -225,7 +234,16 @@
int next;
int count = 0;
for (;;) {
- next = input.read();
+ try {
+ next = input.read();
+ firstByte = false;
+ } catch (SocketException e) {
+ if (firstByte) {
+ return null;
+ } else {
+ throw e;
+ }
+ }
if (next < 0 || next == '\n') {
break;
}
@@ -382,5 +400,10 @@
}
public void close() throws IOException {
+ }
+
+ public void shutdown() throws Throwable {
+ shuttingDown = true;
+ socket.close();
}
}
Modified:
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/HttpServletResponseImpl.java
URL:
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/HttpServletResponseImpl.java?view=diff&rev=463093&r1=463092&r2=463093
==============================================================================
---
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/HttpServletResponseImpl.java
(original)
+++
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/HttpServletResponseImpl.java
Wed Oct 11 18:03:54 2006
@@ -412,7 +412,7 @@
}
}
- String getHttpHeaders(Integer pContentLength) throws IOException {
+ String getHttpHeaders(Integer pContentLength) {
StringBuffer sb = new StringBuffer();
sb.append("HTTP/1.0 ");
sb.append(status);
Modified:
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/ServletConnection.java
URL:
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/ServletConnection.java?view=diff&rev=463093&r1=463092&r2=463093
==============================================================================
---
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/ServletConnection.java
(original)
+++
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/ServletConnection.java
Wed Oct 11 18:03:54 2006
@@ -22,18 +22,19 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.apache.xmlrpc.util.ThreadPool.Task;
+import org.apache.xmlrpc.util.ThreadPool.InterruptableTask;
/** [EMAIL PROTECTED] org.apache.xmlrpc.webserver.ServletWebServer
ServletWebServer's}
* [EMAIL PROTECTED] org.apache.xmlrpc.util.ThreadPool.Task} for handling a
single
* servlet connection.
*/
-public class ServletConnection implements Task {
+public class ServletConnection implements InterruptableTask {
private final HttpServlet servlet;
private final Socket socket;
private final HttpServletRequest request;
private final HttpServletResponse response;
+ private boolean shuttingDown;
/** Creates a new instance.
* @param pServlet The servlet, which ought to handle the request.
@@ -48,6 +49,17 @@
}
public void run() throws Throwable {
- servlet.service(request, response);
+ try {
+ servlet.service(request, response);
+ } catch (Throwable t) {
+ if (!shuttingDown) {
+ throw t;
+ }
+ }
}
+
+ public void shutdown() throws Throwable {
+ shuttingDown = true;
+ socket.close();
+ }
}
Modified: webservices/xmlrpc/trunk/src/changes/changes.xml
URL:
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/src/changes/changes.xml?view=diff&rev=463093&r1=463092&r2=463093
==============================================================================
--- webservices/xmlrpc/trunk/src/changes/changes.xml (original)
+++ webservices/xmlrpc/trunk/src/changes/changes.xml Wed Oct 11 18:03:54 2006
@@ -24,6 +24,10 @@
Atomic properties of XmlRpcServer are now configurable as init
parameters
in the XmlRpcServlet.
</action>
+ <action dev="jochen" type="fix">
+ Reworked the WebServer/ThreadPool framework in order to ensure a clean
+ shutdown.
+ </action>
</release>
<release version="3.0.1-SNAPSHOT" date="Not yet released">
<action dev="jochen" type="fix">
Modified:
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/AuthenticationTest.java
URL:
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/AuthenticationTest.java?view=diff&rev=463093&r1=463092&r2=463093
==============================================================================
---
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/AuthenticationTest.java
(original)
+++
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/AuthenticationTest.java
Wed Oct 11 18:03:54 2006
@@ -17,6 +17,9 @@
import java.io.IOException;
+import javax.servlet.ServletException;
+
+import org.apache.log4j.BasicConfigurator;
import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.XmlRpcRequest;
import org.apache.xmlrpc.XmlRpcRequestConfig;
Modified:
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/ClientProvider.java
URL:
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/ClientProvider.java?view=diff&rev=463093&r1=463092&r2=463093
==============================================================================
---
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/ClientProvider.java
(original)
+++
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/ClientProvider.java
Wed Oct 11 18:03:54 2006
@@ -39,4 +39,8 @@
* @return A server instance, which is being used for performing the test.
*/
XmlRpcServer getServer();
+
+ /** Performs a shutdown of the server.
+ */
+ void shutdown();
}
Modified:
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/JiraTest.java
URL:
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/JiraTest.java?view=diff&rev=463093&r1=463092&r2=463093
==============================================================================
---
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/JiraTest.java
(original)
+++
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/JiraTest.java
Wed Oct 11 18:03:54 2006
@@ -20,6 +20,7 @@
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
+import java.lang.reflect.UndeclaredThrowableException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Collections;
@@ -30,6 +31,7 @@
import java.util.Vector;
import org.apache.xmlrpc.XmlRpcException;
+import org.apache.xmlrpc.client.TimingOutCallback;
import org.apache.xmlrpc.client.XmlRpcClient;
import org.apache.xmlrpc.client.XmlRpcHttpClientConfig;
import org.apache.xmlrpc.client.util.ClientFactory;
@@ -229,6 +231,16 @@
}
/**
+ * Test case for <a href="http://issues.apache.org/jira/browse/XMLRPC-112">
+ * XMLRPC-112</a>
+ */
+ public void testXMLRPC112() throws Exception {
+ for (int i = 0; i < providers.length; i++) {
+ testXMLRPC112(providers[i]);
+ }
+ }
+
+ /**
* Test case for <a href="http://issues.apache.org/jira/browse/XMLRPC-113">
* XMLRPC-113</a>
*/
@@ -236,6 +248,34 @@
for (int i = 0; i < providers.length; i++) {
testXMLRPC113(providers[i]);
}
+ }
+
+
+ private void testXMLRPC112(ClientProvider pProvider) throws Exception {
+ XmlRpcClient client = pProvider.getClient();
+ client.setConfig(getConfig(pProvider));
+ TimingOutCallback toc = new TimingOutCallback(5000);
+ final String methodName = XMLRPC89Handler.class.getName() + ".reverse";
+ client.executeAsync(methodName, new Object[]{new Object[]{"1", "2",
"3"}}, toc);
+ Object o;
+ try {
+ o = toc.waitForResponse();
+ } catch (Exception e) {
+ throw e;
+ } catch (Throwable t) {
+ throw new UndeclaredThrowableException(t);
+ }
+ checkXMLRPC112Result(o);
+ checkXMLRPC112Result(client.execute(methodName, new Object[]{new
Object[]{"1", "2", "3"}}));
+ checkXMLRPC112Result(client.execute(methodName, new Object[]{new
Object[]{"1", "2", "3"}}));
+ }
+
+ private void checkXMLRPC112Result(Object pObject) {
+ Object[] args = (Object[]) pObject;
+ assertEquals(3, args.length);
+ assertEquals("3", args[0]);
+ assertEquals("2", args[1]);
+ assertEquals("1", args[2]);
}
/**
Modified:
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/LocalTransportProvider.java
URL:
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/LocalTransportProvider.java?view=diff&rev=463093&r1=463092&r2=463093
==============================================================================
---
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/LocalTransportProvider.java
(original)
+++
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/LocalTransportProvider.java
Wed Oct 11 18:03:54 2006
@@ -51,4 +51,8 @@
public XmlRpcServer getServer() {
return server;
}
+
+ public void shutdown() {
+ // Does nothing
+ }
}
Modified:
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/ParserTest.java
URL:
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/ParserTest.java?view=diff&rev=463093&r1=463092&r2=463093
==============================================================================
---
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/ParserTest.java
(original)
+++
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/ParserTest.java
Wed Oct 11 18:03:54 2006
@@ -1,7 +1,9 @@
package org.apache.xmlrpc.test;
+import java.io.File;
import java.io.IOException;
import java.io.StringReader;
+import java.util.Map;
import junit.framework.TestCase;
@@ -23,15 +25,24 @@
*/
public class ParserTest extends TestCase {
private Object parseResponse(final String s) throws XmlRpcException,
IOException, SAXException {
- XmlRpcStreamRequestConfig config = new XmlRpcClientConfigImpl();
+ return parseResponse(new InputSource(new StringReader(s)));
+ }
+
+ private Object parseResponse(final File f) throws XmlRpcException,
IOException, SAXException {
+ return parseResponse(new
InputSource(f.toURI().toURL().toExternalForm()));
+ }
+
+ private Object parseResponse(InputSource isource) throws XmlRpcException,
+ IOException, SAXException {
+ XmlRpcStreamRequestConfig config = new XmlRpcClientConfigImpl();
XmlRpcClient client = new XmlRpcClient();
XmlRpcResponseParser parser = new XmlRpcResponseParser(config,
client.getTypeFactory());
XMLReader xr = SAXParsers.newXMLReader();
xr.setContentHandler(parser);
- xr.parse(new InputSource(new StringReader(s)));
+ xr.parse(isource);
Object o = parser.getResult();
return o;
- }
+ }
private XmlRpcRequestParser parseRequest(final String s) throws
XmlRpcException, IOException, SAXException {
XmlRpcStreamConfig config = new XmlRpcHttpRequestConfigImpl();
Modified:
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/ServletWebServerProvider.java
URL:
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/ServletWebServerProvider.java?view=diff&rev=463093&r1=463092&r2=463093
==============================================================================
---
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/ServletWebServerProvider.java
(original)
+++
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/ServletWebServerProvider.java
Wed Oct 11 18:03:54 2006
@@ -77,4 +77,8 @@
public XmlRpcServer getServer() {
return servlet.getXmlRpcServletServer();
}
+
+ public void shutdown() {
+ webServer.shutdown();
+ }
}
Added:
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/ShutdownTest.java
URL:
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/ShutdownTest.java?view=auto&rev=463093
==============================================================================
---
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/ShutdownTest.java
(added)
+++
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/ShutdownTest.java
Wed Oct 11 18:03:54 2006
@@ -0,0 +1,104 @@
+package org.apache.xmlrpc.test;
+
+import java.net.ConnectException;
+import java.net.URL;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import org.apache.xmlrpc.XmlRpcException;
+import org.apache.xmlrpc.client.XmlRpcClient;
+import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
+import org.apache.xmlrpc.server.PropertyHandlerMapping;
+import org.apache.xmlrpc.server.XmlRpcServerConfigImpl;
+import org.apache.xmlrpc.webserver.WebServer;
+
+
+/**
+ * Tests the web servers shutdown method.
+ */
+public class ShutdownTest extends TestCase {
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
+ try {
+ new ShutdownTest().testShutdown();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Dummy handler for running the test.
+ */
+ public static class Adder {
+ /** Returns the sum of p1 and p2.
+ */
+ public int add(int p1, int p2) {
+ return p1 + p2;
+ }
+ }
+
+ private WebServer setupServer() throws Exception {
+ WebServer server = new WebServer(0);
+ PropertyHandlerMapping mapping = new PropertyHandlerMapping();
+ mapping.addHandler("Adder", Adder.class);
+ server.getXmlRpcServer().setHandlerMapping(mapping);
+ XmlRpcServerConfigImpl config = new XmlRpcServerConfigImpl();
+ config.setEnabledForExtensions(true);
+ config.setKeepAliveEnabled(true);
+ server.getXmlRpcServer().setConfig(config);
+ server.start();
+ return server;
+ }
+
+ private class Runner extends Thread {
+ private boolean connectExceptionSeen;
+ private boolean successSeen;
+ private final int port;
+ Runner(int pPort) {
+ port = pPort;
+ }
+ public void run() {
+ for (int i = 0; i < 10; i++) {
+ try {
+ XmlRpcClient client = new XmlRpcClient();
+ XmlRpcClientConfigImpl config = new
XmlRpcClientConfigImpl();
+ config.setServerURL(new URL("http://127.0.0.1:" + port +
"/"));
+ client.setConfig(config);
+ Object[] params = new Object[] {
+ new Integer(3), new Integer(5)
+ };
+ Integer result = (Integer) client.execute("Adder.add",
params);
+ assertEquals(8, result.intValue());
+ successSeen = true;
+ Thread.sleep(200);
+ } catch (XmlRpcException e) {
+ Assert.assertTrue(e.getCause() != null && e.getCause()
instanceof ConnectException);
+ connectExceptionSeen = true;
+ break;
+ } catch (Exception e) {
+ e.printStackTrace();
+ break;
+ }
+ }
+ }
+ boolean isConnectExceptionSeen() { return connectExceptionSeen; }
+ boolean isSuccessSeen() { return successSeen; }
+ }
+
+ /** Tests the web servers shutdown method.
+ */
+ public void testShutdown() throws Exception {
+ final WebServer server = setupServer();
+ final int port = server.getPort();
+ Runner runner = new Runner(port);
+ runner.start();
+ Thread.sleep(700);
+ server.shutdown();
+ runner.join();
+ assertTrue(runner.isSuccessSeen());
+ assertTrue(runner.isConnectExceptionSeen());
+ }
+}
Modified:
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/WebServerProvider.java
URL:
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/WebServerProvider.java?view=diff&rev=463093&r1=463092&r2=463093
==============================================================================
---
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/WebServerProvider.java
(original)
+++
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/WebServerProvider.java
Wed Oct 11 18:03:54 2006
@@ -67,4 +67,8 @@
public XmlRpcServer getServer() {
return webServer.getXmlRpcServer();
}
+
+ public void shutdown() {
+ webServer.shutdown();
+ }
}
Modified:
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/XmlRpcTestCase.java
URL:
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/XmlRpcTestCase.java?view=diff&rev=463093&r1=463092&r2=463093
==============================================================================
---
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/XmlRpcTestCase.java
(original)
+++
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/XmlRpcTestCase.java
Wed Oct 11 18:03:54 2006
@@ -64,7 +64,7 @@
return mapping;
}
- protected final ClientProvider[] initProviders(XmlRpcHandlerMapping
pMapping) throws ServletException, IOException {
+ protected ClientProvider[] initProviders(XmlRpcHandlerMapping pMapping)
throws ServletException, IOException {
return new ClientProvider[]{
new LocalTransportProvider(pMapping),
new LocalStreamTransportProvider(pMapping),
@@ -81,6 +81,14 @@
public void setUp() throws Exception {
if (providers == null) {
providers = initProviders(getHandlerMapping());
+ }
+ }
+
+ public void tearDown() throws Exception {
+ if (providers != null) {
+ for (int i = 0; i < providers.length; i++) {
+ providers[i].shutdown();
+ }
}
}