diff --git a/projects/cadcAccessControl-Admin/build.xml b/projects/cadcAccessControl-Admin/build.xml index 69fca321f6832fdd7e56ab423a3c3b0051a8b49b..7d6e61846b6dadf85504be14efa70f0a910642bb 100644 --- a/projects/cadcAccessControl-Admin/build.xml +++ b/projects/cadcAccessControl-Admin/build.xml @@ -144,8 +144,7 @@ <pathelement path="${build}/test/class"/> <pathelement path="${jars}:${testingJars}"/> </classpath> - <sysproperty key="ca.nrc.cadc.util.PropertiesReader.dir" value="test"/> - <test name="ca.nrc.cadc.ac.admin.integration.AdminIntTest" /> + <test name="ca.nrc.cadc.ac.admin.UserAdminTest" /> <formatter type="plain" usefile="false" /> </junit> </target> diff --git a/projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/AbstractCommand.java b/projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/AbstractCommand.java index 9cda6f89fa9ab2a05d0e94c3a7bb9a19502620ef..5740a43e15bf4c3ecc81eeb0c19b227241dda2b8 100644 --- a/projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/AbstractCommand.java +++ b/projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/AbstractCommand.java @@ -136,7 +136,9 @@ public abstract class AbstractCommand implements PrivilegedAction<Object> protected <T extends Principal> UserPersistence<T> getUserPersistence() { + System.setProperty("java.naming.factory.initial", ContextFactoryImpl.class.getName()); + PluginFactory pluginFactory = new PluginFactory(); - return pluginFactory.getUserPersistence(); + return pluginFactory.createUserPersistence(); } } diff --git a/projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/ContextFactoryImpl.java b/projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/ContextFactoryImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..bbfb8efa2fd6a4a40ab9525959fd1e3e3b111058 --- /dev/null +++ b/projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/ContextFactoryImpl.java @@ -0,0 +1,25 @@ +package ca.nrc.cadc.ac.admin; + +import javax.naming.Context; +import javax.naming.NamingException; +import javax.naming.spi.InitialContextFactory; +import java.util.Hashtable; + +/** + * A Simple ContextFactory. + */ +public class ContextFactoryImpl implements InitialContextFactory +{ + + public ContextFactoryImpl() + { + } + + @Override + public Context getInitialContext(Hashtable environment) + throws NamingException + { + return new ContextImpl(); + } + +} diff --git a/projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/ContextImpl.java b/projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/ContextImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..e0e09fcda743ef609677efbbdce523641b6bccb9 --- /dev/null +++ b/projects/cadcAccessControl-Admin/src/ca/nrc/cadc/ac/admin/ContextImpl.java @@ -0,0 +1,266 @@ +/* +************************************************************************ +******************* CANADIAN ASTRONOMY DATA CENTRE ******************* +************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +* +* (c) 2011. (c) 2011. +* Government of Canada Gouvernement du Canada +* National Research Council Conseil national de recherches +* Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +* All rights reserved Tous droits réservés +* +* NRC disclaims any warranties, Le CNRC dénie toute garantie +* expressed, implied, or énoncée, implicite ou légale, +* statutory, of any kind with de quelque nature que ce +* respect to the software, soit, concernant le logiciel, +* including without limitation y compris sans restriction +* any warranty of merchantability toute garantie de valeur +* or fitness for a particular marchande ou de pertinence +* purpose. NRC shall not be pour un usage particulier. +* liable in any event for any Le CNRC ne pourra en aucun cas +* damages, whether direct or être tenu responsable de tout +* indirect, special or general, dommage, direct ou indirect, +* consequential or incidental, particulier ou général, +* arising from the use of the accessoire ou fortuit, résultant +* software. Neither the name de l'utilisation du logiciel. Ni +* of the National Research le nom du Conseil National de +* Council of Canada nor the Recherches du Canada ni les noms +* names of its contributors may de ses participants ne peuvent +* be used to endorse or promote être utilisés pour approuver ou +* products derived from this promouvoir les produits dérivés +* software without specific prior de ce logiciel sans autorisation +* written permission. préalable et particulière +* par écrit. +* +* This file is part of the Ce fichier fait partie du projet +* OpenCADC project. OpenCADC. +* +* OpenCADC is free software: OpenCADC est un logiciel libre ; +* you can redistribute it and/or vous pouvez le redistribuer ou le +* modify it under the terms of modifier suivant les termes de +* the GNU Affero General Public la “GNU Affero General Public +* License as published by the License” telle que publiée +* Free Software Foundation, par la Free Software Foundation +* either version 3 of the : soit la version 3 de cette +* License, or (at your option) licence, soit (à votre gré) +* any later version. toute version ultérieure. +* +* OpenCADC is distributed in the OpenCADC est distribué +* hope that it will be useful, dans l’espoir qu’il vous +* but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +* without even the implied GARANTIE : sans même la garantie +* warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +* or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +* PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +* General Public License for Générale Publique GNU Affero +* more details. pour plus de détails. +* +* You should have received Vous devriez avoir reçu une +* a copy of the GNU Affero copie de la Licence Générale +* General Public License along Publique GNU Affero avec +* with OpenCADC. If not, see OpenCADC ; si ce n’est +* <http://www.gnu.org/licenses/>. pas le cas, consultez : +* <http://www.gnu.org/licenses/>. +* +* $Revision: 5 $ +* +************************************************************************ +*/ + +package ca.nrc.cadc.ac.admin; + +import javax.naming.Binding; +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.Name; +import javax.naming.NameClassPair; +import javax.naming.NameParser; +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Map; + +/** + * A Simple JNDI context. + */ +public class ContextImpl implements Context +{ + Map<String,Object> map = new HashMap<String,Object>(1); + + @Override + public Object lookup(String name) throws NamingException + { + return map.get(name); + } + + @Override + public void bind(String name, Object value) throws NamingException + { + map.put(name, value); + } + + @Override + public Object addToEnvironment(String arg0, Object arg1) + throws NamingException + { + return null; + } + + @Override + public void bind(Name arg0, Object arg1) throws NamingException + { + } + + @Override + public void close() throws NamingException + { + } + + @Override + public Name composeName(Name arg0, Name arg1) throws NamingException + { + return null; + } + + @Override + public String composeName(String arg0, String arg1) + throws NamingException + { + return null; + } + + @Override + public Context createSubcontext(Name arg0) throws NamingException + { + // TODO Auto-generated method stub + return null; + } + + @Override + public Context createSubcontext(String arg0) throws NamingException + { + return null; + } + + @Override + public void destroySubcontext(Name arg0) throws NamingException + { + } + + @Override + public void destroySubcontext(String arg0) throws NamingException + { + // TODO Auto-generated method stub + + } + + @Override + public Hashtable<?, ?> getEnvironment() throws NamingException + { + return null; + } + + @Override + public String getNameInNamespace() throws NamingException + { + return null; + } + + @Override + public NameParser getNameParser(Name arg0) throws NamingException + { + return null; + } + + @Override + public NameParser getNameParser(String arg0) throws NamingException + { + return null; + } + + @Override + public NamingEnumeration<NameClassPair> list(Name arg0) + throws NamingException + { + return null; + } + + @Override + public NamingEnumeration<NameClassPair> list(String arg0) + throws NamingException + { + // TODO Auto-generated method stub + return null; + } + + @Override + public NamingEnumeration<Binding> listBindings(Name arg0) + throws NamingException + { + return null; + } + + @Override + public NamingEnumeration<Binding> listBindings(String arg0) + throws NamingException + { + return null; + } + + @Override + public Object lookup(Name arg0) throws NamingException + { + // TODO Auto-generated method stub + return null; + } + + @Override + public Object lookupLink(Name arg0) throws NamingException + { + return null; + } + + @Override + public Object lookupLink(String arg0) throws NamingException + { + return null; + } + + @Override + public void rebind(Name arg0, Object arg1) throws NamingException + { + } + + @Override + public void rebind(String arg0, Object arg1) throws NamingException + { + } + + @Override + public Object removeFromEnvironment(String arg0) throws NamingException + { + return null; + } + + @Override + public void rename(Name arg0, Name arg1) throws NamingException + { + } + + @Override + public void rename(String arg0, String arg1) throws NamingException + { + } + + @Override + public void unbind(Name arg0) throws NamingException + { + } + + @Override + public void unbind(String arg0) throws NamingException + { + } + +} \ No newline at end of file diff --git a/projects/cadcAccessControl-Admin/test/LdapConfig.properties b/projects/cadcAccessControl-Admin/test/LdapConfig.properties index 57fdb97105d8df8f1a4fb538f734a7045feadbfb..27f519ac7bb015646dcdabdf763c2a6ebcf8c447 100644 --- a/projects/cadcAccessControl-Admin/test/LdapConfig.properties +++ b/projects/cadcAccessControl-Admin/test/LdapConfig.properties @@ -1,8 +1,48 @@ -# This are the configuration fields required by the unit tests -server = proc5-03.cadc.dao.nrc.ca +############################################################### +# +# LDAP Connection and Pool Configuration +# +# +############################################################### + +# Read-only connection pool +readOnly.servers = proc5-03.cadc.dao.nrc.ca +readOnly.poolInitSize = 1 +readOnly.poolMaxSize = 2 +readOnly.poolPolicy = roundRobin +readOnly.maxWait = 30000 +readOnly.createIfNeeded = false + +# Read-write connection pool +readWrite.servers = proc5-03.cadc.dao.nrc.ca +readWrite.poolInitSize = 1 +readWrite.poolMaxSize = 2 +readWrite.poolPolicy = roundRobin +readWrite.maxWait = 30000 +readWrite.createIfNeeded = false + +# Unbound-Read-only connection pool +unboundReadOnly.servers = proc5-03.cadc.dao.nrc.ca +unboundReadOnly.poolInitSize = 1 +unboundReadOnly.poolMaxSize = 2 +unboundReadOnly.poolPolicy = roundRobin +unboundReadOnly.maxWait = 30000 +unboundReadOnly.createIfNeeded = false + +# server configuration -- applies to all servers +#dbrcHost = devLdap +#port = 636 +#proxyUser = uid=webproxy,ou=SpecialUsers,dc=canfar,dc=net +#usersDN = ou=Users,ou=ds,dc=canfar,dc=net +#userRequestsDN = ou=userRequests,ou=ds,dc=canfar,dc=net +#groupsDN = ou=Groups,ou=ds,dc=canfar,dc=net +#adminGroupsDN = ou=adminGroups,ou=ds,dc=canfar,dc=net + +# tree without aci's +dbrcHost = devLdap port = 389 -proxyUser = testproxy -usersDn = ou=Users,ou=ds,dc=testcanfar +proxyUser = uid=testproxy,ou=SpecialUsers,dc=testcanfar +usersDN = ou=Users,ou=ds,dc=testcanfar userRequestsDN = ou=UserRequests,ou=ds,dc=testcanfar -groupsDn = ou=Groups,ou=ds,dc=testcanfar -adminGroupsDn = ou=adminGroups,ou=ds,dc=testcanfar \ No newline at end of file +groupsDN = ou=Groups,ou=ds,dc=testcanfar +adminGroupsDN = ou=adminGroups,ou=ds,dc=testcanfar \ No newline at end of file diff --git a/projects/cadcAccessControl-Admin/test/src/ca/nrc/cadc/ac/admin/CmdLineParserTest.java b/projects/cadcAccessControl-Admin/test/src/ca/nrc/cadc/ac/admin/CmdLineParserTest.java index 010dc0f64adbb2836a7bd610b80610210774a64d..c9c28332d14f22d5869334e70c7d035c5314cb50 100644 --- a/projects/cadcAccessControl-Admin/test/src/ca/nrc/cadc/ac/admin/CmdLineParserTest.java +++ b/projects/cadcAccessControl-Admin/test/src/ca/nrc/cadc/ac/admin/CmdLineParserTest.java @@ -209,7 +209,7 @@ public class CmdLineParserTest } catch (UsageException e) { - String expected = "Missing command or ommand is not supported"; + String expected = "Missing command or command is not supported"; Assert.assertTrue(e.getMessage().contains(expected)); } catch (Exception e) diff --git a/projects/cadcAccessControl-Admin/test/src/ca/nrc/cadc/ac/admin/integration/AdminIntTest.java b/projects/cadcAccessControl-Admin/test/src/ca/nrc/cadc/ac/admin/UserAdminTest.java similarity index 96% rename from projects/cadcAccessControl-Admin/test/src/ca/nrc/cadc/ac/admin/integration/AdminIntTest.java rename to projects/cadcAccessControl-Admin/test/src/ca/nrc/cadc/ac/admin/UserAdminTest.java index ff8a4262841842871a8cbc45a1bdc81af9a44ca8..938f8b4a42ed8b44c7f2dd7312829c3d80571994 100644 --- a/projects/cadcAccessControl-Admin/test/src/ca/nrc/cadc/ac/admin/integration/AdminIntTest.java +++ b/projects/cadcAccessControl-Admin/test/src/ca/nrc/cadc/ac/admin/UserAdminTest.java @@ -66,7 +66,7 @@ * ************************************************************************ */ -package ca.nrc.cadc.ac.admin.integration; +package ca.nrc.cadc.ac.admin; import ca.nrc.cadc.ac.PersonalDetails; import ca.nrc.cadc.ac.User; @@ -79,6 +79,7 @@ import ca.nrc.cadc.auth.DNPrincipal; import ca.nrc.cadc.auth.HttpPrincipal; import ca.nrc.cadc.net.TransientException; import ca.nrc.cadc.util.Log4jInit; +import ca.nrc.cadc.util.PropertiesReader; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.junit.BeforeClass; @@ -99,9 +100,9 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -public class AdminIntTest +public class UserAdminTest { - private static final Logger log = Logger.getLogger(AdminIntTest.class); + private static final Logger log = Logger.getLogger(UserAdminTest.class); static final String EXEC_CMD = "./test/scripts/userAdminTest"; @@ -117,6 +118,8 @@ public class AdminIntTest testCert = "build/test/class/cadcauthtest1.pem"; config = LdapConfig.getLdapConfig(); + + System.setProperty(PropertiesReader.class.getName() + ".dir", "test"); } @Test @@ -350,15 +353,18 @@ public class AdminIntTest if (isPending) { userDAO.addPendingUser(userRequest); + log.debug("added pending user: " + username); } else { userDAO.addUser(userRequest); + log.debug("added user: " + username); } return null; } catch (Exception e) { + log.error("Exception adding user: " + e.getMessage()); throw new Exception("Problems", e); } } @@ -411,6 +417,7 @@ public class AdminIntTest <T extends Principal> LdapUserPersistence<T> getUserPersistence() { + System.setProperty("java.naming.factory.initial", ContextFactoryImpl.class.getName()); return new LdapUserPersistence<T>(); } diff --git a/projects/cadcAccessControl-Server/config/LdapConfig.dev.properties b/projects/cadcAccessControl-Server/config/LdapConfig.dev.properties index fe5eb3da0a422192242954a5dd0e31066c751052..63709c4b7827ffb0905633352bbb9f6830c82e9f 100644 --- a/projects/cadcAccessControl-Server/config/LdapConfig.dev.properties +++ b/projects/cadcAccessControl-Server/config/LdapConfig.dev.properties @@ -20,6 +20,14 @@ readWrite.poolPolicy = roundRobin readWrite.maxWait = 30000 readWrite.createIfNeeded = false +# Unbound-Read-write connection pool +unboundReadOnly.servers = proc5-03.cadc.dao.nrc.ca +unboundReadOnly.poolInitSize = 1 +unboundReadOnly.poolMaxSize = 1 +unboundReadOnly.poolPolicy = roundRobin +unboundReadOnly.maxWait = 30000 +unboundReadOnly.createIfNeeded = false + # server configuration -- applies to all servers dbrcHost = devLdap port = 636 diff --git a/projects/cadcAccessControl-Server/config/LdapConfig.properties b/projects/cadcAccessControl-Server/config/LdapConfig.properties index 92e89644d9f1b14674eee4d90907e7e07c0e6d3f..da1d558032e275768f341552c67ed37aad431722 100644 --- a/projects/cadcAccessControl-Server/config/LdapConfig.properties +++ b/projects/cadcAccessControl-Server/config/LdapConfig.properties @@ -21,6 +21,14 @@ readWrite.poolPolicy = <roundRobin || fewestConnections> readWrite.maxWait = <timeout wait time in milliseconds> readWrite.createIfNeeded = <true || false> Go beyond poolMaxSize +# Unbound-Read-only connection pool +unboundReadOnly.servers = <list of ldap servers for readonly unbound access> +unboundReadOnly.poolInitSize = <number of initial connections in the readonly pool> +unboundReadOnly.poolMaxSize = <maximum number of connections in the readonly pool> +unboundReadOnly.poolPolicy = <roundRobin || fewestConnections> +unboundReadOnly.maxWait = <timeout wait time in milliseconds> +unboundReadOnly.createIfNeeded = <true || false> Go beyond poolMaxSize + # server configuration -- applies to all servers dbrcHost = <prodLdap || devLdap> port = <389 or 636> diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/ConnectionPools.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/ConnectionPools.java new file mode 100644 index 0000000000000000000000000000000000000000..79956002b7e1ccdaa285cd6b932c1316220cdb2f --- /dev/null +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/ConnectionPools.java @@ -0,0 +1,100 @@ +/* + ************************************************************************ + ******************* CANADIAN ASTRONOMY DATA CENTRE ******************* + ************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** + * + * (c) 2014. (c) 2014. + * Government of Canada Gouvernement du Canada + * National Research Council Conseil national de recherches + * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 + * All rights reserved Tous droits réservés + * + * NRC disclaims any warranties, Le CNRC dénie toute garantie + * expressed, implied, or énoncée, implicite ou légale, + * statutory, of any kind with de quelque nature que ce + * respect to the software, soit, concernant le logiciel, + * including without limitation y compris sans restriction + * any warranty of merchantability toute garantie de valeur + * or fitness for a particular marchande ou de pertinence + * purpose. NRC shall not be pour un usage particulier. + * liable in any event for any Le CNRC ne pourra en aucun cas + * damages, whether direct or être tenu responsable de tout + * indirect, special or general, dommage, direct ou indirect, + * consequential or incidental, particulier ou général, + * arising from the use of the accessoire ou fortuit, résultant + * software. Neither the name de l'utilisation du logiciel. Ni + * of the National Research le nom du Conseil National de + * Council of Canada nor the Recherches du Canada ni les noms + * names of its contributors may de ses participants ne peuvent + * be used to endorse or promote être utilisés pour approuver ou + * products derived from this promouvoir les produits dérivés + * software without specific prior de ce logiciel sans autorisation + * written permission. préalable et particulière + * par écrit. + * + * This file is part of the Ce fichier fait partie du projet + * OpenCADC project. OpenCADC. + * + * OpenCADC is free software: OpenCADC est un logiciel libre ; + * you can redistribute it and/or vous pouvez le redistribuer ou le + * modify it under the terms of modifier suivant les termes de + * the GNU Affero General Public la “GNU Affero General Public + * License as published by the License” telle que publiée + * Free Software Foundation, par la Free Software Foundation + * either version 3 of the : soit la version 3 de cette + * License, or (at your option) licence, soit (à votre gré) + * any later version. toute version ultérieure. + * + * OpenCADC is distributed in the OpenCADC est distribué + * hope that it will be useful, dans l’espoir qu’il vous + * but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE + * without even the implied GARANTIE : sans même la garantie + * warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ + * or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF + * PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence + * General Public License for Générale Publique GNU Affero + * more details. pour plus de détails. + * + * You should have received Vous devriez avoir reçu une + * a copy of the GNU Affero copie de la Licence Générale + * General Public License along Publique GNU Affero avec + * with OpenCADC. If not, see OpenCADC ; si ce n’est + * <http://www.gnu.org/licenses/>. pas le cas, consultez : + * <http://www.gnu.org/licenses/>. + * + * $Revision: 4 $ + * + ************************************************************************ + */ + +package ca.nrc.cadc.ac.server.ldap; + +import java.util.Map; + +/** + * The object that is bound in JNDI to hold the LDAP pools. + */ +public class ConnectionPools +{ + + private LdapConfig config; + + private Map<String,LdapConnectionPool> pools; + + public ConnectionPools(Map<String,LdapConnectionPool> pools, LdapConfig config) + { + this.pools = pools; + this.config = config; + } + + public Map<String,LdapConnectionPool> getPools() + { + return pools; + } + + public LdapConfig getConfig() + { + return config; + } + +} diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapConfig.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapConfig.java index a58366053d277cb3e038844c02688fcabe1b2131..1cd4d5205bff0bc8db1797f2564be840d99712e4 100755 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapConfig.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapConfig.java @@ -81,7 +81,7 @@ import ca.nrc.cadc.util.MultiValuedProperties; import ca.nrc.cadc.util.PropertiesReader; /** - * Reads and stores the LDAP configuration information. The information + * Reads and stores the LDAP configuration information. * * @author adriand * @@ -94,6 +94,7 @@ public class LdapConfig public static final String READONLY_PREFIX = "readOnly."; public static final String READWRITE_PREFIX = "readWrite."; + public static final String UB_READONLY_PREFIX = "unboundReadOnly."; public static final String POOL_SERVERS = "servers"; public static final String POOL_INIT_SIZE = "poolInitSize"; public static final String POOL_MAX_SIZE = "poolMaxSize"; @@ -151,6 +152,23 @@ public class LdapConfig return createIfNeeded; } + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(); + sb.append(" Servers: "); + for (String server : servers) + { + sb.append(" [" + server + "]"); + } + sb.append(" initSize: " + initSize); + sb.append(" maxSize: " + maxSize); + sb.append(" policy: " + policy); + sb.append(" maxWait: " + maxWait); + sb.append(" createIfNeeded: " + createIfNeeded); + return sb.toString(); + } + @Override public boolean equals(Object other) { @@ -183,6 +201,7 @@ public class LdapConfig private LdapPool readOnlyPool = new LdapPool(); private LdapPool readWritePool = new LdapPool(); + private LdapPool unboundReadOnlyPool = new LdapPool(); private int port; private String usersDN; private String userRequestsDN; @@ -204,16 +223,15 @@ public class LdapConfig public static LdapConfig getLdapConfig() { - return getLdapConfig(CONFIG); + return loadLdapConfig(CONFIG); } - public static LdapConfig getLdapConfig(String ldapProperties) + public static LdapConfig loadLdapConfig(String ldapProperties) { logger.debug("Reading LDAP properties from: " + ldapProperties); PropertiesReader pr = new PropertiesReader(ldapProperties); MultiValuedProperties config = pr.getAllProperties(); - if (config == null || config.keySet() == null) { throw new RuntimeException("failed to read any LDAP property "); @@ -221,19 +239,9 @@ public class LdapConfig LdapConfig ldapConfig = new LdapConfig(); - ldapConfig.readOnlyPool.servers = getMultiProperty(pr, READONLY_PREFIX + POOL_SERVERS); - ldapConfig.readOnlyPool.initSize = Integer.valueOf(getProperty(pr, READONLY_PREFIX + POOL_INIT_SIZE)); - ldapConfig.readOnlyPool.maxSize = Integer.valueOf(getProperty(pr, READONLY_PREFIX + POOL_MAX_SIZE)); - ldapConfig.readOnlyPool.policy = PoolPolicy.valueOf(getProperty(pr, READONLY_PREFIX + POOL_POLICY)); - ldapConfig.readOnlyPool.maxWait = Long.valueOf(getProperty(pr, READONLY_PREFIX + MAX_WAIT)); - ldapConfig.readOnlyPool.createIfNeeded = Boolean.valueOf(getProperty(pr, READONLY_PREFIX + CREATE_IF_NEEDED)); - - ldapConfig.readWritePool.servers = getMultiProperty(pr, READWRITE_PREFIX + POOL_SERVERS); - ldapConfig.readWritePool.initSize = Integer.valueOf(getProperty(pr, READWRITE_PREFIX + POOL_INIT_SIZE)); - ldapConfig.readWritePool.maxSize = Integer.valueOf(getProperty(pr, READWRITE_PREFIX + POOL_MAX_SIZE)); - ldapConfig.readWritePool.policy = PoolPolicy.valueOf(getProperty(pr, READWRITE_PREFIX + POOL_POLICY)); - ldapConfig.readWritePool.maxWait = Long.valueOf(getProperty(pr, READONLY_PREFIX + MAX_WAIT)); - ldapConfig.readWritePool.createIfNeeded = Boolean.valueOf(getProperty(pr, READONLY_PREFIX + CREATE_IF_NEEDED)); + loadPoolConfig(ldapConfig.readOnlyPool, pr, READONLY_PREFIX); + loadPoolConfig(ldapConfig.readWritePool, pr, READWRITE_PREFIX); + loadPoolConfig(ldapConfig.unboundReadOnlyPool, pr, UB_READONLY_PREFIX); ldapConfig.dbrcHost = getProperty(pr, LDAP_DBRC_ENTRY); ldapConfig.port = Integer.valueOf(getProperty(pr, LDAP_PORT)); @@ -265,6 +273,16 @@ public class LdapConfig return ldapConfig; } + private static void loadPoolConfig(LdapPool pool, PropertiesReader pr, String prefix) + { + pool.servers = getMultiProperty(pr, prefix + POOL_SERVERS); + pool.initSize = Integer.valueOf(getProperty(pr, prefix + POOL_INIT_SIZE)); + pool.maxSize = Integer.valueOf(getProperty(pr, prefix + POOL_MAX_SIZE)); + pool.policy = PoolPolicy.valueOf(getProperty(pr, prefix + POOL_POLICY)); + pool.maxWait = Long.valueOf(getProperty(pr, prefix + MAX_WAIT)); + pool.createIfNeeded = Boolean.valueOf(getProperty(pr, prefix + CREATE_IF_NEEDED)); + } + private static String getProperty(PropertiesReader properties, String key) { String prop = properties.getFirstPropertyValue(key); @@ -321,6 +339,9 @@ public class LdapConfig if ( !(l.readWritePool.equals(readWritePool))) return false; + if ( !(l.unboundReadOnlyPool.equals(unboundReadOnlyPool))) + return false; + return true; } @@ -338,6 +359,11 @@ public class LdapConfig return readWritePool; } + public LdapPool getUnboundReadOnlyPool() + { + return unboundReadOnlyPool; + } + public String getUsersDN() { return this.usersDN; @@ -386,12 +412,13 @@ public class LdapConfig public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("ldap dbrc host = "); - sb.append(dbrcHost); - sb.append(" port = "); - sb.append(port); - sb.append(" proxyUserDN = "); - sb.append(proxyUserDN); + sb.append(" ReadOnlyPool: [" + readOnlyPool + "]"); + sb.append(" ReadWritePool: [" + readWritePool + "]"); + sb.append(" UnboundReadOnlyPool: [" + unboundReadOnlyPool + "]"); + sb.append(" Port: " + port); + sb.append(" dbrcHost: " + dbrcHost); + sb.append(" proxyUserDN: " + proxyUserDN); + return sb.toString(); } } diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapConnectionPool.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapConnectionPool.java index 3a41fff06b74d891d6fb20849e7f8884cfce2270..b17dfa6932eec9aaa91a0950a391650505630af9 100644 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapConnectionPool.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapConnectionPool.java @@ -81,7 +81,6 @@ import com.unboundid.ldap.sdk.LDAPConnection; import com.unboundid.ldap.sdk.LDAPConnectionOptions; import com.unboundid.ldap.sdk.LDAPConnectionPool; import com.unboundid.ldap.sdk.LDAPException; -import com.unboundid.ldap.sdk.LDAPReadWriteConnectionPool; import com.unboundid.ldap.sdk.RoundRobinServerSet; import com.unboundid.ldap.sdk.ServerSet; import com.unboundid.ldap.sdk.SimpleBindRequest; @@ -98,51 +97,50 @@ public class LdapConnectionPool { private static final Logger logger = Logger.getLogger(LdapConnectionPool.class); - private static final int POOL_CHECK_INTERVAL_MILLESCONDS = 10000; // 10 seconds - Profiler profiler = new Profiler(LdapConnectionPool.class); protected LdapConfig currentConfig; - private LDAPReadWriteConnectionPool pool; + private String poolName; + private LDAPConnectionPool pool; private Object poolMonitor = new Object(); private LDAPConnectionOptions connectionOptions; - private long lastPoolCheck = System.currentTimeMillis(); - - public LdapConnectionPool() - { - this(LdapConfig.getLdapConfig()); - } - - public LdapConnectionPool(LdapConfig config) + public LdapConnectionPool(LdapConfig config, LdapPool poolConfig, String poolName, boolean boundPool) { if (config == null) throw new IllegalArgumentException("config required"); + if (poolConfig == null) + throw new IllegalArgumentException("poolConfig required"); + if (poolName == null) + throw new IllegalArgumentException("poolName required"); connectionOptions = new LDAPConnectionOptions(); connectionOptions.setUseSynchronousMode(true); connectionOptions.setAutoReconnect(true); currentConfig = config; + this.poolName = poolName; synchronized (poolMonitor) { - pool = createPool(currentConfig); - profiler.checkpoint("Create pool"); + if (!boundPool) + pool = createPool(config, poolConfig, poolName, null, null); + else + pool = createPool(config, poolConfig, poolName, config.getAdminUserDN(), config.getAdminPasswd()); + logger.debug(poolName + " statistics after create:\n" + pool.getConnectionPoolStatistics()); + profiler.checkpoint("Create read only pool."); } } - public LDAPConnection getReadOnlyConnection() throws TransientException + public LDAPConnection getConnection() throws TransientException { - poolCheck(); - try { LDAPConnection conn = null; synchronized (poolMonitor) { - conn = pool.getReadConnection(); + conn = pool.getConnection(); } - logger.debug("Read pool statistics after borrow:\n" + pool.getReadPoolStatistics()); - profiler.checkpoint("get read only connection"); + logger.debug(poolName + " pool statistics after borrow:\n" + pool.getConnectionPoolStatistics()); + profiler.checkpoint("get " + poolName + " only connection"); conn.setConnectionOptions(connectionOptions); return conn; @@ -153,40 +151,10 @@ public class LdapConnectionPool } } - public LDAPConnection getReadWriteConnection() throws TransientException - { - poolCheck(); - - try - { - LDAPConnection conn = null; - synchronized (poolMonitor) - { - conn = pool.getWriteConnection(); - } - - logger.debug("write pool statistics after borrow:\n" + pool.getWritePoolStatistics()); - profiler.checkpoint("get read write connection"); - conn.setConnectionOptions(connectionOptions); - - return conn; - } - catch (LDAPException e) - { - throw new TransientException("Failed to get read write connection", e); - } - } - - public void releaseReadOnlyConnection(LDAPConnection conn) + public void releaseConnection(LDAPConnection conn) { - pool.releaseReadConnection(conn); - logger.debug("Read pool statistics after release:\n" + pool.getReadPoolStatistics()); - } - - public void releaseReadWriteConnection(LDAPConnection conn) - { - pool.releaseWriteConnection(conn); - logger.debug("write pool statistics after release:\n" + pool.getWritePoolStatistics()); + pool.releaseConnection(conn); + logger.debug(poolName + " pool statistics after release:\n" + pool.getConnectionPoolStatistics()); } public LdapConfig getCurrentConfig() @@ -196,9 +164,9 @@ public class LdapConnectionPool public void shutdown() { - logger.debug("Shutting down pool"); + logger.debug("Closing pool..."); pool.close(); - profiler.checkpoint("Shutdown pool"); + profiler.checkpoint("Pool closed."); } @Override @@ -209,104 +177,50 @@ public class LdapConnectionPool pool.close(); } - private void poolCheck() - { - if (timeToCheckPool()) - { - // check to see if the configuration has changed - logger.debug("checking for ldap config change"); - LdapConfig newConfig = LdapConfig.getLdapConfig(); - if (!newConfig.equals(currentConfig)) - { - logger.debug("Detected ldap configuration change, rebuilding pools"); - boolean poolRecreated = false; - final LDAPReadWriteConnectionPool oldPool = pool; - - synchronized (poolMonitor) - { - // check to see if another thread has already - // done the work - if (timeToCheckPool()) - { - this.currentConfig = newConfig; - pool = createPool(currentConfig); - profiler.checkpoint("Rebuild pool"); - lastPoolCheck = System.currentTimeMillis(); - poolRecreated = true; - } - } - - if (poolRecreated) - { - // close the old pool in a separate thread - Runnable closeOldPool = new Runnable() - { - public void run() - { - logger.debug("Closing old pool..."); - oldPool.close(); - logger.debug("Old pool closed."); - } - }; - Thread closePoolThread = new Thread(closeOldPool); - closePoolThread.start(); - } + private LDAPConnectionPool createPool(LdapConfig config, LdapPool poolConfig, String poolName, String bindID, String bindPW) - } - else - { - lastPoolCheck = System.currentTimeMillis(); - } - } - } - - private boolean timeToCheckPool() - { - return (System.currentTimeMillis() - lastPoolCheck) > POOL_CHECK_INTERVAL_MILLESCONDS; - } - - private LDAPReadWriteConnectionPool createPool(LdapConfig config) - { - LDAPConnectionPool ro = createPool(config.getReadOnlyPool(), config); - LDAPConnectionPool rw = createPool(config.getReadOnlyPool(), config); - LDAPReadWriteConnectionPool pool = new LDAPReadWriteConnectionPool(ro, rw); - logger.debug("Read pool statistics after create:\n" + pool.getReadPoolStatistics()); - logger.debug("Write pool statistics after create:\n" + pool.getWritePoolStatistics()); - return pool; - } - - private synchronized LDAPConnectionPool createPool(LdapPool pool, LdapConfig config) { try { logger.debug("LDAP Config: " + config); - String[] hosts = pool.getServers().toArray(new String[0]); - int[] ports = new int[pool.getServers().size()]; - for (int i=0; i<pool.getServers().size(); i++) + String[] hosts = poolConfig.getServers().toArray(new String[0]); + int[] ports = new int[poolConfig.getServers().size()]; + for (int i=0; i<poolConfig.getServers().size(); i++) { ports[i] = config.getPort(); } ServerSet serverSet = null; - if (pool.getPolicy().equals(PoolPolicy.roundRobin)) + if (poolConfig.getPolicy().equals(PoolPolicy.roundRobin)) { serverSet = new RoundRobinServerSet(hosts, ports, LdapDAO.getSocketFactory(config)); } - else if (pool.getPolicy().equals(PoolPolicy.fewestConnections)) + else if (poolConfig.getPolicy().equals(PoolPolicy.fewestConnections)) { serverSet = new FewestConnectionsServerSet(hosts, ports, LdapDAO.getSocketFactory(config)); } else { - throw new IllegalStateException("Unconfigured pool policy: " + pool.getPolicy()); + throw new IllegalStateException("Unconfigured pool policy: " + poolConfig.getPolicy()); } - SimpleBindRequest bindRequest = new SimpleBindRequest(config.getAdminUserDN(), config.getAdminPasswd()); + SimpleBindRequest bindRequest = null; + if (bindID != null && bindPW != null) + { + logger.debug("Binding pool as " + bindID); + bindRequest = new SimpleBindRequest(bindID, bindPW); + } + else + { + logger.debug("Binding pool annonymously"); + bindRequest = new SimpleBindRequest(); + } LDAPConnectionPool connectionPool = new LDAPConnectionPool( - serverSet, bindRequest, pool.getInitSize(), pool.getMaxSize()); + serverSet, bindRequest, poolConfig.getInitSize(), poolConfig.getMaxSize()); - connectionPool.setCreateIfNecessary(pool.getCreateIfNeeded()); - connectionPool.setMaxWaitTimeMillis(pool.getMaxWait()); + connectionPool.setCreateIfNecessary(poolConfig.getCreateIfNeeded()); + connectionPool.setMaxWaitTimeMillis(poolConfig.getMaxWait()); + connectionPool.setConnectionPoolName(poolName); return connectionPool; } diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapConnections.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapConnections.java index 93d579c55a2e670507e4ff048d8482acbb833f61..efe43639ca42ca78f975e6cdfa17248ad5106710 100644 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapConnections.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapConnections.java @@ -75,6 +75,7 @@ import ca.nrc.cadc.net.TransientException; import ca.nrc.cadc.profiler.Profiler; import com.unboundid.ldap.sdk.LDAPConnection; +import com.unboundid.ldap.sdk.LDAPConnectionPool; import com.unboundid.ldap.sdk.LDAPException; /** @@ -95,14 +96,19 @@ class LdapConnections Profiler profiler = new Profiler(LdapConnections.class); private LdapPersistence persistence; + private LdapConfig config; + + private LdapConnectionPool readOnlyPool; + private LdapConnectionPool readWritePool; + private LdapConnectionPool unboundReadOnlyPool; private LDAPConnection autoConfigReadOnlyConn; private LDAPConnection autoConfigReadWriteConn; - - private LdapConnectionPool pool; + private LDAPConnection autoConfigUnboundReadOnlyConn; private LDAPConnection manualConfigReadOnlyConn; private LDAPConnection manualConfigReadWriteConn; + private LDAPConnection manualConfigUnboundReadOnlyConn; LdapConnections(LdapPersistence persistence) { @@ -111,11 +117,12 @@ class LdapConnections this.persistence = persistence; } - LdapConnections(LdapConnectionPool pool) + LdapConnections(LdapConfig config) { - if (pool == null) - throw new RuntimeException("pool object is required"); - this.pool = pool; + if (config == null) + throw new RuntimeException("config object is required"); + + this.config = config; } LDAPConnection getReadOnlyConnection() throws TransientException @@ -125,7 +132,7 @@ class LdapConnections if (autoConfigReadOnlyConn == null) { log.debug("Getting new auto config read only connection."); - autoConfigReadOnlyConn = persistence.getReadOnlyConnection(); + autoConfigReadOnlyConn = persistence.getConnection(LdapPersistence.POOL_READONLY); profiler.checkpoint("Get read only connection"); } else @@ -136,10 +143,14 @@ class LdapConnections } else { + if (readOnlyPool == null) + { + readOnlyPool = new LdapConnectionPool(config, config.getReadOnlyPool(), LdapPersistence.POOL_READONLY, true); + } if (manualConfigReadOnlyConn == null) { log.debug("Getting new manual config read only connection."); - manualConfigReadOnlyConn = pool.getReadOnlyConnection(); + manualConfigReadOnlyConn = readOnlyPool.getConnection(); } else { @@ -156,7 +167,7 @@ class LdapConnections if (autoConfigReadWriteConn == null) { log.debug("Getting new auto config read write connection."); - autoConfigReadWriteConn = persistence.getReadWriteConnection(); + autoConfigReadWriteConn = persistence.getConnection(LdapPersistence.POOL_READWRITE); profiler.checkpoint("Get read write connection"); } else @@ -167,10 +178,14 @@ class LdapConnections } else { + if (readWritePool == null) + { + readWritePool = new LdapConnectionPool(config, config.getReadWritePool(), LdapPersistence.POOL_READWRITE, true); + } if (manualConfigReadWriteConn == null) { log.debug("Getting new manual config read write connection."); - manualConfigReadWriteConn = pool.getReadWriteConnection(); + manualConfigReadWriteConn = readWritePool.getConnection(); } else { @@ -180,66 +195,80 @@ class LdapConnections } } - void releaseConnections() + LDAPConnection getUnboundReadOnlyConnection() throws TransientException { if (persistence != null) { - if (autoConfigReadOnlyConn != null) + if (autoConfigUnboundReadOnlyConn == null) { - log.debug("Releasing read only auto config connection."); - persistence.releaseReadOnlyConnection(autoConfigReadOnlyConn); - profiler.checkpoint("Release read only connection"); + log.debug("Getting new auto config unbound read only connection."); + autoConfigUnboundReadOnlyConn = persistence.getConnection(LdapPersistence.POOL_UNBOUNDREADONLY); + profiler.checkpoint("Get read write connection"); } - if (autoConfigReadWriteConn != null) + else { - log.debug("Releasing read write auto config connection."); - persistence.releaseReadWriteConnection(autoConfigReadWriteConn); - profiler.checkpoint("Release read write connection"); + log.debug("Getting reused auto config unbound read only connection."); } + return autoConfigUnboundReadOnlyConn; } else { - if (manualConfigReadOnlyConn != null) + if (unboundReadOnlyPool == null) { - log.debug("Releasing read only manual config connection."); - pool.releaseReadOnlyConnection(manualConfigReadOnlyConn); + unboundReadOnlyPool = new LdapConnectionPool(config, config.getUnboundReadOnlyPool(), LdapPersistence.POOL_UNBOUNDREADONLY, false); } - if (manualConfigReadWriteConn != null) + if (manualConfigUnboundReadOnlyConn == null) { - log.debug("Releasing read write manual config connection."); - pool.releaseReadWriteConnection(manualConfigReadWriteConn); + log.debug("Getting new manual config unbound read only connection."); + manualConfigUnboundReadOnlyConn = unboundReadOnlyPool.getConnection(); + } + else + { + log.debug("Getting reused manual config unbound read only connection."); } + return manualConfigUnboundReadOnlyConn; } } - void releaseConnectionsAfterError() + void releaseConnections() { if (persistence != null) { if (autoConfigReadOnlyConn != null) { log.debug("Releasing read only auto config connection."); - persistence.releaseReadOnlyConnection(autoConfigReadOnlyConn); + persistence.releaseConnection(LdapPersistence.POOL_READONLY, autoConfigReadOnlyConn); profiler.checkpoint("Release read only connection"); } if (autoConfigReadWriteConn != null) { log.debug("Releasing read write auto config connection."); - persistence.releaseReadWriteConnection(autoConfigReadWriteConn); + persistence.releaseConnection(LdapPersistence.POOL_READWRITE, autoConfigReadWriteConn); profiler.checkpoint("Release read write connection"); } + if (autoConfigUnboundReadOnlyConn != null) + { + log.debug("Releasing read only auto config connection."); + persistence.releaseConnection(LdapPersistence.POOL_UNBOUNDREADONLY, autoConfigUnboundReadOnlyConn); + profiler.checkpoint("Release read only connection"); + } } else { if (manualConfigReadOnlyConn != null) { log.debug("Releasing read only manual config connection."); - pool.releaseReadOnlyConnection(manualConfigReadOnlyConn); + readOnlyPool.releaseConnection(manualConfigReadOnlyConn); } if (manualConfigReadWriteConn != null) { log.debug("Releasing read write manual config connection."); - pool.releaseReadWriteConnection(manualConfigReadWriteConn); + readWritePool.releaseConnection(manualConfigReadWriteConn); + } + if (manualConfigUnboundReadOnlyConn != null) + { + log.debug("Releasing read only manual config connection."); + unboundReadOnlyPool.releaseConnection(manualConfigUnboundReadOnlyConn); } } } @@ -250,11 +279,23 @@ class LdapConnections @Override public void finalize() { - if (pool != null) + if (readOnlyPool != null) { - log.debug("Closing manual config connection pool--should only see this " + + log.debug("Closing manual config readonly connection pool--should only see this " + "message when running unit tests."); - pool.shutdown(); + readOnlyPool.shutdown(); + } + if (readWritePool != null) + { + log.debug("Closing manual config readwrite connection pool--should only see this " + + "message when running unit tests."); + readWritePool.shutdown(); + } + if (unboundReadOnlyPool != null) + { + log.debug("Closing manual config unboundreadonly connection pool--should only see this " + + "message when running unit tests."); + unboundReadOnlyPool.shutdown(); } } @@ -263,8 +304,7 @@ class LdapConnections if (persistence != null) return persistence.getCurrentConfig(); else - return pool.getCurrentConfig(); - + return config; } } diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapDAO.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapDAO.java index 2c9d3080846f23c5f2a51ed81fed35f36f5cb563..98cf2297f9a15681fe4f9accadec345004a9a49d 100755 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapDAO.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapDAO.java @@ -109,6 +109,7 @@ public abstract class LdapDAO { this.connections = connections; config = connections.getCurrentConfig(); + logger.debug("New LdapDAO instance, config: " + config); } public LDAPConnection getReadOnlyConnection() throws TransientException @@ -121,6 +122,11 @@ public abstract class LdapDAO return connections.getReadWriteConnection(); } + public LDAPConnection getUnboundReadConnection() throws TransientException + { + return connections.getUnboundReadOnlyConnection(); + } + public void close() { connections.releaseConnections(); diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapPersistence.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapPersistence.java index 484c2ab483fdb948b5d6ccc09930450831520bb8..045e5a806871d4e7ada090bd81e8220665024edd 100644 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapPersistence.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapPersistence.java @@ -69,6 +69,9 @@ package ca.nrc.cadc.ac.server.ldap; +import java.util.HashMap; +import java.util.Map; + import javax.naming.InitialContext; import javax.naming.NameNotFoundException; import javax.naming.NamingException; @@ -76,8 +79,10 @@ import javax.naming.NamingException; import org.apache.log4j.Logger; import com.unboundid.ldap.sdk.LDAPConnection; +import com.unboundid.ldap.sdk.LDAPConnectionPool; import com.unboundid.ldap.sdk.LDAPException; +import ca.nrc.cadc.ac.server.ldap.LdapConfig.LdapPool; import ca.nrc.cadc.net.TransientException; import ca.nrc.cadc.profiler.Profiler; @@ -87,12 +92,20 @@ import ca.nrc.cadc.profiler.Profiler; */ public class LdapPersistence { + + // pool names + public static final String POOL_READONLY = "readOnly"; + public static final String POOL_READWRITE = "readWrite"; + public static final String POOL_UNBOUNDREADONLY = "unboundReadOnly"; + private static final Logger logger = Logger.getLogger(LdapPersistence.class); - private static final String LDAP_POOL_JNDI_NAME = LdapConnectionPool.class.getName(); + private static final String LDAP_POOL_JNDI_NAME = ConnectionPools.class.getName(); + private static final int POOL_CHECK_INTERVAL_MILLESCONDS = 10000; // 10 seconds Profiler profiler = new Profiler(LdapPersistence.class); - private LdapConnectionPool pool; + private long lastPoolCheck = System.currentTimeMillis(); + private ConnectionPools pools; // static monitor is required for when multiple LdapPersistence objects // are created. @@ -100,38 +113,31 @@ public class LdapPersistence LdapPersistence() { - initPool(); - } - - protected LDAPConnection getReadOnlyConnection() throws TransientException - { - return pool.getReadOnlyConnection(); - } - - protected LDAPConnection getReadWriteConnection() throws TransientException - { - return pool.getReadWriteConnection(); + initPools(); } - protected void releaseReadOnlyConnection(LDAPConnection conn) + protected LDAPConnection getConnection(String poolName) throws TransientException { - pool.releaseReadOnlyConnection(conn); + poolCheck(); + return pools.getPools().get(poolName).getConnection(); } - protected void releaseReadWriteConnection(LDAPConnection conn) + protected void releaseConnection(String poolName, LDAPConnection conn) { - pool.releaseReadWriteConnection(conn); + pools.getPools().get(poolName).releaseConnection(conn); } protected LdapConfig getCurrentConfig() { - return pool.currentConfig; + return pools.getConfig(); } protected void shutdown() { - // shutdown the pool - pool.shutdown(); + // shutdown the pools + pools.getPools().get(POOL_READONLY).shutdown(); + pools.getPools().get(POOL_READWRITE).shutdown(); + pools.getPools().get(POOL_UNBOUNDREADONLY).shutdown(); // unbind the pool try @@ -141,31 +147,31 @@ public class LdapPersistence } catch (NamingException e) { - logger.warn("Could not unbind ldap pool", e); + logger.warn("Could not unbind ldap pools", e); } } - private void initPool() + private void initPools() { try { - pool = lookupPool(); - logger.debug("Pool from JNDI lookup: " + pool); + pools = lookupPool(); + logger.debug("Pool from JNDI lookup: " + pools); - if (pool == null) + if (pools == null) { synchronized (jndiMonitor) { - pool = lookupPool(); - logger.debug("Pool from second JNDI lookup: " + pool); - if (pool == null) + pools = lookupPool(); + logger.debug("Pool from second JNDI lookup: " + pools); + if (pools == null) { - pool = new LdapConnectionPool(); - profiler.checkpoint("Created LDAP connection pool"); + LdapConfig config = LdapConfig.getLdapConfig(); + pools = createPools(config); InitialContext ic = new InitialContext(); - ic.bind(LDAP_POOL_JNDI_NAME, pool); - profiler.checkpoint("Bound LDAP pool to JNDI"); - logger.debug("Bound LDAP pool to JNDI"); + ic.bind(LDAP_POOL_JNDI_NAME, pools); + profiler.checkpoint("Bound LDAP pools to JNDI"); + logger.debug("Bound LDAP pools to JNDI"); } } } @@ -177,12 +183,25 @@ public class LdapPersistence } } - private LdapConnectionPool lookupPool() throws NamingException + private ConnectionPools createPools(LdapConfig config) + { + Map<String,LdapConnectionPool> poolMap = new HashMap<String,LdapConnectionPool>(3); + poolMap.put(POOL_READONLY, new LdapConnectionPool( + config, config.getReadOnlyPool(), POOL_READONLY, true)); + poolMap.put(POOL_READWRITE, new LdapConnectionPool( + config, config.getReadWritePool(), POOL_READWRITE, true)); + poolMap.put(POOL_UNBOUNDREADONLY, new LdapConnectionPool( + config, config.getUnboundReadOnlyPool(), POOL_UNBOUNDREADONLY, false)); + profiler.checkpoint("Created 3 LDAP connection pools"); + return new ConnectionPools(poolMap, config); + } + + private ConnectionPools lookupPool() throws NamingException { try { InitialContext ic = new InitialContext(); - return (LdapConnectionPool) ic.lookup(LDAP_POOL_JNDI_NAME); + return (ConnectionPools) ic.lookup(LDAP_POOL_JNDI_NAME); } catch (NameNotFoundException e) { @@ -190,4 +209,79 @@ public class LdapPersistence } } + private void poolCheck() throws TransientException + { + if (timeToCheckPool()) + { + // check to see if the configuration has changed + logger.debug("checking for ldap config change"); + LdapConfig newConfig = LdapConfig.getLdapConfig(); + if (!newConfig.equals(pools.getConfig())) + { + logger.debug("Detected ldap configuration change, rebuilding pools"); + boolean poolRecreated = false; + final ConnectionPools oldPools = pools; + + synchronized (jndiMonitor) + { + // check to see if another thread has already + // done the work + if (timeToCheckPool()) + { + try + { + ConnectionPools newPools = createPools(newConfig); + InitialContext ic = new InitialContext(); + try + { + ic.unbind(LDAP_POOL_JNDI_NAME); + } + catch (NamingException e) + { + logger.warn("Could not unbind previous JNDI instance", e); + } + ic.bind(LDAP_POOL_JNDI_NAME, pools); + profiler.checkpoint("Rebuild pools"); + lastPoolCheck = System.currentTimeMillis(); + pools = newPools; + poolRecreated = true; + } + catch (NamingException e) + { + logger.debug("JNDI Naming Exception: " + e.getMessage()); + throw new TransientException("JNDI Naming Exception", e); + } + } + } + + if (poolRecreated) + { + // close the old pool in a separate thread + Runnable closeOldPools = new Runnable() + { + public void run() + { + logger.debug("Closing old pools..."); + oldPools.getPools().get(POOL_READONLY).shutdown(); + oldPools.getPools().get(POOL_READWRITE).shutdown(); + oldPools.getPools().get(POOL_UNBOUNDREADONLY).shutdown(); + logger.debug("Old pools closed."); + } + }; + Thread closePoolsThread = new Thread(closeOldPools); + closePoolsThread.start(); + } + } + else + { + lastPoolCheck = System.currentTimeMillis(); + } + } + } + + private boolean timeToCheckPool() + { + return (System.currentTimeMillis() - lastPoolCheck) > POOL_CHECK_INTERVAL_MILLESCONDS; + } + } diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAO.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAO.java index 3940f5382b89cb503c3f38b2de1ce65304dcd0aa..414d1539849364204fc9f50525a5ae441de1ef45 100755 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAO.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAO.java @@ -213,11 +213,14 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO { BindRequest bindRequest = new SimpleBindRequest( getUserDN(username, config.getUsersDN()), password); - - String server = config.getReadOnlyPool().getServers().get(0); - int port = config.getPort(); - LDAPConnection conn = new LDAPConnection(LdapDAO.getSocketFactory(config), server, - config.getPort()); +// +// String server = config.getReadOnlyPool().getServers().get(0); +// int port = config.getPort(); +// LDAPConnection conn = new LDAPConnection(LdapDAO.getSocketFactory(config), server, +// config.getPort()); +// BindResult bindResult = conn.bind(bindRequest); + + LDAPConnection conn = this.getUnboundReadConnection(); BindResult bindResult = conn.bind(bindRequest); if (bindResult != null && bindResult.getResultCode() == ResultCode.SUCCESS) @@ -472,9 +475,10 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO } SearchResultEntry searchResult = null; + Filter filter = null; try { - Filter filter = Filter.createEqualityFilter(searchField, userID.getName()); + filter = Filter.createEqualityFilter(searchField, userID.getName()); logger.debug("search filter: " + filter); SearchRequest searchRequest = @@ -496,9 +500,26 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO if (searchResult == null) { - String msg = "User not found " + userID.toString(); - logger.debug(msg); - throw new UserNotFoundException(msg); + // determine if the user is not there of if the calling user + // doesn't have permission to see it + SearchRequest searchRequest = + new SearchRequest(usersDN, SearchScope.ONE, filter, userAttribs); + try + { + searchResult = getReadOnlyConnection().searchForEntry(searchRequest); + } + catch (LDAPException e) + { + LdapDAO.checkLdapResult(e.getResultCode()); + } + + if (searchResult == null) + { + String msg = "User not found " + userID.toString(); + logger.debug(msg); + throw new UserNotFoundException(msg); + } + throw new AccessControlException("Permission denied"); } User<T> user = new User<T>(userID); @@ -795,9 +816,10 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO new PasswordModifyExtendedRequest( userDN.toNormalizedString(), oldPassword, newPassword, controls); - String server = config.getReadWritePool().getServers().get(0); - int port = config.getPort(); - LDAPConnection conn = new LDAPConnection(LdapDAO.getSocketFactory(config), server, port); + LdapConfig ldapConfig = LdapConfig.getLdapConfig(); + String server = ldapConfig.getReadWritePool().getServers().get(0); + int port = ldapConfig.getPort(); + LDAPConnection conn = new LDAPConnection(LdapDAO.getSocketFactory(ldapConfig), server, port); PasswordModifyExtendedResult passwordModifyResult = (PasswordModifyExtendedResult) conn.processExtendedOperation(passwordModifyRequest); diff --git a/projects/cadcAccessControl-Server/test/LdapConfig.test.properties b/projects/cadcAccessControl-Server/test/LdapConfig.test.properties index f2d9b8ba536fc48563dd990c9621678edaa1571b..9b64724758556ec0e03cb3a716a052fb5a3622f3 100644 --- a/projects/cadcAccessControl-Server/test/LdapConfig.test.properties +++ b/projects/cadcAccessControl-Server/test/LdapConfig.test.properties @@ -19,6 +19,14 @@ readWrite.poolPolicy = roundRobin readWrite.maxWait = 30000 readWrite.createIfNeeded = false +# Unbound-Read-write connection pool +unboundReadOnly.servers = proc5-03.cadc.dao.nrc.ca +unboundReadOnly.poolInitSize = 1 +unboundReadOnly.poolMaxSize = 1 +unboundReadOnly.poolPolicy = roundRobin +unboundReadOnly.maxWait = 30000 +unboundReadOnly.createIfNeeded = false + # server configuration -- applies to all servers dbrcHost = devLdap port = 636 diff --git a/projects/cadcAccessControl-Server/test/config/testConfig1.properties b/projects/cadcAccessControl-Server/test/config/testConfig1.properties index b427f660db38b420ef89b256d11469f4b17ce954..130f087baee17061e35c408b69648943efffb899 100644 --- a/projects/cadcAccessControl-Server/test/config/testConfig1.properties +++ b/projects/cadcAccessControl-Server/test/config/testConfig1.properties @@ -21,6 +21,14 @@ readWrite.poolPolicy = fewestConnections readWrite.maxWait = 30000 readWrite.createIfNeeded = false +# Unbound-Read-only connection pool +unboundReadOnly.servers = server1 server2 server3 +unboundReadOnly.poolInitSize = 3 +unboundReadOnly.poolMaxSize = 8 +unboundReadOnly.poolPolicy = roundRobin +unboundReadOnly.maxWait = 30000 +unboundReadOnly.createIfNeeded = false + # server configuration -- applies to all servers dbrcHost = devLdap port = 389 diff --git a/projects/cadcAccessControl-Server/test/config/testConfig2.properties b/projects/cadcAccessControl-Server/test/config/testConfig2.properties index 32e494320625d42dbe8cd161309cc207ee612e9b..67c822c2fe523cca7e38e363a89f827e5a74ca6a 100644 --- a/projects/cadcAccessControl-Server/test/config/testConfig2.properties +++ b/projects/cadcAccessControl-Server/test/config/testConfig2.properties @@ -21,6 +21,14 @@ readWrite.poolPolicy = fewestConnections readWrite.maxWait = 30000 readWrite.createIfNeeded = false +# Unbound-Read-only connection pool +unboundReadOnly.servers = serverA serverB serverC +unboundReadOnly.poolInitSize = 0 +unboundReadOnly.poolMaxSize = 1 +unboundReadOnly.poolPolicy = fewestConnections +unboundReadOnly.maxWait = 30000 +unboundReadOnly.createIfNeeded = false + # server configuration -- applies to all servers dbrcHost = devLdap port = 389 diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/RequestValidatorTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/RequestValidatorTest.java index 87abcdac7c5d70b2aadf0aca0aba438ae04ecbdd..0b50c482739c15ae84a1862ca8930ad79a10f075 100644 --- a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/RequestValidatorTest.java +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/RequestValidatorTest.java @@ -70,7 +70,6 @@ package ca.nrc.cadc.ac.server; import ca.nrc.cadc.ac.Role; import ca.nrc.cadc.ac.server.web.groups.AddUserMemberActionTest; -import ca.nrc.cadc.auth.AuthenticationUtil; import ca.nrc.cadc.auth.IdentityType; import ca.nrc.cadc.util.Log4jInit; import ca.nrc.cadc.uws.Parameter; @@ -92,7 +91,7 @@ import static org.junit.Assert.*; public class RequestValidatorTest { private final static Logger log = Logger.getLogger(AddUserMemberActionTest.class); - + @BeforeClass public static void setUpClass() { @@ -106,16 +105,16 @@ public class RequestValidatorTest public void testValidate() { try - { + { RequestValidator rv = new RequestValidator(); - + try { rv.validate(null); fail("null parameter list should throw IllegalArgumentException"); } catch (IllegalArgumentException ignore) {} - + List<Parameter> paramList = new ArrayList<Parameter>(); try { @@ -123,7 +122,7 @@ public class RequestValidatorTest fail("empty parameter list should throw IllegalArgumentException"); } catch (IllegalArgumentException ignore) {} - + paramList.add(new Parameter("IDTYPE", "idtype")); paramList.add(new Parameter("ROLE", "role")); try @@ -132,7 +131,7 @@ public class RequestValidatorTest fail("missing ID parameter should throw IllegalArgumentException"); } catch (IllegalArgumentException ignore) {} - + paramList.clear(); paramList.add(new Parameter("ID", "foo")); paramList.add(new Parameter("ROLE", "role")); @@ -142,7 +141,7 @@ public class RequestValidatorTest fail("missing IDTYPE parameter should throw IllegalArgumentException"); } catch (IllegalArgumentException ignore) {} - + paramList.clear(); paramList.add(new Parameter("ID", "foo")); paramList.add(new Parameter("IDTYPE", "idtype")); @@ -152,7 +151,7 @@ public class RequestValidatorTest fail("missing ROLE parameter should throw IllegalArgumentException"); } catch (IllegalArgumentException ignore) {} - + paramList.clear(); paramList.add(new Parameter("ID", "foo")); paramList.add(new Parameter("IDTYPE", IdentityType.USERNAME.getValue())); @@ -163,7 +162,7 @@ public class RequestValidatorTest fail("invalid ROLE parameter should throw IllegalArgumentException"); } catch (IllegalArgumentException ignore) {} - + paramList.clear(); paramList.add(new Parameter("ID", "foo")); paramList.add(new Parameter("IDTYPE", IdentityType.USERNAME.getValue())); @@ -175,20 +174,20 @@ public class RequestValidatorTest fail("empty GROUPID parameter value should throw IllegalArgumentException"); } catch (IllegalArgumentException ignore) {} - + paramList.clear(); paramList.add(new Parameter("ID", "foo")); paramList.add(new Parameter("IDTYPE", IdentityType.USERNAME.getValue())); paramList.add(new Parameter("ROLE", Role.MEMBER.getValue())); rv.validate(paramList); - + assertNotNull(rv.getPrincipal()); assertNotNull(rv.getRole()); assertNull(rv.getGroupID()); - + paramList.add(new Parameter("GROUPID", "bar")); rv.validate(paramList); - + assertNotNull(rv.getPrincipal()); assertNotNull(rv.getRole()); assertNotNull(rv.getGroupID()); @@ -199,5 +198,5 @@ public class RequestValidatorTest fail("unexpected error: " + t.getMessage()); } } - + } diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/AbstractLdapDAOTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/AbstractLdapDAOTest.java index 5801981ac380b8f2314d4b321952cd86d15789ea..361fdd4fdff8de3c692a0eda21ab4b193272f7ef 100644 --- a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/AbstractLdapDAOTest.java +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/AbstractLdapDAOTest.java @@ -76,7 +76,7 @@ public class AbstractLdapDAOTest static protected LdapConfig getLdapConfig() { - return LdapConfig.getLdapConfig(CONFIG); + return LdapConfig.loadLdapConfig(CONFIG); } } diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapConfigTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapConfigTest.java index 32085f9ce85a0d65fb0299a6831768801e3dbd8a..2602442019ec617c1b11835c08b1625d7b0061ca 100644 --- a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapConfigTest.java +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapConfigTest.java @@ -98,7 +98,7 @@ public class LdapConfigTest { System.setProperty(PropertiesReader.class.getName() + ".dir", "test/config"); - LdapConfig c = LdapConfig.getLdapConfig("testConfig1.properties"); + LdapConfig c = LdapConfig.loadLdapConfig("testConfig1.properties"); Assert.assertEquals("devLdap", c.getDbrcHost()); Assert.assertEquals(389, c.getPort()); Assert.assertEquals("uid=testproxy,ou=SpecialUsers,dc=testcanfar", c.getProxyUserDN()); @@ -139,7 +139,7 @@ public class LdapConfigTest { System.setProperty(PropertiesReader.class.getName() + ".dir", "test/config"); - LdapConfig c = LdapConfig.getLdapConfig("testConfig2.properties"); + LdapConfig c = LdapConfig.loadLdapConfig("testConfig2.properties"); Assert.assertEquals("devLdap", c.getDbrcHost()); Assert.assertEquals(389, c.getPort()); Assert.assertEquals("uid=testproxy,ou=SpecialUsers,dc=testcanfar", c.getProxyUserDN()); @@ -180,8 +180,8 @@ public class LdapConfigTest { System.setProperty(PropertiesReader.class.getName() + ".dir", "test/config"); - LdapConfig c1 = LdapConfig.getLdapConfig("testConfig1.properties"); - LdapConfig c2 = LdapConfig.getLdapConfig("testConfig1.properties"); + LdapConfig c1 = LdapConfig.loadLdapConfig("testConfig1.properties"); + LdapConfig c2 = LdapConfig.loadLdapConfig("testConfig1.properties"); Assert.assertEquals(c1, c2); } catch (Throwable t) @@ -202,8 +202,8 @@ public class LdapConfigTest { System.setProperty(PropertiesReader.class.getName() + ".dir", "test/config"); - LdapConfig c1 = LdapConfig.getLdapConfig("testConfig2.properties"); - LdapConfig c2 = LdapConfig.getLdapConfig("testConfig2.properties"); + LdapConfig c1 = LdapConfig.loadLdapConfig("testConfig2.properties"); + LdapConfig c2 = LdapConfig.loadLdapConfig("testConfig2.properties"); Assert.assertEquals(c1, c2); } catch (Throwable t) @@ -224,8 +224,8 @@ public class LdapConfigTest { System.setProperty(PropertiesReader.class.getName() + ".dir", "test/config"); - LdapConfig c1 = LdapConfig.getLdapConfig("testConfig1.properties"); - LdapConfig c2 = LdapConfig.getLdapConfig("testConfig2.properties"); + LdapConfig c1 = LdapConfig.loadLdapConfig("testConfig1.properties"); + LdapConfig c2 = LdapConfig.loadLdapConfig("testConfig2.properties"); Assert.assertTrue(!c1.equals(c2)); } catch (Throwable t) diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapConnectionsTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapConnectionsTest.java index 5be2dedf121c0a0ff54e572e4a52256d5ad12c71..ef287d7dd11f8bbb7cfe24935fdacda00aefa9af 100644 --- a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapConnectionsTest.java +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapConnectionsTest.java @@ -97,16 +97,21 @@ public class LdapConnectionsTest { LDAPConnection readConn = new LDAPConnection(); LDAPConnection writeConn = new LDAPConnection(); + LDAPConnection unReadConn = new LDAPConnection(); LdapPersistence persistence = EasyMock.createMock(LdapPersistence.class); - EasyMock.expect(persistence.getReadOnlyConnection()).andReturn(readConn).once(); - EasyMock.expect(persistence.getReadWriteConnection()).andReturn(writeConn).once(); + EasyMock.expect(persistence.getConnection(LdapPersistence.POOL_READONLY)).andReturn(readConn).once(); + EasyMock.expect(persistence.getConnection(LdapPersistence.POOL_READWRITE)).andReturn(writeConn).once(); + EasyMock.expect(persistence.getConnection(LdapPersistence.POOL_UNBOUNDREADONLY)).andReturn(unReadConn).once(); EasyMock.expect(persistence.getCurrentConfig()).andReturn(null).once(); - persistence.releaseReadOnlyConnection(readConn); + persistence.releaseConnection(LdapPersistence.POOL_READONLY, readConn); EasyMock.expectLastCall().once(); - persistence.releaseReadWriteConnection(writeConn); + persistence.releaseConnection(LdapPersistence.POOL_READWRITE, writeConn); + EasyMock.expectLastCall().once(); + + persistence.releaseConnection(LdapPersistence.POOL_UNBOUNDREADONLY, unReadConn); EasyMock.expectLastCall().once(); EasyMock.replay(persistence); @@ -122,57 +127,15 @@ public class LdapConnectionsTest connections.getReadWriteConnection(); connections.getReadWriteConnection(); - connections.getCurrentConfig(); - - connections.releaseConnections(); - - EasyMock.verify(persistence); - - } - catch (Exception e) - { - log.error("Unexpected exception", e); - Assert.fail("Unexpected exception"); - } - } - - @Test - public void testManualConfig() - { - try - { - LDAPConnection readConn = new LDAPConnection(); - LDAPConnection writeConn = new LDAPConnection(); - LdapConnectionPool pool = EasyMock.createMock(LdapConnectionPool.class); - - EasyMock.expect(pool.getReadOnlyConnection()).andReturn(readConn).once(); - EasyMock.expect(pool.getReadWriteConnection()).andReturn(writeConn).once(); - EasyMock.expect(pool.getCurrentConfig()).andReturn(null).once(); - - pool.releaseReadOnlyConnection(readConn); - EasyMock.expectLastCall().once(); - - pool.releaseReadWriteConnection(writeConn); - EasyMock.expectLastCall().once(); - - EasyMock.replay(pool); - - LdapConnections connections = new LdapConnections(pool); - - // multiple calls to get connections should only go to the pool once - connections.getReadOnlyConnection(); - connections.getReadOnlyConnection(); - connections.getReadOnlyConnection(); - - connections.getReadWriteConnection(); - connections.getReadWriteConnection(); - connections.getReadWriteConnection(); + connections.getUnboundReadOnlyConnection(); + connections.getUnboundReadOnlyConnection(); + connections.getUnboundReadOnlyConnection(); connections.getCurrentConfig(); connections.releaseConnections(); - EasyMock.verify(pool); + EasyMock.verify(persistence); } catch (Exception e) diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapDAOTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapDAOTest.java index 3ab3c073f4f4401154dada9c05caeafe7820cd97..f2df46ef4b392aa38d19427bcc83d2caba314f00 100644 --- a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapDAOTest.java +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapDAOTest.java @@ -117,8 +117,7 @@ public class LdapDAOTest extends AbstractLdapDAOTest subject.getPrincipals().add(httpPrincipal); - LdapConnectionPool pool = new LdapConnectionPool(config); - LdapConnections connections = new LdapConnections(pool); + LdapConnections connections = new LdapConnections(config); final LdapDAOTestImpl ldapDao = new LdapDAOTestImpl(connections); Subject.doAs(subject, new PrivilegedExceptionAction<Object>() @@ -191,9 +190,8 @@ public class LdapDAOTest extends AbstractLdapDAOTest subject.getPrincipals().add(new X500Principal("uid=foo,o=bar")); subject.getPrincipals().add(dnPrincipal); - LdapConfig config = LdapConfig.getLdapConfig("LdapConfig.test.properties"); - LdapConnectionPool pool = new LdapConnectionPool(config); - LdapConnections conn = new LdapConnections(pool); + LdapConfig config = LdapConfig.loadLdapConfig("LdapConfig.test.properties"); + LdapConnections conn = new LdapConnections(config); final LdapDAO ldapDAO = new LdapDAO(conn) { }; // abstract DN actual = Subject.doAs(subject, new PrivilegedAction<DN>() diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAOTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAOTest.java index f559a730ec1a77c3f7a4c5e07b48bbb3501f40be..e67fa02bf086c2bc0c1af69061093e02a0172010 100644 --- a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAOTest.java +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapGroupDAOTest.java @@ -164,8 +164,7 @@ public class LdapGroupDAOTest extends AbstractLdapDAOTest LdapGroupDAO<X500Principal> getGroupDAO() throws Exception { - LdapConnectionPool pool = new LdapConnectionPool(config); - LdapConnections connections = new LdapConnections(pool); + LdapConnections connections = new LdapConnections(config); return new LdapGroupDAO<X500Principal>(connections, new LdapUserDAO<X500Principal>(connections)); } diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAOTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAOTest.java index 86249c43c143b83815870691bd4e622970dea81a..df58629d3c93b3d6de4251b3c2cb8712f3032035 100644 --- a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAOTest.java +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/ldap/LdapUserDAOTest.java @@ -162,8 +162,7 @@ public class LdapUserDAOTest extends AbstractLdapDAOTest <T extends Principal> LdapUserDAO<T> getUserDAO() throws Exception { - LdapConnectionPool pool = new LdapConnectionPool(config); - LdapConnections connections = new LdapConnections(pool); + LdapConnections connections = new LdapConnections(config); return new LdapUserDAO(connections){ protected int genNextNumericId() {