From 731bfec47324a90a30e1a97e3901c2f42c4c0d80 Mon Sep 17 00:00:00 2001 From: yapei Date: Wed, 13 Sep 2017 16:10:00 -0500 Subject: [PATCH] Add ability to reset password in JedisFactory for JedisPool and JedisSentinelPool --- .../redis/clients/jedis/JedisFactory.java | 18 +++++---- .../java/redis/clients/jedis/JedisPool.java | 5 +++ .../clients/jedis/JedisSentinelPool.java | 9 +++++ .../clients/jedis/tests/JedisPoolTest.java | 39 ++++++++++++++++++- .../jedis/tests/JedisSentinelPoolTest.java | 39 +++++++++++++++++++ 5 files changed, 102 insertions(+), 8 deletions(-) diff --git a/src/main/java/redis/clients/jedis/JedisFactory.java b/src/main/java/redis/clients/jedis/JedisFactory.java index be837d3660..eb6aa08cbb 100644 --- a/src/main/java/redis/clients/jedis/JedisFactory.java +++ b/src/main/java/redis/clients/jedis/JedisFactory.java @@ -18,11 +18,11 @@ /** * PoolableObjectFactory custom impl. */ -class JedisFactory implements PooledObjectFactory { +public class JedisFactory implements PooledObjectFactory { private final AtomicReference hostAndPort = new AtomicReference(); + private final AtomicReference password = new AtomicReference(); private final int connectionTimeout; private final int soTimeout; - private final String password; private final int database; private final String clientName; private final boolean ssl; @@ -30,7 +30,7 @@ class JedisFactory implements PooledObjectFactory { private final SSLParameters sslParameters; private final HostnameVerifier hostnameVerifier; - JedisFactory(final String host, final int port, final int connectionTimeout, + public JedisFactory(final String host, final int port, final int connectionTimeout, final int soTimeout, final String password, final int database, final String clientName) { this(host, port, connectionTimeout, soTimeout, password, database, clientName, false, null, null, null); @@ -43,7 +43,7 @@ class JedisFactory implements PooledObjectFactory { this.hostAndPort.set(new HostAndPort(host, port)); this.connectionTimeout = connectionTimeout; this.soTimeout = soTimeout; - this.password = password; + this.password.set(password); this.database = database; this.clientName = clientName; this.ssl = ssl; @@ -68,7 +68,7 @@ class JedisFactory implements PooledObjectFactory { this.hostAndPort.set(new HostAndPort(uri.getHost(), uri.getPort())); this.connectionTimeout = connectionTimeout; this.soTimeout = soTimeout; - this.password = JedisURIHelper.getPassword(uri); + this.password.set(JedisURIHelper.getPassword(uri)); this.database = JedisURIHelper.getDBIndex(uri); this.clientName = clientName; this.ssl = JedisURIHelper.isRedisSSLScheme(uri); @@ -81,6 +81,10 @@ public void setHostAndPort(final HostAndPort hostAndPort) { this.hostAndPort.set(hostAndPort); } + public void setPassword(final String password) { + this.password.set(password); + } + @Override public void activateObject(PooledObject pooledJedis) throws Exception { final BinaryJedis jedis = pooledJedis.getObject(); @@ -115,8 +119,8 @@ public PooledObject makeObject() throws Exception { try { jedis.connect(); - if (password != null) { - jedis.auth(password); + if (password.get() != null) { + jedis.auth(password.get()); } if (database != 0) { jedis.select(database); diff --git a/src/main/java/redis/clients/jedis/JedisPool.java b/src/main/java/redis/clients/jedis/JedisPool.java index 1b9cc1bc36..1b3de6d490 100644 --- a/src/main/java/redis/clients/jedis/JedisPool.java +++ b/src/main/java/redis/clients/jedis/JedisPool.java @@ -6,6 +6,7 @@ import javax.net.ssl.SSLParameters; import javax.net.ssl.SSLSocketFactory; +import org.apache.commons.pool2.PooledObjectFactory; import org.apache.commons.pool2.impl.GenericObjectPool; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; @@ -228,6 +229,10 @@ public JedisPool(final GenericObjectPoolConfig poolConfig, final URI uri, super(poolConfig, new JedisFactory(uri, connectionTimeout, soTimeout, null, sslSocketFactory, sslParameters, hostnameVerifier)); } + + public JedisPool(GenericObjectPoolConfig poolConfig, PooledObjectFactory factory) { + super(poolConfig, factory); + } @Override public Jedis getResource() { diff --git a/src/main/java/redis/clients/jedis/JedisSentinelPool.java b/src/main/java/redis/clients/jedis/JedisSentinelPool.java index f681d00150..eaaf5e2c76 100644 --- a/src/main/java/redis/clients/jedis/JedisSentinelPool.java +++ b/src/main/java/redis/clients/jedis/JedisSentinelPool.java @@ -95,6 +95,15 @@ public JedisSentinelPool(String masterName, Set sentinels, initPool(master); } + public JedisSentinelPool(String masterName, Set sentinels, final GenericObjectPoolConfig poolConfig, final JedisFactory factory) { + this.poolConfig = poolConfig; + this.factory = factory; + + HostAndPort master = initSentinels(sentinels, masterName); + initPool(poolConfig, factory); + initPool(master); + } + @Override public void destroy() { for (MasterListener m : masterListeners) { diff --git a/src/test/java/redis/clients/jedis/tests/JedisPoolTest.java b/src/test/java/redis/clients/jedis/tests/JedisPoolTest.java index a18de306f8..05e0711b4e 100644 --- a/src/test/java/redis/clients/jedis/tests/JedisPoolTest.java +++ b/src/test/java/redis/clients/jedis/tests/JedisPoolTest.java @@ -17,11 +17,12 @@ import redis.clients.jedis.HostAndPort; import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisFactory; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; import redis.clients.jedis.Transaction; import redis.clients.jedis.exceptions.InvalidURIException; -import redis.clients.jedis.exceptions.JedisException; +import redis.clients.jedis.exceptions.JedisConnectionException; import redis.clients.jedis.exceptions.JedisExhaustedPoolException; public class JedisPoolTest { @@ -381,4 +382,40 @@ private int getClientCount(final String clientList) { return clientList.split("\n").length; } + @Test + public void testResetInvalidPassword() { + JedisFactory factory = new JedisFactory(hnp.getHost(), hnp.getPort(), 2000, 2000, "foobared", 0, "my_shiny_client_name"); + + + try(JedisPool pool = new JedisPool(new JedisPoolConfig(), factory); + Jedis obj1 = pool.getResource();){ + obj1.set("foo", "bar"); + assertEquals("bar", obj1.get("foo")); + assertEquals(1, pool.getNumActive()); + + factory.setPassword("wrong password"); + try (Jedis obj2 = pool.getResource()) { + fail("Should not get resource from pool"); + } catch (JedisConnectionException e) {} + } + } + + @Test + public void testResetValidPassword() { + JedisFactory factory = new JedisFactory(hnp.getHost(), hnp.getPort(), 2000, 2000, "bad password", 0, "my_shiny_client_name"); + JedisPool pool = new JedisPool(new JedisPoolConfig(), factory); + Jedis obj = null; + try { + pool.getResource(); + fail("Could not get resource from pool"); + } catch (JedisConnectionException e) { + factory.setPassword("foobared"); + obj = pool.getResource(); + obj.set("foo", "bar"); + assertEquals("bar", obj.get("foo")); + } finally { + obj.close(); + pool.close(); + } + } } diff --git a/src/test/java/redis/clients/jedis/tests/JedisSentinelPoolTest.java b/src/test/java/redis/clients/jedis/tests/JedisSentinelPoolTest.java index bdf1975b1c..5adfa48d4e 100644 --- a/src/test/java/redis/clients/jedis/tests/JedisSentinelPoolTest.java +++ b/src/test/java/redis/clients/jedis/tests/JedisSentinelPoolTest.java @@ -2,6 +2,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.util.HashSet; import java.util.Set; @@ -12,6 +13,8 @@ import redis.clients.jedis.HostAndPort; import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisFactory; +import redis.clients.jedis.JedisPoolConfig; import redis.clients.jedis.JedisSentinelPool; import redis.clients.jedis.Transaction; import redis.clients.jedis.exceptions.JedisConnectionException; @@ -161,6 +164,42 @@ public void customClientName() { assertTrue(pool.isClosed()); } + + @Test + public void testResetInvalidPassword() { + JedisFactory factory = new JedisFactory(null, 0, 2000, 2000, "foobared", 0, "my_shiny_client_name"); + + try(JedisSentinelPool pool = new JedisSentinelPool(MASTER_NAME, sentinels, new JedisPoolConfig(), factory); + Jedis obj1 = pool.getResource(); ) { + obj1.set("foo", "bar"); + assertEquals("bar", obj1.get("foo")); + assertEquals(1, pool.getNumActive()); + + factory.setPassword("wrong password"); + try (Jedis obj2 = pool.getResource();) { + fail("Should not get resource from pool"); + }catch (JedisConnectionException e) {} + } + } + + @Test + public void testResetValidPassword() { + JedisFactory factory = new JedisFactory(null, 0, 2000, 2000, "wrong password", 0, "my_shiny_client_name"); + JedisSentinelPool pool = new JedisSentinelPool(MASTER_NAME, sentinels, new JedisPoolConfig(), factory); + Jedis obj = null; + try { + pool.getResource(); + fail("Could not get resource from pool"); + } catch (JedisConnectionException e) { + factory.setPassword("foobared"); + obj = pool.getResource(); + obj.set("foo", "bar"); + assertEquals("bar", obj.get("foo")); + } finally { + obj.close(); + pool.close(); + } + } private void forceFailover(JedisSentinelPool pool) throws InterruptedException { HostAndPort oldMaster = pool.getCurrentHostMaster();