--- a/java/org/apache/catalina/connector/Connector.java
+++ a/java/org/apache/catalina/connector/Connector.java
@@ -114,7 +114,7 @@ public class Connector extends LifecycleMBeanBase {
/**
* The port number on which we listen for requests.
*/
- protected int port = 0;
+ protected int port = -1;
/**
@@ -497,7 +497,9 @@ public class Connector extends LifecycleMBeanBase {
}
/**
- * Return the port number on which we listen for requests.
+ * Return the port number on which this connector is configured to listen
+ * for requests. The special value of 0 means select a random free port
+ * when the socket is bound.
*/
public int getPort() {
@@ -520,6 +522,16 @@ public class Connector extends LifecycleMBeanBase {
/**
+ * Return the port number on which this connector is listening to requests.
+ * If the special value for {@link #port} of zero is used then this method
+ * will report the actual port bound.
+ */
+ public int getLocalPort() {
+ return ((Integer) getProperty("localPort")).intValue();
+ }
+
+
+ /**
* Return the Coyote protocol handler in use.
*/
public String getProtocol() {
@@ -938,7 +950,7 @@ public class Connector extends LifecycleMBeanBase {
protected void startInternal() throws LifecycleException {
// Validate settings before starting
- if (getPort() < 1) {
+ if (getPort() < 0) {
throw new LifecycleException(sm.getString(
"coyoteConnector.invalidPort", Integer.valueOf(getPort())));
}
--- a/java/org/apache/catalina/connector/mbeans-descriptors.xml
+++ a/java/org/apache/catalina/connector/mbeans-descriptors.xml
@@ -108,7 +108,11 @@
type="int"/>
+
+
--- a/java/org/apache/coyote/AbstractProtocol.java
+++ a/java/org/apache/coyote/AbstractProtocol.java
@@ -194,6 +194,8 @@ public abstract class AbstractProtocol implements ProtocolHandler,
}
+ public int getLocalPort() { return endpoint.getLocalPort(); }
+
/*
* When Tomcat expects data from the client, this is the time Tomcat will
* wait for that data to arrive before closing the connection.
--- a/java/org/apache/tomcat/util/net/AbstractEndpoint.java
+++ a/java/org/apache/tomcat/util/net/AbstractEndpoint.java
@@ -141,6 +141,7 @@ public abstract class AbstractEndpoint {
public int getPort() { return port; }
public void setPort(int port ) { this.port=port; }
+ public abstract int getLocalPort();
/**
* Address for the server socket.
--- a/java/org/apache/tomcat/util/net/AprEndpoint.java
+++ a/java/org/apache/tomcat/util/net/AprEndpoint.java
@@ -37,6 +37,7 @@ import org.apache.tomcat.jni.Pool;
import org.apache.tomcat.jni.SSL;
import org.apache.tomcat.jni.SSLContext;
import org.apache.tomcat.jni.SSLSocket;
+import org.apache.tomcat.jni.Sockaddr;
import org.apache.tomcat.jni.Socket;
import org.apache.tomcat.jni.Status;
import org.apache.tomcat.util.ExceptionUtils;
@@ -326,8 +327,29 @@ public class AprEndpoint extends AbstractEndpoint {
public void setSSLInsecureRenegotiation(boolean SSLInsecureRenegotiation) { this.SSLInsecureRenegotiation = SSLInsecureRenegotiation; }
public boolean getSSLInsecureRenegotiation() { return SSLInsecureRenegotiation; }
- // --------------------------------------------------------- Public Methods
+ /**
+ * Port in use.
+ */
+ @Override
+ public int getLocalPort() {
+ long s = serverSock;
+ if (s == 0) {
+ return -1;
+ } else {
+ long sa;
+ try {
+ sa = Address.get(Socket.APR_LOCAL, s);
+ Sockaddr addr = Address.getInfo(sa);
+ return addr.port;
+ } catch (Exception e) {
+ return -1;
+ }
+ }
+ }
+
+
+ // --------------------------------------------------------- Public Methods
/**
* Number of keepalive sockets.
--- a/java/org/apache/tomcat/util/net/JIoEndpoint.java
+++ a/java/org/apache/tomcat/util/net/JIoEndpoint.java
@@ -96,6 +96,18 @@ public class JIoEndpoint extends AbstractEndpoint {
public void setServerSocketFactory(ServerSocketFactory factory) { this.serverSocketFactory = factory; }
public ServerSocketFactory getServerSocketFactory() { return serverSocketFactory; }
+ /**
+ * Port in use.
+ */
+ @Override
+ public int getLocalPort() {
+ ServerSocket s = serverSocket;
+ if (s == null) {
+ return -1;
+ } else {
+ return s.getLocalPort();
+ }
+ }
/*
* Optional feature support.
--- a/java/org/apache/tomcat/util/net/NioEndpoint.java
+++ a/java/org/apache/tomcat/util/net/NioEndpoint.java
@@ -21,6 +21,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
+import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.nio.ByteBuffer;
@@ -402,6 +403,26 @@ public class NioEndpoint extends AbstractEndpoint {
public SSLContext getSSLContext() { return sslContext;}
public void setSSLContext(SSLContext c) { sslContext = c;}
+
+ /**
+ * Port in use.
+ */
+ @Override
+ public int getLocalPort() {
+ ServerSocketChannel ssc = serverSock;
+ if (ssc == null) {
+ return -1;
+ } else {
+ ServerSocket s = ssc.socket();
+ if (s == null) {
+ return -1;
+ } else {
+ return s.getLocalPort();
+ }
+ }
+ }
+
+
// --------------------------------------------------------- OOM Parachute Methods
protected void checkParachute() {
--- a/test/org/apache/catalina/connector/TestConnector.java
+++ a/test/org/apache/catalina/connector/TestConnector.java
@@ -19,6 +19,7 @@ package org.apache.catalina.connector;
import java.net.SocketTimeoutException;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import org.junit.Test;
@@ -69,4 +70,26 @@ public class TestConnector extends TomcatBaseTest {
}
assertEquals(503, rc);
}
+
+
+ @Test
+ public void testPort() throws Exception {
+ Tomcat tomcat = getTomcatInstance();
+
+ Connector connector1 = tomcat.getConnector();
+ connector1.setPort(0);
+
+ Connector connector2 = new Connector();
+ connector2.setPort(0);
+
+ tomcat.getService().addConnector(connector2);
+
+ tomcat.start();
+
+ int localPort1 = connector1.getLocalPort();
+ int localPort2 = connector2.getLocalPort();
+
+ assertTrue(localPort1 > 0);
+ assertTrue(localPort2 > 0);
+ }
}