package org.cagrid.gts.service.impl; import gov.nih.nci.cagrid.common.Utils; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Statement; import java.util.ArrayList; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.cagrid.core.common.FaultHelper; import org.cagrid.gts.model.AuthorityGTS; import org.cagrid.gts.model.AuthorityPrioritySpecification; import org.cagrid.gts.model.AuthorityPriorityUpdate; import org.cagrid.gts.model.TimeToLive; import org.cagrid.gts.service.exception.GTSInternalException; import org.cagrid.gts.service.exception.IllegalAuthorityException; import org.cagrid.gts.service.exception.InvalidAuthorityException; import org.cagrid.gts.service.impl.db.AuthorityTable; import org.cagrid.gts.service.impl.db.DBManager; import org.cagrid.gts.wsrf.stubs.AddAuthorityRequest; /** * @author <A href="mailto:langella@bmi.osu.edu">Stephen Langella </A> * @author <A href="mailto:oster@bmi.osu.edu">Scott Oster </A> * @author <A href="mailto:hastings@bmi.osu.edu">Shannon Hastings </A> * @version $Id: ArgumentManagerTable.java,v 1.2 2004/10/15 16:35:16 langella Exp $ */ public class GTSAuthorityManager { private Log log; private boolean dbBuilt = false; private Database db; private DBManager dbManager; private String gtsURI; private AuthoritySyncTime syncTime; public GTSAuthorityManager(String gtsURI, AuthoritySyncTime syncTime, DBManager dbManager) { log = LogFactory.getLog(this.getClass().getName()); this.dbManager = dbManager; this.db = dbManager.getDatabase(); this.gtsURI = gtsURI; this.syncTime = syncTime; } public synchronized AuthorityGTS getAuthority(String gtsURI) throws GTSInternalException, InvalidAuthorityException { this.buildDatabase(); Connection c = null; PreparedStatement s = null; ResultSet rs = null; try { c = db.getConnection(); s = c.prepareStatement("select * from " + AuthorityTable.TABLE_NAME + " where " + AuthorityTable.GTS_URI + "= ?"); s.setString(1, gtsURI); rs = s.executeQuery(); AuthorityGTS gts = null; if (rs.next()) { gts = new AuthorityGTS(); gts.setServiceURI(rs.getString(AuthorityTable.GTS_URI)); gts.setPerformAuthorization(rs.getBoolean(AuthorityTable.PERFORM_AUTH)); gts.setPriority(rs.getInt(AuthorityTable.PRIORITY)); gts.setServiceIdentity(Utils.clean(rs.getString(AuthorityTable.GTS_IDENTITY))); gts.setSyncTrustLevels(rs.getBoolean(AuthorityTable.SYNC_TRUST_LEVELS)); TimeToLive ttl = new TimeToLive(); ttl.setHours(rs.getInt(AuthorityTable.TTL_HOURS)); ttl.setMinutes(rs.getInt(AuthorityTable.TTL_MINUTES)); ttl.setSeconds(rs.getInt(AuthorityTable.TTL_SECONDS)); gts.setTimeToLive(ttl); } if(gts != null){ return gts; } } catch (Exception e) { this.log.fatal("Unexpected database error incurred in obtaining the authority, " + gtsURI + ", the following statement generated the error: \n", e); GTSInternalException fault = FaultHelper.createFaultException(GTSInternalException.class, "Unexpected error obtaining the authority " + gtsURI); throw fault; } finally { if (rs != null) { try { rs.close(); } catch (Exception e) { log.error(e.getMessage(), e); } } if (s != null) { try { s.close(); } catch (Exception e) { log.error(e.getMessage(), e); } } try { db.releaseConnection(c); } catch (Exception exception) { this.log.error(exception.getMessage(), exception); } } InvalidAuthorityException fault = FaultHelper.createFaultException(InvalidAuthorityException.class, "The authority " + gtsURI + " does not exist."); throw fault; } public synchronized void updateAuthorityPriorities(AuthorityPriorityUpdate update) throws GTSInternalException, IllegalAuthorityException { AuthorityGTS[] auths = this.getAuthorities(); // Create HashMap Map<String, AuthorityGTS> map = new HashMap<String, AuthorityGTS>(); for (int i = 0; i < auths.length; i++) { map.put(auths[i].getServiceURI(), auths[i]); } // Verfiy that all authorities are accounted for List<AuthorityPrioritySpecification> specs = update.getAuthorityPrioritySpecification(); for (AuthorityPrioritySpecification spec : specs) { map.remove(spec.getServiceURI()); } if (map.size() > 0) { StringBuffer error = new StringBuffer(); error.append("Cannot update the authority priorities, an incomplete authority list was provided.\n The provided list was missing the following authorities:\n"); Iterator<String> itr = map.keySet().iterator(); while (itr.hasNext()) { error.append((String) itr.next() + "\n"); } IllegalAuthorityException fault = FaultHelper.createFaultException(IllegalAuthorityException.class, error.toString()); throw fault; } // Validate priorities int count = this.getAuthorityCount(); for (int i = 1; i <= count; i++) { int found = 0; for (int j = 0; j < specs.size(); j++) { if (i == specs.get(j).getPriority()) { found = found + 1; } } if (found < 1) { IllegalAuthorityException fault = FaultHelper.createFaultException(IllegalAuthorityException.class, "Cannot update the authority priorities, no authority specified with the priority " + i + ", each authority must be assigned a unique priority between 1 and " + count + "!!!"); throw fault; } else if (found > 1) { IllegalAuthorityException fault = FaultHelper.createFaultException(IllegalAuthorityException.class, "Cannot update the authority priorities, multiple authorities specified with the priority " + i + ", each authority must be assigned a unique priority between 1 and " + count + "!!!"); throw fault; } } Connection c = null; try { c = db.getConnection(); c.setAutoCommit(false); for (int i = 0; i < specs.size(); i++) { updateAuthorityPriority(c, specs.get(i).getServiceURI(), specs.get(i).getPriority()); } c.commit(); } catch (Exception e) { if (c != null) { try { c.rollback(); } catch (Exception ex) { ex.printStackTrace(); } } this.log.error("Unexpected database error incurred in updating the authority priorities!!!", e); GTSInternalException fault = FaultHelper.createFaultException(GTSInternalException.class, "Unexpected error in updating the authority priorities!!!"); throw fault; } finally { try { if (c != null) { c.setAutoCommit(true); } } catch (Exception e) { } try { db.releaseConnection(c); } catch (Exception exception) { this.log.error(exception.getMessage(), exception); } } } protected synchronized void updateAuthorityPriority(Connection c, String uri, int priority) throws GTSInternalException, InvalidAuthorityException { this.buildDatabase(); if (!doesAuthorityExist(uri)) { } else { PreparedStatement update = null; try { update = c.prepareStatement("UPDATE " + AuthorityTable.TABLE_NAME + " SET " + AuthorityTable.PRIORITY + " = ? WHERE " + AuthorityTable.GTS_URI + " = ?"); update.setInt(1, priority); update.setString(2, uri); update.executeUpdate(); } catch (Exception e) { this.log.error("Unexpected database error incurred in updating the priority for the authority, " + uri + ".", e); GTSInternalException fault = FaultHelper.createFaultException(GTSInternalException.class, "Unexpected error occurred in updating the priority for the authority, " + uri + "."); throw fault; }finally { if (update != null) { try { update.close(); } catch (Exception e) { log.error(e.getMessage(), e); } } } } } public synchronized void updateAuthority(AuthorityGTS gts) throws GTSInternalException, IllegalAuthorityException, InvalidAuthorityException { this.buildDatabase(); if (Utils.clean(gts.getServiceURI()) == null) { IllegalAuthorityException fault = FaultHelper.createFaultException(IllegalAuthorityException.class, "The Authority cannot be updated, no service URI specified!!!"); throw fault; } validateTimeToLive(gts.getTimeToLive()); if ((gts.isPerformAuthorization()) && (Utils.clean(gts.getServiceIdentity()) == null)) { IllegalAuthorityException fault = FaultHelper.createFaultException(IllegalAuthorityException.class, "The Authority, " + gts.getServiceURI() + " cannot be updated, when authorization is required a service identity must be specified!!!"); throw fault; } AuthorityGTS curr = getAuthority(gts.getServiceURI()); if (curr.getPriority() != gts.getPriority()) { IllegalAuthorityException fault = FaultHelper.createFaultException(IllegalAuthorityException.class, "The Authority, " + gts.getServiceURI() + " cannot be updated, priorities cannot be updated using this method, use the update priorities method!!!"); throw fault; } Connection c = null; PreparedStatement update = null; try { c = db.getConnection(); if (!gts.equals(curr)) { update = c.prepareStatement("UPDATE " + AuthorityTable.TABLE_NAME + " SET " + AuthorityTable.PRIORITY + " = ?, " + AuthorityTable.SYNC_TRUST_LEVELS + " = ?, " + AuthorityTable.TTL_HOURS + " = ?, " + AuthorityTable.TTL_MINUTES + " = ?, " + AuthorityTable.TTL_SECONDS + " = ?, " + AuthorityTable.PERFORM_AUTH + " = ?, " + AuthorityTable.GTS_IDENTITY + " = ? WHERE " + AuthorityTable.GTS_URI + " = ?"); update.setInt(1, gts.getPriority()); update.setString(2, String.valueOf(gts.isSyncTrustLevels())); update.setInt(3, gts.getTimeToLive().getHours()); update.setInt(4, gts.getTimeToLive().getMinutes()); update.setInt(5, gts.getTimeToLive().getSeconds()); update.setString(6, String.valueOf(gts.isPerformAuthorization())); update.setString(7, gts.getServiceIdentity()); update.setString(8, gts.getServiceURI()); update.executeUpdate(); } } catch (Exception e) { this.log.error("Unexpected database error incurred in updating the authority " + gts.getServiceURI() + "!!!", e); GTSInternalException fault = FaultHelper.createFaultException(GTSInternalException.class, "Unexpected error in updating the authority " + gts.getServiceURI() + "!!!"); throw fault; } finally { if (update != null) { try { update.close(); } catch (Exception e) { log.error(e.getMessage(), e); } } try { db.releaseConnection(c); } catch (Exception exception) { this.log.error(exception.getMessage(), exception); } } } private synchronized AuthorityGTS[] getAuthoritiesEqualToOrAfter(int priority) throws GTSInternalException { this.buildDatabase(); Connection c = null; PreparedStatement s = null; ResultSet rs = null; List<String> list = new ArrayList<String>(); try { c = db.getConnection(); s = c.prepareStatement("select " + AuthorityTable.GTS_URI + " from " + AuthorityTable.TABLE_NAME + " WHERE " + AuthorityTable.PRIORITY + ">= ? ORDER BY " + AuthorityTable.PRIORITY + ""); s.setInt(1, priority); rs = s.executeQuery(); while (rs.next()) { list.add(rs.getString(AuthorityTable.GTS_URI)); } AuthorityGTS[] gts = new AuthorityGTS[list.size()]; for (int i = 0; i < gts.length; i++) { String uri = (String) list.get(i); gts[i] = this.getAuthority(uri); } return gts; } catch (Exception e) { this.log.error("Unexpected database error incurred in getting the authorities, the following statement generated the error: \n", e); GTSInternalException fault = FaultHelper.createFaultException(GTSInternalException.class, "Unexpected error occurred in getting the authorities."); throw fault; } finally { if (rs != null) { try { rs.close(); } catch (Exception e) { log.error(e.getMessage(), e); } } if (s != null) { try { s.close(); } catch (Exception e) { log.error(e.getMessage(), e); } } try { db.releaseConnection(c); } catch (Exception exception) { this.log.error(exception.getMessage(), exception); } } } public synchronized AuthorityGTS[] getAuthorities() throws GTSInternalException { this.buildDatabase(); Connection c = null; Statement s = null; ResultSet rs = null; List<String> list = new ArrayList<String>(); StringBuffer sql = new StringBuffer(); try { c = db.getConnection(); s = c.createStatement(); sql.append("select " + AuthorityTable.GTS_URI + " from " + AuthorityTable.TABLE_NAME + " ORDER BY " + AuthorityTable.PRIORITY + ""); rs = s.executeQuery(sql.toString()); while (rs.next()) { list.add(rs.getString(AuthorityTable.GTS_URI)); } AuthorityGTS[] gts = new AuthorityGTS[list.size()]; for (int i = 0; i < gts.length; i++) { String uri = (String) list.get(i); gts[i] = this.getAuthority(uri); } return gts; } catch (Exception e) { this.log.error("Unexpected database error incurred in getting the authorities, the following statement generated the error: \n" + sql.toString() + "\n", e); GTSInternalException fault = FaultHelper.createFaultException(GTSInternalException.class, "Unexpected error occurred in getting the authorities."); throw fault; } finally { if (rs != null) { try { rs.close(); } catch (Exception e) { log.error(e.getMessage(), e); } } if (s != null) { try { s.close(); } catch (Exception e) { log.error(e.getMessage(), e); } } try { db.releaseConnection(c); } catch (Exception exception) { this.log.error(exception.getMessage(), exception); } } } public synchronized int getAuthorityCount() throws GTSInternalException { this.buildDatabase(); Connection c = null; Statement s = null; ResultSet rs = null; StringBuffer sql = new StringBuffer(); try { c = db.getConnection(); s = c.createStatement(); sql.append("select COUNT(*) from " + AuthorityTable.TABLE_NAME); rs = s.executeQuery(sql.toString()); int count = 0; if (rs.next()) { count = rs.getInt(1); } return count; } catch (Exception e) { this.log.error( "Unexpected database error incurred in getting the authority count, the following statement generated the error: \n" + sql.toString() + "\n", e); GTSInternalException fault = FaultHelper.createFaultException(GTSInternalException.class, "Unexpected error occurred in getting the authority count."); throw fault; } finally { if (rs != null) { try { rs.close(); } catch (Exception e) { log.error(e.getMessage(), e); } } if (s != null) { try { s.close(); } catch (Exception e) { log.error(e.getMessage(), e); } } db.releaseConnection(c); } } public synchronized void addAuthority(AuthorityGTS gts) throws GTSInternalException, IllegalAuthorityException { this.buildDatabase(); if (Utils.clean(gts.getServiceURI()) == null) { IllegalAuthorityException fault = FaultHelper.createFaultException(IllegalAuthorityException.class, "The Authority cannot be added, no service URI specified!!!"); throw fault; } if (gts.getServiceURI().equals(gtsURI)) { IllegalAuthorityException fault = FaultHelper.createFaultException(IllegalAuthorityException.class, "The Authority cannot be added, a GTS cannot be its own authority!!!"); throw fault; } validateTimeToLive(gts.getTimeToLive()); if ((gts.isPerformAuthorization()) && (Utils.clean(gts.getServiceIdentity()) == null)) { IllegalAuthorityException fault = FaultHelper.createFaultException(IllegalAuthorityException.class, "The Authority, " + gts.getServiceURI() + " cannot be added, when authorization is required a service identity must be specified!!!"); throw fault; } if (doesAuthorityExist(gts.getServiceURI())) { IllegalAuthorityException fault = FaultHelper.createFaultException(IllegalAuthorityException.class, "The Authority, " + gts.getServiceURI() + " cannot be added, it already exists!!!"); throw fault; } // Validate the Priority (greater than 1 and not more than the count) int count = this.getAuthorityCount() + 1; if ((gts.getPriority() < 1) || (gts.getPriority() > count)) { IllegalAuthorityException fault = FaultHelper.createFaultException(IllegalAuthorityException.class, "The Authority, " + gts.getServiceURI() + " cannot be added, invalid priority specified the priority must be between 1 and " + count + "!!!"); throw fault; } Connection c = null; PreparedStatement insert = null; try { c = db.getConnection(); c.setAutoCommit(false); // Get the current list of Authorities AuthorityGTS[] list = this.getAuthoritiesEqualToOrAfter(gts.getPriority()); for (int i = 0; i < list.length; i++) { this.updateAuthorityPriority(c, list[i].getServiceURI(), (list[i].getPriority() + 1)); } insert = c.prepareStatement("INSERT INTO " + AuthorityTable.TABLE_NAME + " SET " + AuthorityTable.GTS_URI + " = ?, " + AuthorityTable.PRIORITY + " = ?, " + AuthorityTable.SYNC_TRUST_LEVELS + " = ?, " + AuthorityTable.TTL_HOURS + " = ?, " + AuthorityTable.TTL_MINUTES + " = ?, " + AuthorityTable.TTL_SECONDS + " = ?, " + AuthorityTable.PERFORM_AUTH + " = ?, " + AuthorityTable.GTS_IDENTITY + " = ?"); insert.setString(1, gts.getServiceURI()); insert.setInt(2, gts.getPriority()); insert.setString(3, String.valueOf(gts.isSyncTrustLevels())); insert.setInt(4, gts.getTimeToLive().getHours()); insert.setInt(5, gts.getTimeToLive().getMinutes()); insert.setInt(6, gts.getTimeToLive().getSeconds()); insert.setString(7, String.valueOf(gts.isPerformAuthorization())); insert.setString(8, gts.getServiceIdentity()); insert.executeUpdate(); c.commit(); } catch (Exception e) { if (c != null) { try { c.rollback(); } catch (Exception ex) { ex.printStackTrace(); } } this.log.error("Unexpected database error incurred in adding the authority " + gts.getServiceURI() + "!!!", e); GTSInternalException fault = FaultHelper.createFaultException(GTSInternalException.class, "Unexpected error in adding the authority " + gts.getServiceURI() + "!!!"); throw fault; } finally { try { if (c != null) { c.setAutoCommit(true); } } catch (Exception e) { } if (insert != null) { try { insert.close(); } catch (Exception e) { log.error(e.getMessage(), e); } } db.releaseConnection(c); } } public synchronized void removeAuthority(String uri) throws GTSInternalException, InvalidAuthorityException { this.buildDatabase(); AuthorityGTS gts = getAuthority(uri); Connection c = null; PreparedStatement s = null; try { c = db.getConnection(); c.setAutoCommit(false); // Get the current list of Authorities AuthorityGTS[] list = this.getAuthoritiesEqualToOrAfter(gts.getPriority()); for (int i = 0; i < list.length; i++) { this.updateAuthorityPriority(c, list[i].getServiceURI(), (list[i].getPriority() - 1)); } s = c.prepareStatement("DELETE FROM " + AuthorityTable.TABLE_NAME + " WHERE " + AuthorityTable.GTS_URI + " = ?"); s.setString(1, uri); s.executeUpdate(); c.commit(); } catch (Exception e) { if (c != null) { try { c.rollback(); } catch (Exception ex) { ex.printStackTrace(); } } this.log.error("Unexpected database error incurred in deleting the authority " + uri + "!!!", e); GTSInternalException fault = FaultHelper.createFaultException(GTSInternalException.class, "Unexpected error in deleting the authority " + uri + "!!!"); throw fault; } finally { try { if (c != null) { c.setAutoCommit(true); } } catch (Exception e) { } if (s != null) { try { s.close(); } catch (Exception e) { log.error(e.getMessage(), e); } } db.releaseConnection(c); } } public synchronized boolean doesAuthorityExist(String gtsURI) throws GTSInternalException { this.buildDatabase(); Connection c = null; PreparedStatement s = null; boolean exists = false; try { c = db.getConnection(); s = c.prepareStatement("select count(*) from " + AuthorityTable.TABLE_NAME + " where " + AuthorityTable.GTS_URI + "= ?"); s.setString(1, gtsURI); ResultSet rs = s.executeQuery(); if (rs.next()) { int count = rs.getInt(1); if (count > 0) { exists = true; } } rs.close(); s.close(); } catch (Exception e) { this.log.error("Unexpected database error incurred in determining if the Authority GTS " + gtsURI + " exists, the following statement generated the error: \n", e); GTSInternalException fault = FaultHelper.createFaultException(GTSInternalException.class, "Unexpected error in determining if the Authority GTS " + gtsURI + " exists."); throw fault; } finally { if (s != null) { try { s.close(); } catch (Exception e) { log.error(e.getMessage(), e); } } db.releaseConnection(c); } return exists; } public synchronized void clearDatabase() throws GTSInternalException { try { this.buildDatabase(); db.update("delete FROM " + AuthorityTable.TABLE_NAME); } catch (Exception e) { this.log.error("Unexpected error in destroying the database.", e); GTSInternalException fault = FaultHelper.createFaultException(GTSInternalException.class, "Unexpected error in destroying the database."); throw fault; } } public synchronized void buildDatabase() throws GTSInternalException { if (!dbBuilt) { try { db.createDatabase(); if (!this.db.tableExists(AuthorityTable.TABLE_NAME)) { String trust = dbManager.getAuthorityTable().getCreateTableSQL(); db.update(trust); } dbBuilt = true; } catch (Exception e) { this.log.error("Unexpected error in creating the database.", e); GTSInternalException fault = FaultHelper.createFaultException(GTSInternalException.class, "Unexpected error in creating the database."); throw fault; } } } private void validateTimeToLive(TimeToLive ttl) throws IllegalAuthorityException { if (ttl == null) { IllegalAuthorityException fault = FaultHelper.createFaultException(IllegalAuthorityException.class, "The Authority cannot be added, no time to live specified!!!"); throw fault; } if (syncTime != null) { Calendar c = new GregorianCalendar(); Calendar c2 = new GregorianCalendar(); c2.setTimeInMillis(c.getTimeInMillis()); c.add(Calendar.HOUR, syncTime.getHours()); c.add(Calendar.MINUTE, syncTime.getMinutes()); c.add(Calendar.SECOND, syncTime.getSeconds()); c2.add(Calendar.HOUR, ttl.getHours()); c2.add(Calendar.MINUTE, ttl.getMinutes()); c2.add(Calendar.SECOND, ttl.getSeconds()); if (c2.before(c)) { IllegalAuthorityException fault = FaultHelper.createFaultException(IllegalAuthorityException.class, "The time to live (" + ttl.getHours() + " hour(s), " + ttl.getMinutes() + " minute(s), and " + ttl.getSeconds() + " second(s)" + "), is shorter than how often the GTS syncs with its authorities.\n The gts syncs withs authorities every " + syncTime.getHours() + " hour(s), " + syncTime.getMinutes() + " minute(s), and " + syncTime.getSeconds() + " second(s)."); throw fault; } } else { IllegalAuthorityException fault = FaultHelper.createFaultException(IllegalAuthorityException.class, "The Authority cannot be added, this GTS is not configured to sync with authorities!!!"); throw fault; } } }