Author: kkolinko
Date: Thu Jan 7 14:04:28 2016
New Revision: 1723551
URL: http://svn.apache.org/viewvc?rev=1723551&view=rev
Log:
Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=52028
Add support for automatic binding to a free port by a connector
if the special value of zero is used for the port. This is
mainly useful in embedded and testing scenarios.
This includes backport of the following revisions from Tomcat 7:
r1207695 r1208115 r1208148 r1723441 r1723489
Handling of port number 0 in Jk AJP connector (ChannelSocket, ChannelNioSocket)
was changed.
Old behaviour was to disable the connector.
New behaviour is to bind to a random port number.
To disable the connector one can now use a negative port number. I doubt that
this "disable" feature was actually used by anyone. Also binding to a random
port is not so much different from disabling.
Modified:
tomcat/tc6.0.x/trunk/java/org/apache/catalina/connector/Connector.java
tomcat/tc6.0.x/trunk/java/org/apache/catalina/connector/mbeans-descriptors.xml
tomcat/tc6.0.x/trunk/java/org/apache/coyote/AbstractProtocol.java
tomcat/tc6.0.x/trunk/java/org/apache/coyote/memory/MemoryProtocolHandler.java
tomcat/tc6.0.x/trunk/java/org/apache/jk/common/ChannelNioSocket.java
tomcat/tc6.0.x/trunk/java/org/apache/jk/common/ChannelSocket.java
tomcat/tc6.0.x/trunk/java/org/apache/jk/server/JkCoyoteHandler.java
tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java
tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java
tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java
tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java
tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml
tomcat/tc6.0.x/trunk/webapps/docs/config/ajp.xml
tomcat/tc6.0.x/trunk/webapps/docs/config/http.xml
Modified: tomcat/tc6.0.x/trunk/java/org/apache/catalina/connector/Connector.java
URL:
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/connector/Connector.java?rev=1723551&r1=1723550&r2=1723551&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/catalina/connector/Connector.java
(original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/connector/Connector.java Thu
Jan 7 14:04:28 2016
@@ -659,7 +659,9 @@ public class Connector
}
/**
- * 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() {
@@ -682,6 +684,16 @@ public class Connector
/**
+ * 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() {
@@ -1067,7 +1079,13 @@ public class Connector
sb.append(":type=");
sb.append(type);
sb.append(",port=");
- sb.append(getPort());
+ int port = getPort();
+ if (port > 0) {
+ sb.append(port);
+ } else {
+ sb.append("auto-");
+ sb.append(getProperty("nameIndex"));
+ }
if (addressObj != null) {
String address = addressObj.toString();
if (address.length() > 0) {
@@ -1384,7 +1402,13 @@ public class Connector
StringBuilder sb = new StringBuilder("Connector[");
sb.append(getProtocol());
sb.append('-');
- sb.append(getPort());
+ int port = getPort();
+ if (port > 0) {
+ sb.append(port);
+ } else {
+ sb.append("auto-");
+ sb.append(getProperty("nameIndex"));
+ }
sb.append(']');
return sb.toString();
}
Modified:
tomcat/tc6.0.x/trunk/java/org/apache/catalina/connector/mbeans-descriptors.xml
URL:
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/connector/mbeans-descriptors.xml?rev=1723551&r1=1723550&r2=1723551&view=diff
==============================================================================
---
tomcat/tc6.0.x/trunk/java/org/apache/catalina/connector/mbeans-descriptors.xml
(original)
+++
tomcat/tc6.0.x/trunk/java/org/apache/catalina/connector/mbeans-descriptors.xml
Thu Jan 7 14:04:28 2016
@@ -110,6 +110,11 @@
description="Alias name of this connector's keypair and supporting
certificate chain"
type="java.lang.String"/>
+ <attribute name="localPort"
+ description="The port number on which this connector is listening to
requests. If the special value for port of zero is used then this method will
report the actual port bound."
+ type="int"
+ writeable="false"/>
+
<attribute name="maxHeaderCount"
description="The maximum number of headers that are allowed by the
container. 100 by default. A value of less than 0 means no limit."
type="int"/>
@@ -143,7 +148,7 @@
type="int"/>
<attribute name="port"
- description="The port number on which we listen for requests"
+ description="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."
type="int"/>
<attribute name="protocol"
Modified: tomcat/tc6.0.x/trunk/java/org/apache/coyote/AbstractProtocol.java
URL:
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/coyote/AbstractProtocol.java?rev=1723551&r1=1723550&r2=1723551&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/coyote/AbstractProtocol.java (original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/coyote/AbstractProtocol.java Thu Jan
7 14:04:28 2016
@@ -18,11 +18,26 @@ package org.apache.coyote;
import java.net.InetAddress;
import java.net.URLEncoder;
+import java.util.concurrent.atomic.AtomicInteger;
import org.apache.tomcat.util.net.AbstractEndpoint;
public abstract class AbstractProtocol implements ProtocolHandler {
+ /**
+ * Counter used to generate unique JMX names for connectors using automatic
+ * port binding.
+ */
+ private static final AtomicInteger nameCounter = new AtomicInteger(0);
+
+ /**
+ * Unique ID for this connector. Only used if the connector is configured
+ * to use a random port as the port will change if stop(), start() is
+ * called.
+ */
+ private int nameIndex = 0;
+
+
protected abstract AbstractEndpoint getEndpoint();
public int getMaxHeaderCount() {
@@ -32,6 +47,21 @@ public abstract class AbstractProtocol i
getEndpoint().setMaxHeaderCount(maxHeaderCount);
}
+ public int getLocalPort() {
+ return getEndpoint().getLocalPort();
+ }
+
+ public synchronized int getNameIndex() {
+ if (nameIndex == 0) {
+ nameIndex = nextNameIndex();
+ }
+ return nameIndex;
+ }
+
+ public static int nextNameIndex() {
+ return nameCounter.incrementAndGet();
+ }
+
/**
* An utility method, used to implement getName() in subclasses.
*/
@@ -45,7 +75,18 @@ public abstract class AbstractProtocol i
}
name.append(URLEncoder.encode(strAddr)).append('-');
}
- name.append(port);
+ if (port == 0) {
+ // Auto binding is in use. Check if port is known
+ name.append("auto-");
+ name.append(getNameIndex());
+ port = getLocalPort();
+ if (port != -1) {
+ name.append('-');
+ name.append(port);
+ }
+ } else {
+ name.append(port);
+ }
return name.toString();
}
}
Modified:
tomcat/tc6.0.x/trunk/java/org/apache/coyote/memory/MemoryProtocolHandler.java
URL:
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/coyote/memory/MemoryProtocolHandler.java?rev=1723551&r1=1723550&r2=1723551&view=diff
==============================================================================
---
tomcat/tc6.0.x/trunk/java/org/apache/coyote/memory/MemoryProtocolHandler.java
(original)
+++
tomcat/tc6.0.x/trunk/java/org/apache/coyote/memory/MemoryProtocolHandler.java
Thu Jan 7 14:04:28 2016
@@ -19,14 +19,15 @@ package org.apache.coyote.memory;
import java.io.IOException;
import java.util.Iterator;
-import org.apache.tomcat.util.buf.ByteChunk;
+import org.apache.coyote.AbstractProtocol;
import org.apache.coyote.Adapter;
import org.apache.coyote.InputBuffer;
import org.apache.coyote.OutputBuffer;
import org.apache.coyote.ProtocolHandler;
import org.apache.coyote.Request;
import org.apache.coyote.Response;
+import org.apache.tomcat.util.buf.ByteChunk;
/**
@@ -70,6 +71,20 @@ public class MemoryProtocolHandler
return (adapter);
}
+ /**
+ * Unique ID for this connector.
+ */
+ private int nameIndex = 0;
+
+ public synchronized int getNameIndex() {
+ if (nameIndex == 0) {
+ nameIndex = AbstractProtocol.nextNameIndex();
+ }
+
+ return nameIndex;
+ }
+
+ public int getLocalPort() { return -1; }
// ------------------------------------------------ ProtocolHandler Methods
Modified: tomcat/tc6.0.x/trunk/java/org/apache/jk/common/ChannelNioSocket.java
URL:
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/jk/common/ChannelNioSocket.java?rev=1723551&r1=1723550&r2=1723551&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/jk/common/ChannelNioSocket.java
(original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/jk/common/ChannelNioSocket.java Thu
Jan 7 14:04:28 2016
@@ -378,40 +378,61 @@ public class ChannelNioSocket extends Jk
*/
public void init() throws IOException {
// Find a port.
- if (startPort == 0) {
+ if (startPort < 0) {
port = 0;
if(log.isInfoEnabled())
log.info("JK: ajp13 disabling channelNioSocket");
running = true;
return;
}
- int endPort = maxPort;
- if (endPort < startPort)
- endPort = startPort;
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.configureBlocking(false);
- for( int i=startPort; i<=endPort; i++ ) {
+
+ if (startPort == 0) {
+ // Let operating system to choose a random free port
try {
InetSocketAddress iddr = null;
if( inet == null ) {
- iddr = new InetSocketAddress( i);
+ iddr = new InetSocketAddress(0);
} else {
- iddr=new InetSocketAddress( inet, i);
+ iddr=new InetSocketAddress(inet, 0);
}
sSocket = ssc.socket();
sSocket.bind(iddr);
- port=i;
- break;
} catch( IOException ex ) {
- if(log.isInfoEnabled())
- log.info("Port busy " + i + " " + ex.toString());
+ log.error("Can't find free port", ex);
sSocket = null;
+ return;
}
- }
- if( sSocket==null ) {
- log.error("Can't find free port " + startPort + " " + endPort );
- return;
+ port = sSocket.getLocalPort();
+ } else {
+ int endPort = maxPort;
+ if (endPort < startPort)
+ endPort = startPort;
+ for( int i=startPort; i<=endPort; i++ ) {
+ try {
+ InetSocketAddress iddr = null;
+ if( inet == null ) {
+ iddr = new InetSocketAddress( i);
+ } else {
+ iddr=new InetSocketAddress( inet, i);
+ }
+ sSocket = ssc.socket();
+ sSocket.bind(iddr);
+ port=i;
+ break;
+ } catch( IOException ex ) {
+ if(log.isInfoEnabled())
+ log.info("Port busy " + i + " " + ex.toString());
+ sSocket = null;
+ }
+ }
+
+ if( sSocket==null ) {
+ log.error("Can't find free port " + startPort + " " + endPort
);
+ return;
+ }
}
if(log.isInfoEnabled())
log.info("JK: ajp13 listening on " + getAddress() + ":" + port );
Modified: tomcat/tc6.0.x/trunk/java/org/apache/jk/common/ChannelSocket.java
URL:
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/jk/common/ChannelSocket.java?rev=1723551&r1=1723550&r2=1723551&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/jk/common/ChannelSocket.java (original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/jk/common/ChannelSocket.java Thu Jan
7 14:04:28 2016
@@ -359,35 +359,52 @@ public class ChannelSocket extends JkHan
*/
public void init() throws IOException {
// Find a port.
- if (startPort == 0) {
+ if (startPort < 0) {
port = 0;
if(log.isInfoEnabled())
log.info("JK: ajp13 disabling channelSocket");
running = true;
return;
}
- int endPort = maxPort;
- if (endPort < startPort)
- endPort = startPort;
- for( int i=startPort; i<=endPort; i++ ) {
+ if (startPort == 0) {
+ // Let operating system to choose a random free port
try {
if( inet == null ) {
- sSocket = new ServerSocket( i, backlog );
+ sSocket = new ServerSocket( 0, backlog );
} else {
- sSocket=new ServerSocket( i, backlog, inet );
+ sSocket=new ServerSocket( 0, backlog, inet );
}
- port=i;
- break;
} catch( IOException ex ) {
- if(log.isInfoEnabled())
- log.info("Port busy " + i + " " + ex.toString());
- continue;
+ log.error("Can't find free port", ex);
+ sSocket = null;
+ return;
}
- }
- if( sSocket==null ) {
- log.error("Can't find free port " + startPort + " " + endPort );
- return;
+ port = sSocket.getLocalPort();
+ } else {
+ int endPort = maxPort;
+ if (endPort < startPort)
+ endPort = startPort;
+ for( int i=startPort; i<=endPort; i++ ) {
+ try {
+ if( inet == null ) {
+ sSocket = new ServerSocket( i, backlog );
+ } else {
+ sSocket=new ServerSocket( i, backlog, inet );
+ }
+ port=i;
+ break;
+ } catch( IOException ex ) {
+ if(log.isInfoEnabled())
+ log.info("Port busy " + i + " " + ex.toString());
+ continue;
+ }
+ }
+
+ if( sSocket==null ) {
+ log.error("Can't find free port " + startPort + " " + endPort
);
+ return;
+ }
}
if(log.isInfoEnabled())
log.info("JK: ajp13 listening on " + getAddress() + ":" + port );
Modified: tomcat/tc6.0.x/trunk/java/org/apache/jk/server/JkCoyoteHandler.java
URL:
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/jk/server/JkCoyoteHandler.java?rev=1723551&r1=1723550&r2=1723551&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/jk/server/JkCoyoteHandler.java
(original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/jk/server/JkCoyoteHandler.java Thu Jan
7 14:04:28 2016
@@ -23,15 +23,19 @@ import java.util.Iterator;
import javax.management.MBeanServer;
import javax.management.ObjectName;
+import org.apache.coyote.AbstractProtocol;
import org.apache.coyote.Adapter;
import org.apache.coyote.ProtocolHandler;
import org.apache.coyote.Request;
import org.apache.coyote.Response;
import org.apache.coyote.RequestInfo;
import org.apache.coyote.Constants;
+import org.apache.jk.common.ChannelNioSocket;
+import org.apache.jk.common.ChannelSocket;
import org.apache.jk.core.JkHandler;
import org.apache.jk.core.Msg;
import org.apache.jk.core.MsgContext;
+import org.apache.jk.core.WorkerEnv;
import org.apache.tomcat.util.modeler.Registry;
/** Plugs Jk into Coyote. Must be named "type=JkHandler,name=container"
@@ -44,6 +48,35 @@ public class JkCoyoteHandler extends JkH
= org.apache.juli.logging.LogFactory.getLog(JkCoyoteHandler.class);
// Set debug on this logger to see the container request time
+ /**
+ * Unique ID for this connector. Only used if the connector is configured
+ * to use a random port as the port will change if stop(), start() is
+ * called.
+ */
+ private int nameIndex = 0;
+
+ public synchronized int getNameIndex() {
+ if (nameIndex == 0) {
+ nameIndex = AbstractProtocol.nextNameIndex();
+ }
+
+ return nameIndex;
+ }
+
+ public int getLocalPort() {
+ WorkerEnv wEnv = getJkMain().getWorkerEnv();
+ for( int i=0; i<wEnv.getHandlerCount(); i++ ) {
+ JkHandler w = wEnv.getHandler(i);
+ if( w instanceof ChannelSocket ) {
+ return ((ChannelSocket) w).getPort();
+ }
+ if( w instanceof ChannelNioSocket ) {
+ return ((ChannelNioSocket) w).getPort();
+ }
+ }
+ return -1;
+ }
+
// ----------------------------------------------------------- DoPrivileged
private boolean paused = false;
int epNote;
Modified:
tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java
URL:
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java?rev=1723551&r1=1723550&r2=1723551&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java
(original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java
Thu Jan 7 14:04:28 2016
@@ -16,7 +16,7 @@
*/
package org.apache.tomcat.util.net;
-public class AbstractEndpoint {
+public abstract class AbstractEndpoint {
/**
* The maximum number of headers in a request that are allowed.
@@ -30,4 +30,6 @@ public class AbstractEndpoint {
this.maxHeaderCount = maxHeaderCount;
}
+ public abstract int getLocalPort();
+
}
Modified: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java
URL:
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java?rev=1723551&r1=1723550&r2=1723551&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java
(original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java Thu
Jan 7 14:04:28 2016
@@ -36,6 +36,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.res.StringManager;
@@ -517,8 +518,6 @@ public class AprEndpoint extends Abstrac
public void setSSLVerifyDepth(int SSLVerifyDepth) { this.SSLVerifyDepth =
SSLVerifyDepth; }
- // --------------------------------------------------------- Public Methods
-
protected boolean SSLHonorCipherOrder = false;
/**
* Set to <code>true</code> to enforce the <i>server's</i> cipher order
@@ -542,6 +541,30 @@ public class AprEndpoint extends Abstrac
public void setSSLDisableCompression(boolean SSLDisableCompression) {
this.SSLDisableCompression = SSLDisableCompression; }
public boolean getSSLDisableCompression() { return SSLDisableCompression; }
+
+ /**
+ * 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.
*/
@@ -1036,9 +1059,9 @@ public class AprEndpoint extends Abstrac
try {
// Need to create a connection to unlock the accept();
if (address == null) {
- saddr = new InetSocketAddress("localhost", port);
+ saddr = new InetSocketAddress("localhost", getLocalPort());
} else {
- saddr = new InetSocketAddress(address,port);
+ saddr = new InetSocketAddress(address, getLocalPort());
}
s = new java.net.Socket();
s.setSoTimeout(soTimeout > 0 ? soTimeout : 60000);
@@ -1062,7 +1085,7 @@ public class AprEndpoint extends Abstrac
}
} catch(Exception e) {
if (log.isDebugEnabled()) {
- log.debug(sm.getString("endpoint.debug.unlock", "" + port), e);
+ log.debug(sm.getString("endpoint.debug.unlock", "" +
getLocalPort()), e);
}
} finally {
if (s != null) {
@@ -1137,7 +1160,7 @@ public class AprEndpoint extends Abstrac
if (curThreadsBusy == maxThreads) {
log.info(sm.getString("endpoint.info.maxThreads",
Integer.toString(maxThreads), address,
- Integer.toString(port)));
+ Integer.toString(getLocalPort())));
}
return (newWorkerThread());
} else {
Modified: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java
URL:
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java?rev=1723551&r1=1723550&r2=1723551&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java
(original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java Thu
Jan 7 14:04:28 2016
@@ -271,7 +271,21 @@ public class JIoEndpoint extends Abstrac
this.unlockTimeout = unlockTimeout;
}
-
+
+ /**
+ * Port in use.
+ */
+ @Override
+ public int getLocalPort() {
+ ServerSocket s = serverSocket;
+ if (s == null) {
+ return -1;
+ } else {
+ return s.getLocalPort();
+ }
+ }
+
+
public boolean isRunning() {
return running;
}
@@ -632,9 +646,9 @@ public class JIoEndpoint extends Abstrac
try {
// Need to create a connection to unlock the accept();
if (address == null) {
- saddr = new InetSocketAddress("localhost", port);
+ saddr = new InetSocketAddress("localhost", getLocalPort());
} else {
- saddr = new InetSocketAddress(address,port);
+ saddr = new InetSocketAddress(address, getLocalPort());
}
s = new java.net.Socket();
s.setSoTimeout(soTimeout);
@@ -648,7 +662,8 @@ public class JIoEndpoint extends Abstrac
}
} catch (Exception e) {
if (log.isDebugEnabled()) {
- log.debug(sm.getString("endpoint.debug.unlock", "" + port), e);
+ log.debug(sm.getString("endpoint.debug.unlock",
+ Integer.toString(getLocalPort())), e);
}
} finally {
if (s != null) {
@@ -718,7 +733,7 @@ public class JIoEndpoint extends Abstrac
if (curThreadsBusy == maxThreads) {
log.info(sm.getString("endpoint.info.maxThreads",
Integer.toString(maxThreads), address,
- Integer.toString(port)));
+ Integer.toString(getLocalPort())));
}
return (newWorkerThread());
} else {
Modified: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java
URL:
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java?rev=1723551&r1=1723550&r2=1723551&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java
(original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java Thu
Jan 7 14:04:28 2016
@@ -22,6 +22,7 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
+import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.nio.ByteBuffer;
@@ -690,6 +691,26 @@ public class NioEndpoint extends Abstrac
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() {
@@ -982,7 +1003,7 @@ public class NioEndpoint extends Abstrac
*/
public void destroy() throws Exception {
if (log.isDebugEnabled()) {
- log.debug("Destroy initiated for "+new
InetSocketAddress(address,port));
+ log.debug("Destroy initiated for "+new
InetSocketAddress(address,getLocalPort()));
}
if (running) {
stop();
@@ -996,7 +1017,7 @@ public class NioEndpoint extends Abstrac
releaseCaches();
selectorPool.close();
if (log.isDebugEnabled()) {
- log.debug("Destroy completed for "+new
InetSocketAddress(address,port));
+ log.debug("Destroy completed for "+new
InetSocketAddress(address,getLocalPort()));
}
}
@@ -1049,9 +1070,9 @@ public class NioEndpoint extends Abstrac
try {
// Need to create a connection to unlock the accept();
if (address == null) {
- saddr = new InetSocketAddress("localhost", port);
+ saddr = new InetSocketAddress("localhost", getLocalPort());
} else {
- saddr = new InetSocketAddress(address,port);
+ saddr = new InetSocketAddress(address, getLocalPort());
}
s = new java.net.Socket();
s.setSoTimeout(getSocketProperties().getSoTimeout());
@@ -1065,7 +1086,8 @@ public class NioEndpoint extends Abstrac
}
} catch(Exception e) {
if (log.isDebugEnabled()) {
- log.debug(sm.getString("endpoint.debug.unlock", "" + port), e);
+ log.debug(sm.getString("endpoint.debug.unlock",
+ Integer.toString(getLocalPort())), e);
}
} finally {
if (s != null) {
@@ -1192,7 +1214,7 @@ public class NioEndpoint extends Abstrac
if (curThreadsBusy == maxThreads) {
log.info(sm.getString("endpoint.info.maxThreads",
Integer.toString(maxThreads), address,
- Integer.toString(port)));
+ Integer.toString(getLocalPort())));
}
return (newWorkerThread());
} else {
Modified: tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml
URL:
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml?rev=1723551&r1=1723550&r2=1723551&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml Thu Jan 7 14:04:28 2016
@@ -115,6 +115,11 @@
<bug>51503</bug>: Add additional validation that prevents a connector
from starting if it does not have a valid port number. (kkolinko)
</fix>
+ <add>
+ <bug>52028</bug>: Add support for automatic binding to a free port by a
+ connector if the special value of zero is used for the port. This is
+ mainly useful in embedded and testing scenarios. (kkolinko)
+ </add>
<fix>
<bug>52926</bug>: Avoid NPE when an NIO Comet connection times out on
one thread at the same time as it is closed on another thread.
Modified: tomcat/tc6.0.x/trunk/webapps/docs/config/ajp.xml
URL:
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/webapps/docs/config/ajp.xml?rev=1723551&r1=1723550&r2=1723551&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/webapps/docs/config/ajp.xml (original)
+++ tomcat/tc6.0.x/trunk/webapps/docs/config/ajp.xml Thu Jan 7 14:04:28 2016
@@ -147,7 +147,10 @@
<p>The TCP port number on which this <strong>Connector</strong>
will create a server socket and await incoming connections. Your
operating system will allow only one server application to listen
- to a particular port number on a particular IP address.</p>
+ to a particular port number on a particular IP address. If the special
+ value of 0 (zero) is used, then Tomcat will select a free port at random
+ to use for this connector. This is typically only useful in embedded and
+ testing applications.</p>
</attribute>
<attribute name="protocol" required="false">
Modified: tomcat/tc6.0.x/trunk/webapps/docs/config/http.xml
URL:
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/webapps/docs/config/http.xml?rev=1723551&r1=1723550&r2=1723551&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/webapps/docs/config/http.xml (original)
+++ tomcat/tc6.0.x/trunk/webapps/docs/config/http.xml Thu Jan 7 14:04:28 2016
@@ -154,7 +154,10 @@
<p>The TCP port number on which this <strong>Connector</strong>
will create a server socket and await incoming connections. Your
operating system will allow only one server application to listen
- to a particular port number on a particular IP address.</p>
+ to a particular port number on a particular IP address. If the special
+ value of 0 (zero) is used, then Tomcat will select a free port at random
+ to use for this connector. This is typically only useful in embedded and
+ testing applications.</p>
</attribute>
<attribute name="protocol" required="false">
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]