postgresql-jdbc.git / summary / log / commit / refs
commit e6b23db0150385629e536cf9df74f38cef736aee
Author: JY Cr <jycr@users.noreply.github.com>
Commit: GitHub <noreply@github.com>
Date: Mon Mar 08 21:04:06 2021 +0000
feat: Add new property to specify local Socket Address (#2081) (#2082)
README.md | 1 +
pgjdbc/src/main/java/org/postgresql/Driver.java | 3 ++-
pgjdbc/src/main/java/org/postgresql/core/PGStream.java | 5 +++++
pgjdbc/src/main/java/org/postgresql/util/HostSpec.java | 15 +++++++++++++--
.../test/java/org/postgresql/test/util/HostSpecTest.java | 14 ++++++++++++++
5 files changed, 35 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 32419789..6d8e25a6 100644
--- a/README.md
+++ b/README.md
@@ -136,6 +136,7 @@ In addition to the standard connection parameters the driver supports a number o
| adaptiveFetch | Boolean | false | Specifies if number of rows fetched in ResultSet by each fetch iteration should be dynamic. Number of rows will be calculated by dividing maxResultBuffer size into max row size observed so far. Requires declaring maxResultBuffer and defaultRowFetchSize for first iteration.
| adaptiveFetchMinimum | Integer | 0 | Specifies minimum number of rows, which can be calculated by adaptiveFetch. Number of rows used by adaptiveFetch cannot go below this value.
| adaptiveFetchMaximum | Integer | -1 | Specifies maximum number of rows, which can be calculated by adaptiveFetch. Number of rows used by adaptiveFetch cannot go above this value. Any negative number set as adaptiveFetchMaximum is used by adaptiveFetch as infinity number of rows.
+| localSocketAddress | String | null | Hostname or IP address given to explicitly configure the interface that the driver will bind the client side of the TCP/IP connection to when connecting.
## Contributing
For information on how to contribute to the project see the [Contributing Guidelines](CONTRIBUTING.md)
diff --git a/pgjdbc/src/main/java/org/postgresql/Driver.java b/pgjdbc/src/main/java/org/postgresql/Driver.java
index 97f7b906..5a101436 100644
--- a/pgjdbc/src/main/java/org/postgresql/Driver.java
+++ b/pgjdbc/src/main/java/org/postgresql/Driver.java
@@ -645,9 +645,10 @@ public class Driver implements java.sql.Driver {
private static HostSpec[] hostSpecs(Properties props) {
String[] hosts = castNonNull(props.getProperty("PGHOST")).split(",");
String[] ports = castNonNull(props.getProperty("PGPORT")).split(",");
+ String localSocketAddress = props.getProperty("localSocketAddress");
HostSpec[] hostSpecs = new HostSpec[hosts.length];
for (int i = 0; i < hostSpecs.length; ++i) {
- hostSpecs[i] = new HostSpec(hosts[i], Integer.parseInt(ports[i]));
+ hostSpecs[i] = new HostSpec(hosts[i], Integer.parseInt(ports[i]), localSocketAddress);
}
return hostSpecs;
}
diff --git a/pgjdbc/src/main/java/org/postgresql/core/PGStream.java b/pgjdbc/src/main/java/org/postgresql/core/PGStream.java
index 94bbcdaf..f33ab295 100644
--- a/pgjdbc/src/main/java/org/postgresql/core/PGStream.java
+++ b/pgjdbc/src/main/java/org/postgresql/core/PGStream.java
@@ -27,6 +27,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Writer;
+import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketException;
@@ -223,6 +224,10 @@ public class PGStream implements Closeable, Flushable {
private Socket createSocket(int timeout) throws IOException {
Socket socket = socketFactory.createSocket();
+ String localSocketAddress = hostSpec.getLocalSocketAddress();
+ if (localSocketAddress != null) {
+ socket.bind(new InetSocketAddress(InetAddress.getByName(localSocketAddress), 0));
+ }
if (!socket.isConnected()) {
// When using a SOCKS proxy, the host might not be resolvable locally,
// thus we defer resolution until the traffic reaches the proxy. If there
diff --git a/pgjdbc/src/main/java/org/postgresql/util/HostSpec.java b/pgjdbc/src/main/java/org/postgresql/util/HostSpec.java
index d3b2bec4..12d735c5 100644
--- a/pgjdbc/src/main/java/org/postgresql/util/HostSpec.java
+++ b/pgjdbc/src/main/java/org/postgresql/util/HostSpec.java
@@ -9,6 +9,7 @@ import static java.util.regex.Pattern.compile;
import org.checkerframework.checker.nullness.qual.Nullable;
+import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -18,12 +19,18 @@ import java.util.regex.Pattern;
public class HostSpec {
public static final String DEFAULT_NON_PROXY_HOSTS = "localhost|127.*|[::1]|0.0.0.0|[::0]";
+ protected final @Nullable String localSocketAddress;
protected final String host;
protected final int port;
public HostSpec(String host, int port) {
+ this(host, port, null);
+ }
+
+ public HostSpec(String host, int port, @Nullable String localSocketAddress) {
this.host = host;
this.port = port;
+ this.localSocketAddress = localSocketAddress;
}
public String getHost() {
@@ -41,12 +48,16 @@ public class HostSpec {
@Override
public boolean equals(@Nullable Object obj) {
return obj instanceof HostSpec && port == ((HostSpec) obj).port
- && host.equals(((HostSpec) obj).host);
+ && host.equals(((HostSpec) obj).host) && Objects.equals(localSocketAddress, ((HostSpec) obj).localSocketAddress);
}
@Override
public int hashCode() {
- return port ^ host.hashCode();
+ return Objects.hash(localSocketAddress, host, port);
+ }
+
+ public @Nullable String getLocalSocketAddress() {
+ return localSocketAddress;
}
public Boolean shouldResolve() {
diff --git a/pgjdbc/src/test/java/org/postgresql/test/util/HostSpecTest.java b/pgjdbc/src/test/java/org/postgresql/test/util/HostSpecTest.java
index a23deced..54aabf38 100644
--- a/pgjdbc/src/test/java/org/postgresql/test/util/HostSpecTest.java
+++ b/pgjdbc/src/test/java/org/postgresql/test/util/HostSpecTest.java
@@ -5,7 +5,9 @@
package org.postgresql.test.util;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import org.postgresql.util.HostSpec;
@@ -83,4 +85,16 @@ public class HostSpecTest {
HostSpec hostSpec = new HostSpec("example.org", 5432);
assertFalse(hostSpec.shouldResolve());
}
+
+ @Test
+ public void testShouldReturnEmptyLocalAddressBind() throws Exception {
+ HostSpec hostSpec = new HostSpec("example.org", 5432);
+ assertNull(hostSpec.getLocalSocketAddress());
+ }
+
+ @Test
+ public void testShouldReturnLocalAddressBind() throws Exception {
+ HostSpec hostSpec = new HostSpec("example.org", 5432, "foo");
+ assertEquals("foo", hostSpec.getLocalSocketAddress());
+ }
}
[parent: b9f791f940ef]