Index: src/java/org/apache/xmlrpc/WebServer.java
===================================================================
RCS file: /home/cvspublic/ws-xmlrpc/src/java/org/apache/xmlrpc/WebServer.java,v
retrieving revision 1.24
diff -u -r1.24 WebServer.java
--- src/java/org/apache/xmlrpc/WebServer.java	1 May 2004 00:40:47 -0000	1.24
+++ src/java/org/apache/xmlrpc/WebServer.java	15 May 2004 11:28:44 -0000
@@ -90,7 +90,18 @@
 
     // Inputs to setupServerSocket()
     private InetAddress address;
-    private int port;
+    
+    /**
+     * <p>Port number to create the serverSocket.</p>
+     * <p>This may be 0 in which case the port is actually chosen by the JVM.
+     * Please note that the accessor on the port number waits for the
+     * serverSocket to be created and asks it directly on which port it listens
+     * (so this accessor never returns 0).</p>
+     * <p>It is an Integer, so I can hook a monitor on it for getPort.</p>
+     *
+     * @see #getPort
+     */
+    private Integer port;
 
     private boolean paranoid;
 
@@ -137,6 +148,11 @@
         {
             webserver.addDefaultHandlers();
             webserver.start();
+            
+            // Test the getPort() method. It's mostly interesting if
+            // the port passed as a parameter was 0.
+            System.out.println(
+                            "Server is running on port " + webserver.getPort());
         }
         catch (Exception e)
         {
@@ -175,7 +191,10 @@
     }
 
     /**
-     * Creates a web server at the specified port number.
+     * Creates a web server at the specified port number. A port of 0 creates
+     * the web server on any free port determined by the JVM.
+     *
+     * @param port  port to create the serverSocket at. 0 means any free port.
      */
     public WebServer(int port)
     {
@@ -183,7 +202,11 @@
     }
 
     /**
-     * Creates a web server at the specified port number and IP address.
+     * Creates a web server at the specified port number and IP address. A port
+     * of 0 creates the web server on any free port determined by the JVM.
+     *
+     * @param port  port to create the serverSocket at. 0 means any free port.
+     * @param addr  IP address of the interface to create the webserver at.
      */
     public WebServer(int port, InetAddress addr)
     {
@@ -193,11 +216,16 @@
     /**
      * Creates a web server at the specified port number and IP
      * address.
+     *
+     * @param port  port to create the serverSocket at. 0 means any free port.
+     * @param addr  IP address of the interface to create the webserver at.
      */
     public WebServer(int port, InetAddress addr, XmlRpcServer xmlrpc)
     {
+        // At first, we don't have any serverSocket (so getPort will wait).
+        this.serverSocket = null;
         this.address = addr;
-        this.port = port;
+        this.port = new Integer(port);
         this.xmlrpc = xmlrpc;
         accept = new Vector();
         deny = new Vector();
@@ -206,6 +234,51 @@
     }
 
     /**
+     * <p>Accessor on the port number.</p>
+     * <p>This accessor is a little bit special. It will wait until the
+     * serverSocket is setup and then ask it which port it listens to, unless
+     * the port is not 0. The rationale is that the port might be initialized to
+     * 0 and therefore left to the JVM.</p>
+     * <p>If the port is 0, this accessor will wait until the server socket is
+     * set.</p>
+     *
+     * @return the port the server is listening on.
+     * @throws IllegalThreadStateException if the server has not been started
+     *         and the port is set to 0 (i.e. to be chosen by the JVM). This is
+     *         to prevent any deadlock, please call start before calling this
+     *         accessor.
+     * @see #start()
+     * @see port
+     */
+    public final int getPort() throws IllegalThreadStateException {
+        int theResult = port.intValue();
+        
+        if (theResult == 0) {
+            // The server needs to be running. Please call start() before
+            // calling this method.
+            if ((listener == null) || (!listener.isAlive())) {
+                throw new IllegalThreadStateException();
+            }
+            
+            // Wait until the server socket is setup.
+            synchronized (port) {
+                while (serverSocket == null) {
+                    try {
+                        port.wait();
+                    } catch (InterruptedException anException) {
+                        // Let's ignore it and keep looping.
+                    }
+                }
+            }
+            
+            // Grab the result.
+            theResult = serverSocket.getLocalPort();
+        }
+        
+        return theResult;
+    }
+    
+    /**
      * Returns the US-ASCII encoded byte representation of text for
      * HTTP use (as per section 2.2 of RFC 2068).
      */
@@ -227,7 +300,7 @@
      * hook method for subclasses to override when they desire
      * different flavor of socket (i.e. a <code>SSLServerSocket</code>).
      *
-     * @param port
+     * @param port    port to create the serverSocket at. 0 means any free port.
      * @param backlog
      * @param addr If <code>null</code>, binds to
      * <code>INADDR_ANY</code>, meaning that all network interfaces on
@@ -262,7 +335,13 @@
         {
             try
             {
-                serverSocket = createServerSocket(port, backlog, address);
+                synchronized (port) {
+                    serverSocket = createServerSocket(
+                                            port.intValue(), backlog, address);
+                
+                    // getPort might retrieve the port now.
+                    port.notifyAll();
+                }
             }
             catch (BindException e)
             {
