--- /usr/local/src/cvs/shibboleth/java/src/edu/internet2/middleware/shibboleth/aa/attrresolv/provider/JDBCDataConnector.java 2005-07-14 10:25:45.000000000 -0700 +++ /usr/local/tomcat/webapps/shibboleth/WEB-INF/classes/edu/washington/UWJDBCDataConnector.java 2005-07-18 15:54:14.000000000 -0700 @@ -1,4 +1,15 @@ /* + * University of Washington, JDBC data connector + * by Fox + * from JDBCDataConnector + * + * This is for the tgtid database + * + * 1 - allow multiple databases, try each until success + * + */ + +/* * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.] * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,7 +25,15 @@ * limitations under the License. */ -package edu.internet2.middleware.shibboleth.aa.attrresolv.provider; +/** Modified for UW by Fox + * + * Allow use of "Requester" string + * Allow update of DB + * Try successive DBs until get response (redundant DBs) + * + **/ + +package edu.washington; import java.io.PrintWriter; import java.lang.reflect.Constructor; @@ -56,6 +75,7 @@ import edu.internet2.middleware.shibboleth.aa.attrresolv.Dependencies; import edu.internet2.middleware.shibboleth.aa.attrresolv.ResolutionPlugInException; import edu.internet2.middleware.shibboleth.aa.attrresolv.ResolverAttribute; +import edu.internet2.middleware.shibboleth.aa.attrresolv.provider.*; /* * Built at the Canada Institute for Scientific and Technical Information (CISTI @@ -73,17 +93,18 @@ * @author Scott Cantor */ -public class JDBCDataConnector extends BaseDataConnector implements DataConnectorPlugIn { +public class UWJDBCDataConnector extends BaseDataConnector implements DataConnectorPlugIn { private static Logger log = Logger.getLogger(JDBCDataConnector.class.getName()); protected String searchVal; protected int minResultSet = 0, maxResultSet = 0, retryInterval = 300; protected long deadSince = 0; - protected DataSource dataSource; + // protected DataSource dataSource; protected JDBCAttributeExtractor extractor; protected JDBCStatementCreator statementCreator; + protected ArrayList dataSources; - public JDBCDataConnector(Element e) throws ResolutionPlugInException { + public UWJDBCDataConnector(Element e) throws ResolutionPlugInException { super(e); @@ -165,19 +186,29 @@ } catch (NumberFormatException ex) { log.error("Malformed pooling limits: using defaults."); } - if (e.getAttribute("dbURL") == null || e.getAttribute("dbURL").equals("")) { - log.error("JDBC connection requires a dbURL property"); - throw new ResolutionPlugInException("JDBCDataConnection requires a \"dbURL\" property"); - } - setupDataSource(e.getAttribute("dbURL"), props, maxActive, maxIdle, maxWait, validationQuery); + + // Get data sources + dataSources = new ArrayList(); + for (int i=0;i<10;i++) { + if (e.getAttribute("dbURL" + i) != null ) { + DataSource dataSource = setupDataSource(e.getAttribute("dbURL"+i), props, maxActive, maxIdle, maxWait, validationQuery); + dataSources.add(dataSource); + } + } + if (dataSources.size() == 0) { + log.error("UW JDBC connection requires at least one dbURL? property"); + throw new ResolutionPlugInException("UWJDBCDataConnection requires least one \"dbURL?\" property"); + } + } /** * Initialize a Pooling Data Source */ - private void setupDataSource(String dbURL, Properties props, int maxActive, int maxIdle, int maxWait, + private DataSource setupDataSource(String dbURL, Properties props, int maxActive, int maxIdle, int maxWait, String validationQuery) throws ResolutionPlugInException { + DataSource src; GenericObjectPool objectPool = new GenericObjectPool(null); objectPool.setMaxActive(maxActive); @@ -202,19 +233,20 @@ try { poolConnFactory = new PoolableConnectionFactory(connFactory, objectPool, new StackKeyedObjectPoolFactory(), - validationQuery, true, true); + validationQuery, false, true); } catch (Exception ex) { log.debug("Poolable connection factory error"); } - dataSource = new PoolingDataSource(objectPool); + src = new PoolingDataSource(objectPool); log.info("Data Source initialized."); try { - dataSource.setLogWriter(new Log4jPrintWriter(Logger.getLogger(JDBCDataConnector.class.getName() + ".Pool"), + src.setLogWriter(new Log4jPrintWriter(Logger.getLogger(JDBCDataConnector.class.getName() + ".Pool"), Priority.DEBUG)); } catch (SQLException e) { log.error("Coudn't setup logger for database connection pool."); } + return src; } /** @@ -295,7 +327,10 @@ public Attributes resolve(Principal principal, String requester, String responder, Dependencies depends) throws ResolutionPlugInException { - log.debug("Resolving connector: (" + getId() + ")"); + Attributes retattr; + int lds = dataSources.size() - 1; + + log.debug("Resolving UW connector: (" + getId() + ")"); // Are we alive? boolean alive = true; @@ -309,10 +344,15 @@ } if (!alive) { - log.info("JDBC Connector (" + getId() + ") is dead, returning immediately"); - throw new ResolutionPlugInException("Connection is dead"); + log.info("UW JDBC Connector (" + getId() + ") all dead"); + throw new ResolutionPlugInException("Connections are dead"); } + // loop on connectors + for (int ds=0;ds<=lds;ds++) { + log.debug("UW Connector (" + getId() + ") try " + ds ); + DataSource dataSource = (DataSource) dataSources.get(ds); + // Retrieve a connection from the connection pool Connection conn = null; try { @@ -320,15 +360,17 @@ log.debug("Connection retrieved from pool"); } catch (Exception e) { synchronized (this) { - deadSince = now; + if (ds==lds) deadSince = now; // mark dead only if all are dead } - log.error("JDBC Connector (" + getId() + ") unable to fetch a connection from the pool, marking it dead"); - throw new ResolutionPlugInException("Unable to fetch a connection from the pool, marking it dead: " + log.error("UW JDBC Connector (" + getId() + ") unable to fetch a connection from the pool"); + if (ds " + (columnValue != null ? columnValue.toString() : "(null)")); } + if (columnValue == null) return null; if (row == 0) { BasicAttribute ba = new BasicAttribute(columnName, true); ba.add(row, columnValue); @@ -791,6 +852,7 @@ Attribute attribute = attributes.get(attributeName); if (attribute == null || attribute.size() < 1) { + log.debug("Processing attribute: " + attributeName); if (attributeName.equalsIgnoreCase("%REQUESTER%")) { try { setSpecificParameter(preparedStatement, valueIndex, requester);