package org.deegree.security.drm; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.StringReader; import java.sql.Clob; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; import java.sql.Types; import java.util.ArrayList; import java.util.Properties; import oracle.jdbc.OracleConnection; import oracle.sql.CLOB; import org.deegree.framework.log.ILogger; import org.deegree.framework.log.LoggerFactory; import org.deegree.framework.util.DataBaseIDGenerator; import org.deegree.framework.util.StringTools; import org.deegree.framework.xml.XMLTools; import org.deegree.io.DBConnectionPool; import org.deegree.io.IDGeneratorFactory; import org.deegree.model.filterencoding.AbstractFilter; import org.deegree.model.filterencoding.ComplexFilter; import org.deegree.model.filterencoding.Filter; import org.deegree.model.filterencoding.FilterConstructionException; import org.deegree.security.GeneralSecurityException; import org.deegree.security.drm.model.Group; import org.deegree.security.drm.model.Privilege; import org.deegree.security.drm.model.Right; import org.deegree.security.drm.model.RightType; import org.deegree.security.drm.model.Role; import org.deegree.security.drm.model.SecurableObject; import org.deegree.security.drm.model.SecuredObject; import org.deegree.security.drm.model.User; import org.w3c.dom.Document; import org.w3c.dom.Element; /** * This is an implementation of a <code>Registry</code> using an SQL-Database (via JDBC) as * backend. * * @author <a href="mailto:mschneider@lat-lon.de">Markus Schneider </a> * @version $Revision: 1.23 $ */ public final class SQLRegistry implements SecurityRegistry { private static final ILogger LOG = LoggerFactory.getLogger( SQLRegistry.class ); private String dbDriver; private String dbName; private String dbUser; private String dbPassword; /** Exclusive connection for a transaction (only one at a time). */ private Connection transactionalConnection = null; public void clean( SecurityTransaction transaction ) throws GeneralSecurityException { PreparedStatement pstmt = null; try { BufferedReader reader = new BufferedReader( new InputStreamReader( SQLRegistry.class .getResourceAsStream( "clean.sql" ) ) ); StringBuffer sb = new StringBuffer( 5000 ); String line = null; while (( line = reader.readLine() ) != null) { sb.append( line ); } String tmp = sb.toString(); String[] commands = StringTools.toArray( tmp, ";", false ); for (int i = 0; i < commands.length; i++) { String command = commands[i].trim(); if ( !command.equals( "" ) ) { pstmt = transactionalConnection.prepareStatement( command ); pstmt.executeUpdate(); closeStatement( pstmt ); pstmt = null; } } } catch (SQLException e) { LOG.logError( e.getMessage(), e ); closeStatement( pstmt ); abortTransaction( transaction ); throw new GeneralSecurityException( "SQLRegistry.clean() failed. Rollback performed. " + "Error message: " + e.getMessage() ); } catch (IOException e) { LOG.logError( e.getMessage(), e ); throw new GeneralSecurityException( "SQLRegistry.clean() failed. Problem reading sql command file. " + "Error message: " + e.getMessage() ); } } /** * Adds a new user account to the <code>Registry</code>. * * @param transaction * @param name * @throws GeneralSecurityException * this is a <code>DuplicateException</code> if the group already existed */ public User registerUser( SecurityTransaction transaction, String name, String password, String lastName, String firstName, String emailAddress ) throws GeneralSecurityException { try { getUserByName( transaction, name ); throw new DuplicateException( "Registration of user '" + name + "' failed! A user with " + "this name already exists." ); } catch (UnknownException e) { } User user = new User( getID( transaction, "SEC_SECURABLE_OBJECTS" ), name, password, firstName, lastName, emailAddress, this ); PreparedStatement pstmt = null; try { pstmt = transactionalConnection .prepareStatement( "INSERT INTO SEC_SECURABLE_OBJECTS (ID,NAME,TITLE) VALUES (?,?,?)" ); pstmt.setInt( 1, user.getID() ); pstmt.setString( 2, user.getName() ); pstmt.setString( 3, user.getTitle() ); pstmt.executeUpdate(); closeStatement( pstmt ); pstmt = null; pstmt = transactionalConnection .prepareStatement( "INSERT INTO SEC_USERS (ID,PASSWORD,FIRSTNAME,LASTNAME,EMAIL) VALUES (?,?,?,?,?)" ); pstmt.setInt( 1, user.getID() ); pstmt.setString( 2, password ); pstmt.setString( 3, user.getFirstName() ); pstmt.setString( 4, user.getLastName() ); pstmt.setString( 5, user.getEmailAddress() ); pstmt.executeUpdate(); closeStatement( pstmt ); } catch (SQLException e) { LOG.logError( e.getMessage(), e ); closeStatement( pstmt ); abortTransaction( transaction ); throw new GeneralSecurityException( "SQLRegistry.registerUser() failed. Rollback performed. " + "Error message: " + e.getMessage() ); } return user; } /** * Removes an existing <code>User<code> from the <code>Registry</code> * (including its relations). * * @param transaction * @param user * @throws GeneralSecurityException */ public void deregisterUser( SecurityTransaction transaction, User user ) throws GeneralSecurityException { PreparedStatement pstmt = null; try { pstmt = transactionalConnection .prepareStatement( "DELETE FROM SEC_JT_USERS_GROUPS WHERE FK_USERS=?" ); pstmt.setInt( 1, user.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; pstmt = transactionalConnection .prepareStatement( "DELETE FROM SEC_JT_USERS_ROLES WHERE FK_USERS=?" ); pstmt.setInt( 1, user.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; pstmt = transactionalConnection.prepareStatement( "DELETE FROM SEC_USERS WHERE ID=?" ); pstmt.setInt( 1, user.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; pstmt = transactionalConnection .prepareStatement( "DELETE FROM SEC_JT_ROLES_SECOBJECTS WHERE FK_SECURABLE_OBJECTS=?" ); pstmt.setInt( 1, user.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; pstmt = transactionalConnection .prepareStatement( "DELETE FROM SEC_SECURABLE_OBJECTS WHERE ID=?" ); pstmt.setInt( 1, user.getID() ); pstmt.executeUpdate(); pstmt.close(); } catch (SQLException e) { LOG.logError( e.getMessage(), e ); closeStatement( pstmt ); abortTransaction( transaction ); throw new GeneralSecurityException( "SQLRegistry.deregisterUser() failed. Rollback performed. " + "Error message: " + e.getMessage() ); } } /** * Updates the metadata (name, email, etc.) of a <code>User</code> in the * <code>Registry</code>. * * @throws GeneralSecurityException * this is a <code>DuplicateException</code> if a user with the new name already * existed */ public void updateUser( SecurityTransaction transaction, User user ) throws GeneralSecurityException { PreparedStatement pstmt = null; try { pstmt = transactionalConnection .prepareStatement( "UPDATE SEC_SECURABLE_OBJECTS SET NAME=?,TITLE=? WHERE ID=?" ); pstmt.setString( 1, user.getName() ); pstmt.setString( 2, user.getTitle() ); pstmt.setInt( 3, user.getID() ); pstmt.executeUpdate(); closeStatement( pstmt ); pstmt = null; pstmt = transactionalConnection .prepareStatement( "UPDATE SEC_USERS SET PASSWORD=?,FIRSTNAME=?,LASTNAME=?,EMAIL=? WHERE ID=?" ); pstmt.setString( 1, user.getPassword() ); pstmt.setString( 2, user.getFirstName() ); pstmt.setString( 3, user.getLastName() ); pstmt.setString( 4, user.getEmailAddress() ); pstmt.setInt( 5, user.getID() ); pstmt.executeUpdate(); closeStatement( pstmt ); } catch (SQLException e) { LOG.logError( e.getMessage(), e ); closeStatement( pstmt ); abortTransaction( transaction ); throw new GeneralSecurityException( "SQLRegistry.registerUser() failed. Rollback performed. " + "Error message: " + e.getMessage() ); } } /** * Retrieves a <code>User</code> from the <code>Registry</code>. * * @param securityAccess * @param name * @throws GeneralSecurityException * this is an <code>UnknownException</code> if the user is not known to the * <code>Registry</code> * */ public User getUserByName( SecurityAccess securityAccess, String name ) throws GeneralSecurityException { User user = null; Connection con = acquireLocalConnection( securityAccess ); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = con .prepareStatement( "SELECT SEC_USERS.ID,SEC_USERS.PASSWORD,SEC_USERS.FIRSTNAME,SEC_USERS.LASTNAME,SEC_USERS.EMAIL " + "FROM SEC_USERS,SEC_SECURABLE_OBJECTS " + "WHERE SEC_USERS.ID=SEC_SECURABLE_OBJECTS.ID AND " + "SEC_SECURABLE_OBJECTS.NAME=?" ); pstmt.setString( 1, name ); rs = pstmt.executeQuery(); if ( rs.next() ) { user = new User( rs.getInt( 1 ), name, rs.getString( 2 ), rs.getString( 3 ), rs .getString( 4 ), rs.getString( 5 ), this ); } else { throw new UnknownException( "Lookup of user '" + name + "' failed! A user with this name does not exist." ); } } catch (SQLException e) { LOG.logError( e.getMessage(), e ); throw new GeneralSecurityException( e ); } finally { closeResultSet( rs ); closeStatement( pstmt ); releaseLocalConnection( securityAccess, con ); } return user; } /** * Retrieves a <code>User</code> from the <code>Registry</code>. * * @param securityAccess * @param id * @throws GeneralSecurityException * this is an <code>UnknownException</code> if the user is not known to the * <code>Registry</code> */ public User getUserById( SecurityAccess securityAccess, int id ) throws GeneralSecurityException { User user = null; Connection con = acquireLocalConnection( securityAccess ); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = con.prepareStatement( "SELECT SEC_SECURABLE_OBJECTS.NAME," + "SEC_USERS.PASSWORD,SEC_USERS.FIRSTNAME,SEC_USERS.LASTNAME," + "SEC_USERS.EMAIL FROM SEC_USERS,SEC_SECURABLE_OBJECTS " + "WHERE SEC_SECURABLE_OBJECTS.ID=? AND SEC_USERS.ID=SEC_SECURABLE_OBJECTS.ID" ); pstmt.setInt( 1, id ); rs = pstmt.executeQuery(); if ( rs.next() ) { user = new User( id, rs.getString( 1 ), rs.getString( 2 ), rs.getString( 3 ), rs .getString( 4 ), rs.getString( 5 ), this ); } else { throw new UnknownException( "Lookup of user with id: " + id + " failed! A user with this id does not exist." ); } } catch (SQLException e) { throw new GeneralSecurityException( e ); } finally { closeResultSet( rs ); closeStatement( pstmt ); releaseLocalConnection( securityAccess, con ); } return user; } /** * Retrieves all <code>User</code> s from the <code>Registry</code>. * * @param securityAccess * @throws GeneralSecurityException */ public User[] getAllUsers( SecurityAccess securityAccess ) throws GeneralSecurityException { ArrayList users = new ArrayList(); Connection con = acquireLocalConnection( securityAccess ); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = con .prepareStatement( "SELECT SEC_USERS.ID,SEC_SECURABLE_OBJECTS.NAME,SEC_USERS.PASSWORD,SEC_USERS.FIRSTNAME,SEC_USERS.LASTNAME,SEC_USERS.EMAIL " + "FROM SEC_USERS,SEC_SECURABLE_OBJECTS " + "WHERE SEC_USERS.ID=SEC_SECURABLE_OBJECTS.ID" ); rs = pstmt.executeQuery(); while (rs.next()) { users.add( new User( rs.getInt( 1 ), rs.getString( 2 ), rs.getString( 3 ), rs .getString( 4 ), rs.getString( 5 ), rs.getString( 6 ), this ) ); } } catch (SQLException e) { LOG.logError( e.getMessage(), e ); throw new GeneralSecurityException( e ); } finally { closeResultSet( rs ); closeStatement( pstmt ); releaseLocalConnection( securityAccess, con ); } return (User[]) users.toArray( new User[users.size()] ); } /** * Retrieves all <code>Users</code> s from the <code>Registry</code> that are associated * DIRECTLY (i.e. not via group memberships) with a given <code>Role</code>. * * @param securityAccess * @param role * @throws GeneralSecurityException */ public User[] getUsersWithRole( SecurityAccess securityAccess, Role role ) throws GeneralSecurityException { ArrayList users = new ArrayList(); Connection con = acquireLocalConnection( securityAccess ); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = con .prepareStatement( "SELECT SEC_USERS.ID,SEC_SECURABLE_OBJECTS.NAME,SEC_USERS.PASSWORD,SEC_USERS.FIRSTNAME,SEC_USERS.LASTNAME," + "SEC_USERS.EMAIL " + "FROM SEC_USERS,SEC_SECURABLE_OBJECTS,SEC_JT_USERS_ROLES " + "WHERE SEC_SECURABLE_OBJECTS.ID=SEC_USERS.ID AND SEC_JT_USERS_ROLES.FK_USERS=SEC_USERS.ID" + " AND SEC_JT_USERS_ROLES.FK_ROLES=?" ); pstmt.setInt( 1, role.getID() ); rs = pstmt.executeQuery(); while (rs.next()) { users.add( new User( rs.getInt( 1 ), rs.getString( 2 ), rs.getString( 3 ), rs .getString( 4 ), rs.getString( 5 ), rs.getString( 6 ), this ) ); } } catch (SQLException e) { LOG.logError( e.getMessage(), e ); throw new GeneralSecurityException( e ); } finally { closeResultSet( rs ); closeStatement( pstmt ); releaseLocalConnection( securityAccess, con ); } return (User[]) users.toArray( new User[users.size()] ); } /** * Retrieves all <code>User</code> s from the <code>Registry</code> that belong to the given * <code>Group</code> DIRECTLY (i.e. not via inheritance). * * @param securityAccess * @param group * @throws GeneralSecurityException */ public User[] getUsersInGroup( SecurityAccess securityAccess, Group group ) throws GeneralSecurityException { ArrayList users = new ArrayList(); Connection con = acquireLocalConnection( securityAccess ); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = con .prepareStatement( "SELECT SEC_USERS.ID,SEC_SECURABLE_OBJECTS.NAME,SEC_USERS.PASSWORD,SEC_USERS.FIRSTNAME,SEC_USERS.LASTNAME," + "SEC_USERS.EMAIL " + "FROM SEC_USERS,SEC_SECURABLE_OBJECTS,SEC_JT_USERS_GROUPS " + "WHERE SEC_SECURABLE_OBJECTS.ID=SEC_USERS.ID AND SEC_JT_USERS_GROUPS.FK_USERS=SEC_USERS.ID" + " AND SEC_JT_USERS_GROUPS.FK_GROUPS=?" ); pstmt.setInt( 1, group.getID() ); rs = pstmt.executeQuery(); while (rs.next()) { users.add( new User( rs.getInt( 1 ), rs.getString( 2 ), rs.getString( 3 ), rs .getString( 4 ), rs.getString( 5 ), rs.getString( 6 ), this ) ); } } catch (SQLException e) { LOG.logError( e.getMessage(), e ); throw new GeneralSecurityException( e ); } finally { closeResultSet( rs ); closeStatement( pstmt ); releaseLocalConnection( securityAccess, con ); } return (User[]) users.toArray( new User[users.size()] ); } /** * Adds a new group account to the <code>Registry</code>. * * * @param transaction * @param name * @throws GeneralSecurityException * this is a <code>DuplicateException</code> if the group already existed */ public Group registerGroup( SecurityTransaction transaction, String name, String title ) throws GeneralSecurityException { try { getGroupByName( transaction, name ); throw new DuplicateException( "Registration of group '" + name + "' failed! A group with " + "this name already exists." ); } catch (UnknownException e) { } Group group = new Group( getID( transaction, "SEC_SECURABLE_OBJECTS" ), name, title, this ); PreparedStatement pstmt = null; try { pstmt = transactionalConnection .prepareStatement( "INSERT INTO SEC_SECURABLE_OBJECTS (ID,NAME,TITLE) VALUES (?,?,?)" ); pstmt.setInt( 1, group.getID() ); pstmt.setString( 2, group.getName() ); pstmt.setString( 3, group.getTitle() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; pstmt = transactionalConnection .prepareStatement( "INSERT INTO SEC_GROUPS (ID) VALUES (?)" ); pstmt.setInt( 1, group.getID() ); pstmt.executeUpdate(); pstmt.close(); } catch (SQLException e) { LOG.logError( e.getMessage(), e ); closeStatement( pstmt ); abortTransaction( transaction ); throw new GeneralSecurityException( "SQLRegistry.registerGroup() failed. Rollback performed. " + "Error message: " + e.getMessage() ); } return group; } /** * Removes an existing <code>Group</code> from the <code>Registry</code> (including its * relations). * * @param transaction * @param group * @throws GeneralSecurityException */ public void deregisterGroup( SecurityTransaction transaction, Group group ) throws GeneralSecurityException { PreparedStatement pstmt = null; try { pstmt = transactionalConnection .prepareStatement( "DELETE FROM SEC_JT_USERS_GROUPS WHERE FK_GROUPS=?" ); pstmt.setInt( 1, group.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; pstmt = transactionalConnection .prepareStatement( "DELETE FROM SEC_JT_GROUPS_GROUPS WHERE FK_GROUPS=? OR FK_GROUPS_MEMBER=?" ); pstmt.setInt( 1, group.getID() ); pstmt.setInt( 2, group.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; pstmt = transactionalConnection .prepareStatement( "DELETE FROM SEC_JT_GROUPS_ROLES WHERE FK_GROUPS=?" ); pstmt.setInt( 1, group.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; pstmt = transactionalConnection.prepareStatement( "DELETE FROM SEC_GROUPS WHERE ID=?" ); pstmt.setInt( 1, group.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; pstmt = transactionalConnection .prepareStatement( "DELETE FROM SEC_JT_ROLES_SECOBJECTS WHERE FK_SECURABLE_OBJECTS=?" ); pstmt.setInt( 1, group.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; pstmt = transactionalConnection .prepareStatement( "DELETE FROM SEC_SECURABLE_OBJECTS WHERE ID=?" ); pstmt.setInt( 1, group.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; } catch (SQLException e) { LOG.logError( e.getMessage(), e ); closeStatement( pstmt ); abortTransaction( transaction ); throw new GeneralSecurityException( "SQLRegistry.deregisterGroup() failed. Rollback performed. " + "Error message: " + e.getMessage() ); } } /** * Retrieves a <code>Group</code> from the <code>Registry</code>. * * @param securityAccess * @param name * @throws GeneralSecurityException * this is an <code>UnknownException</code> if the group is not known to the * <code>Registry</code> */ public Group getGroupByName( SecurityAccess securityAccess, String name ) throws GeneralSecurityException { Group group = null; Connection con = acquireLocalConnection( securityAccess ); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = con.prepareStatement( "SELECT SEC_GROUPS.ID,SEC_SECURABLE_OBJECTS.TITLE " + "FROM SEC_GROUPS,SEC_SECURABLE_OBJECTS " + "WHERE SEC_GROUPS.ID=SEC_SECURABLE_OBJECTS.ID AND " + "SEC_SECURABLE_OBJECTS.NAME=?" ); pstmt.setString( 1, name ); rs = pstmt.executeQuery(); if ( rs.next() ) { group = new Group( rs.getInt( 1 ), name, rs.getString( 2 ), this ); } else { throw new UnknownException( "Lookup of group '" + name + "' failed! A group with this name does not exist." ); } } catch (SQLException e) { LOG.logError( e.getMessage(), e ); throw new GeneralSecurityException( e ); } finally { closeResultSet( rs ); closeStatement( pstmt ); releaseLocalConnection( securityAccess, con ); } return group; } /** * Retrieves a <code>Group</code> from the <code>Registry</code>. * * @param securityAccess * @param id * @throws GeneralSecurityException * this is an <code>UnknownException</code> if the group is not known to the * <code>Registry</code> */ public Group getGroupById( SecurityAccess securityAccess, int id ) throws GeneralSecurityException { Group group = null; Connection con = acquireLocalConnection( securityAccess ); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = con .prepareStatement( "SELECT SEC_SECURABLE_OBJECTS.NAME,SEC_SECURABLE_OBJECTS.TITLE " + "FROM SEC_GROUPS,SEC_SECURABLE_OBJECTS " + "WHERE SEC_SECURABLE_OBJECTS.ID=? AND SEC_GROUPS.ID=SEC_SECURABLE_OBJECTS.ID" ); pstmt.setInt( 1, id ); rs = pstmt.executeQuery(); if ( rs.next() ) { group = new Group( id, rs.getString( 1 ), rs.getString( 2 ), this ); } else { throw new UnknownException( "Lookup of group with id: " + id + " failed! A group with this id does not exist." ); } } catch (SQLException e) { LOG.logError( e.getMessage(), e ); throw new GeneralSecurityException( e ); } finally { closeResultSet( rs ); closeStatement( pstmt ); releaseLocalConnection( securityAccess, con ); } return group; } /** * Retrieves all <code>Group</code> s from the <code>Registry</code>. * * @param securityAccess * @throws GeneralSecurityException */ public Group[] getAllGroups( SecurityAccess securityAccess ) throws GeneralSecurityException { ArrayList groups = new ArrayList(); Connection con = acquireLocalConnection( securityAccess ); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = con .prepareStatement( "SELECT SEC_GROUPS.ID,SEC_SECURABLE_OBJECTS.NAME,SEC_SECURABLE_OBJECTS.TITLE " + "FROM SEC_GROUPS,SEC_SECURABLE_OBJECTS " + "WHERE SEC_GROUPS.ID=SEC_SECURABLE_OBJECTS.ID" ); rs = pstmt.executeQuery(); while (rs.next()) { groups .add( new Group( rs.getInt( 1 ), rs.getString( 2 ), rs.getString( 3 ), this ) ); } } catch (SQLException e) { LOG.logError( e.getMessage(), e ); throw new GeneralSecurityException( e ); } finally { closeResultSet( rs ); closeStatement( pstmt ); releaseLocalConnection( securityAccess, con ); } return (Group[]) groups.toArray( new Group[groups.size()] ); } /** * Adds a new role to the <code>Registry</code>. * * @param transaction * @param name * @throws GeneralSecurityException * this is a <code>DuplicateException</code> if the role already existed */ public Role registerRole( SecurityTransaction transaction, String name ) throws GeneralSecurityException { try { getRoleByName( transaction, name ); throw new DuplicateException( "Registration of role '" + name + "' failed! A role with " + "this name already exists." ); } catch (UnknownException e) { } Role role = new Role( getID( transaction, "SEC_SECURABLE_OBJECTS" ), name, this ); PreparedStatement pstmt = null; try { pstmt = transactionalConnection .prepareStatement( "INSERT INTO SEC_SECURABLE_OBJECTS (ID,NAME,TITLE) VALUES (?,?,?)" ); pstmt.setInt( 1, role.getID() ); pstmt.setString( 2, role.getName() ); pstmt.setString( 3, role.getTitle() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; pstmt = transactionalConnection .prepareStatement( "INSERT INTO SEC_ROLES (ID) VALUES (?)" ); pstmt.setInt( 1, role.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; } catch (SQLException e) { LOG.logError( e.getMessage(), e ); closeStatement( pstmt ); abortTransaction( transaction ); throw new GeneralSecurityException( "SQLRegistry.registerRole() failed. Rollback performed. " + "Error message: " + e.getMessage() ); } return role; } /** * Removes an existing <code>Role</code> from the <code>Registry</code> (including its * relations). * * @param transaction * @param role * @throws GeneralSecurityException */ public void deregisterRole( SecurityTransaction transaction, Role role ) throws GeneralSecurityException { PreparedStatement pstmt = null; try { pstmt = transactionalConnection .prepareStatement( "DELETE FROM SEC_JT_USERS_ROLES WHERE FK_ROLES=?" ); pstmt.setInt( 1, role.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; pstmt = transactionalConnection .prepareStatement( "DELETE FROM SEC_JT_GROUPS_ROLES WHERE FK_ROLES=?" ); pstmt.setInt( 1, role.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; pstmt = transactionalConnection .prepareStatement( "DELETE FROM SEC_JT_ROLES_SECOBJECTS WHERE FK_ROLES=? OR FK_SECURABLE_OBJECTS=?" ); pstmt.setInt( 1, role.getID() ); pstmt.setInt( 2, role.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; pstmt = transactionalConnection.prepareStatement( "DELETE FROM SEC_ROLES WHERE ID=?" ); pstmt.setInt( 1, role.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; pstmt = transactionalConnection .prepareStatement( "DELETE FROM SEC_SECURABLE_OBJECTS WHERE ID=?" ); pstmt.setInt( 1, role.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; } catch (SQLException e) { LOG.logError( e.getMessage(), e ); closeStatement( pstmt ); abortTransaction( transaction ); throw new GeneralSecurityException( "SQLRegistry.deregisterRole() failed. Rollback performed. " + "Error message: " + e.getMessage() ); } } /** * Retrieves a <code>Role</code> from the <code>Registry</code>. * * @param securityAccess * @param name * @throws GeneralSecurityException * this is an <code>UnknownException</code> if the role is not known to the * <code>Registry</code> */ public Role getRoleByName( SecurityAccess securityAccess, String name ) throws GeneralSecurityException { Role role = null; Connection con = acquireLocalConnection( securityAccess ); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = con.prepareStatement( "SELECT SEC_ROLES.ID " + "FROM SEC_ROLES,SEC_SECURABLE_OBJECTS " + "WHERE SEC_ROLES.ID=SEC_SECURABLE_OBJECTS.ID AND " + "SEC_SECURABLE_OBJECTS.NAME=?" ); pstmt.setString( 1, name ); rs = pstmt.executeQuery(); if ( rs.next() ) { role = new Role( rs.getInt( 1 ), name, this ); } else { throw new UnknownException( "Lookup of role '" + name + "' failed! A role with this name does not exist." ); } } catch (SQLException e) { LOG.logError( e.getMessage(), e ); throw new GeneralSecurityException( e ); } finally { closeResultSet( rs ); closeStatement( pstmt ); releaseLocalConnection( securityAccess, con ); } return role; } /** * Retrieves all <code>Roles</code> s from the <code>Registry</code> that have a certain * namespace. * * @param securityAccess * @param ns * null for default namespace * @throws GeneralSecurityException */ public Role[] getRolesByNS( SecurityAccess securityAccess, String ns ) throws GeneralSecurityException { ArrayList roles = new ArrayList(); Connection con = acquireLocalConnection( securityAccess ); PreparedStatement pstmt = null; ResultSet rs = null; try { if ( ns != null && ( !ns.equals( "" ) ) ) { pstmt = con .prepareStatement( "SELECT SEC_ROLES.ID,SEC_SECURABLE_OBJECTS.NAME " + "FROM SEC_ROLES,SEC_SECURABLE_OBJECTS " + "WHERE SEC_SECURABLE_OBJECTS.ID=SEC_ROLES.ID AND SEC_SECURABLE_OBJECTS.NAME LIKE ?" ); pstmt.setString( 1, ns + ":%" ); } else { pstmt = con.prepareStatement( "SELECT SEC_ROLES.ID,SEC_SECURABLE_OBJECTS.NAME " + "FROM SEC_ROLES,SEC_SECURABLE_OBJECTS " + "WHERE SEC_SECURABLE_OBJECTS.ID=SEC_ROLES.ID AND " + "SEC_SECURABLE_OBJECTS.NAME NOT LIKE '%:%'" ); } rs = pstmt.executeQuery(); while (rs.next()) { roles.add( new Role( rs.getInt( 1 ), rs.getString( 2 ), this ) ); } } catch (SQLException e) { LOG.logError( e.getMessage(), e ); throw new GeneralSecurityException( e ); } finally { closeResultSet( rs ); closeStatement( pstmt ); releaseLocalConnection( securityAccess, con ); } return (Role[]) roles.toArray( new Role[roles.size()] ); } /** * Retrieves a <code>Role</code> from the <code>Registry</code>. * * @param securityAccess * @param id * @throws GeneralSecurityException * this is an <code>UnknownException</code> if the role is not known to the * <code>Registry</code> */ public Role getRoleById( SecurityAccess securityAccess, int id ) throws GeneralSecurityException { Role role = null; Connection con = acquireLocalConnection( securityAccess ); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = con.prepareStatement( "SELECT SEC_SECURABLE_OBJECTS.NAME " + "FROM SEC_ROLES,SEC_SECURABLE_OBJECTS " + "WHERE SEC_SECURABLE_OBJECTS.ID=? AND SEC_ROLES.ID=SEC_SECURABLE_OBJECTS.ID" ); pstmt.setInt( 1, id ); rs = pstmt.executeQuery(); if ( rs.next() ) { role = new Role( id, rs.getString( 1 ), this ); } else { throw new UnknownException( "Lookup of role with id: " + id + " failed! A role with this id does not exist." ); } } catch (SQLException e) { LOG.logError( e.getMessage(), e ); throw new GeneralSecurityException( e ); } finally { closeResultSet( rs ); closeStatement( pstmt ); releaseLocalConnection( securityAccess, con ); } return role; } /** * Retrieves all <code>Role</code> s from the <code>Registry</code>, except those that are * only used internally (these have namespaces that begin with $). * * @param securityAccess * @throws GeneralSecurityException */ public Role[] getAllRoles( SecurityAccess securityAccess ) throws GeneralSecurityException { ArrayList roles = new ArrayList(); Connection con = acquireLocalConnection( securityAccess ); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = con.prepareStatement( "SELECT SEC_ROLES.ID,SEC_SECURABLE_OBJECTS.NAME " + "FROM SEC_ROLES,SEC_SECURABLE_OBJECTS " + "WHERE SEC_ROLES.ID=SEC_SECURABLE_OBJECTS.ID AND " + "SEC_SECURABLE_OBJECTS.NAME NOT LIKE '$%:%'" ); rs = pstmt.executeQuery(); while (rs.next()) { roles.add( new Role( rs.getInt( 1 ), rs.getString( 2 ), this ) ); } } catch (SQLException e) { LOG.logError( e.getMessage(), e ); throw new GeneralSecurityException( e ); } finally { closeResultSet( rs ); closeStatement( pstmt ); releaseLocalConnection( securityAccess, con ); } return (Role[]) roles.toArray( new Role[roles.size()] ); } /** * Adds a new <code>SecuredObject</code> to the <code>Registry</code>. * * @param transaction * @param type * @param name * @param title * @throws GeneralSecurityException * this is a <code>DuplicateException</code> if the object already existed */ public SecuredObject registerSecuredObject( SecurityTransaction transaction, String type, String name, String title ) throws GeneralSecurityException { try { getSecuredObjectByName( transaction, name, type ); throw new DuplicateException( "Registration of secured object '" + name + "' with type '" + type + "' failed! A secured object with this name and type " + "already exists." ); } catch (UnknownException e) { } PreparedStatement pstmt = null; SecuredObject object = null; ResultSet rs = null; try { // check for ID of object type (add type if necessary) int typeId = 0; pstmt = transactionalConnection .prepareStatement( "SELECT ID FROM SEC_SECURED_OBJECT_TYPES WHERE NAME=?" ); pstmt.setString( 1, type ); rs = pstmt.executeQuery(); if ( rs.next() ) { typeId = rs.getInt( 1 ); rs.close(); rs = null; pstmt.close(); pstmt = null; } else { typeId = getID( transaction, "SEC_SECURED_OBJECT_TYPES" ); rs.close(); rs = null; pstmt.close(); pstmt = null; pstmt = transactionalConnection .prepareStatement( "INSERT INTO SEC_SECURED_OBJECT_TYPES (ID,NAME) VALUES (?,?)" ); pstmt.setInt( 1, typeId ); pstmt.setString( 2, type ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; } // insert securable object part object = new SecuredObject( getID( transaction, "SEC_SECURABLE_OBJECTS" ), typeId, name, title, this ); pstmt = transactionalConnection .prepareStatement( "INSERT INTO SEC_SECURABLE_OBJECTS (ID,NAME,TITLE) VALUES (?,?,?)" ); pstmt.setInt( 1, object.getID() ); pstmt.setString( 2, object.getName() ); pstmt.setString( 3, object.getTitle() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; // insert secured object pstmt = transactionalConnection .prepareStatement( "INSERT INTO SEC_SECURED_OBJECTS (ID, FK_SECURED_OBJECT_TYPES) VALUES (?,?)" ); pstmt.setInt( 1, object.getID() ); pstmt.setInt( 2, typeId ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; } catch (SQLException e) { LOG.logError( e.getMessage(), e ); closeResultSet( rs ); closeStatement( pstmt ); abortTransaction( transaction ); throw new GeneralSecurityException( "SQLRegistry.registerSecuredObject() failed. Rollback performed. " + "Error message: " + e.getMessage() ); } return object; } /** * Removes an existing <code>SecuredObject</code> from the <code>Registry</code> (including * its associations). * * @param transaction * @param object * @throws GeneralSecurityException */ public void deregisterSecuredObject( SecurityTransaction transaction, SecuredObject object ) throws GeneralSecurityException { PreparedStatement pstmt = null; try { pstmt = transactionalConnection .prepareStatement( "DELETE FROM SEC_SECURED_OBJECTS WHERE ID=?" ); pstmt.setInt( 1, object.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; pstmt = transactionalConnection .prepareStatement( "DELETE FROM SEC_JT_ROLES_SECOBJECTS WHERE FK_SECURABLE_OBJECTS=?" ); pstmt.setInt( 1, object.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; pstmt = transactionalConnection .prepareStatement( "DELETE FROM SEC_SECURABLE_OBJECTS WHERE ID=?" ); pstmt.setInt( 1, object.getID() ); pstmt.executeUpdate(); pstmt = null; } catch (SQLException e) { LOG.logError( e.getMessage(), e ); closeStatement( pstmt ); abortTransaction( transaction ); throw new GeneralSecurityException( "SQLRegistry.deregisterSecuredObject() failed. Rollback performed. " + "Error message: " + e.getMessage() ); } } /** * Retrieves a <code>SecuredObject</code> from the <code>Registry</code>. * * @param securityAccess * @param name * @throws GeneralSecurityException * this is an <code>UnknownException</code> if the object is not known to the * <code>Registry</code> */ public SecuredObject getSecuredObjectByName( SecurityAccess securityAccess, String name, String type ) throws GeneralSecurityException { SecuredObject object = null; Connection con = acquireLocalConnection( securityAccess ); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = con .prepareStatement( "SELECT SEC_SECURED_OBJECTS.ID,SEC_SECURED_OBJECT_TYPES.ID, " + "SEC_SECURABLE_OBJECTS.TITLE " + "FROM SEC_SECURED_OBJECTS,SEC_SECURED_OBJECT_TYPES,SEC_SECURABLE_OBJECTS " + "WHERE SEC_SECURED_OBJECTS.FK_SECURED_OBJECT_TYPES=SEC_SECURED_OBJECT_TYPES.ID AND " + "SEC_SECURED_OBJECTS.ID=SEC_SECURABLE_OBJECTS.ID AND SEC_SECURABLE_OBJECTS.NAME LIKE ? AND " + "SEC_SECURED_OBJECT_TYPES.NAME=?" ); pstmt.setString( 1, name ); pstmt.setString( 2, type ); rs = pstmt.executeQuery(); if ( rs.next() ) { object = new SecuredObject( rs.getInt( 1 ), rs.getInt( 2 ), name, rs.getString( 3 ), this ); } else { throw new UnknownException( "Lookup of secured object '" + name + "' with type '" + type + "' failed! A secured object with this " + "name and type does not exist." ); } } catch (SQLException e) { LOG.logError( e.getMessage(), e ); throw new GeneralSecurityException( e ); } finally { closeResultSet( rs ); closeStatement( pstmt ); releaseLocalConnection( securityAccess, con ); } return object; } /** * Retrieves a <code>SecuredObject</code> from the <code>Registry</code>. * * @param securityAccess * @param id * @throws GeneralSecurityException * this is an <code>UnknownException</code> if the object is not known to the * <code>Registry</code> */ public SecuredObject getSecuredObjectById( SecurityAccess securityAccess, int id ) throws GeneralSecurityException { SecuredObject object = null; Connection con = acquireLocalConnection( securityAccess ); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = con .prepareStatement( "SELECT SEC_SECURED_OBJECTS.FK_SECURED_OBJECT_TYPES,SEC_SECURABLE_OBJECTS.NAME," + "SEC_SECURABLE_OBJECTS.TITLE " + "FROM SEC_SECURED_OBJECTS,SEC_SECURABLE_OBJECTS " + "WHERE SEC_SECURED_OBJECTS.ID=SEC_SECURABLE_OBJECTS.ID AND SEC_SECURABLE_OBJECTS.ID=?" ); pstmt.setInt( 1, id ); rs = pstmt.executeQuery(); if ( rs.next() ) { object = new SecuredObject( id, rs.getInt( 1 ), rs.getString( 2 ), rs.getString( 3 ), this ); } else { throw new UnknownException( "Lookup of secured object with id: " + id + " failed! A secured object with this id does not exist." ); } } catch (SQLException e) { LOG.logError( e.getMessage(), e ); throw new GeneralSecurityException( e ); } finally { closeResultSet( rs ); closeStatement( pstmt ); releaseLocalConnection( securityAccess, con ); } return object; } /** * Retrieves all <code>SecuredObject</code> s from the <code>Registry</code> that have a * certain namespace. * * @param securityAccess * @param ns * null for default namespace * @param type * @throws GeneralSecurityException */ public SecuredObject[] getSecuredObjectsByNS( SecurityAccess securityAccess, String ns, String type ) throws GeneralSecurityException { ArrayList objects = new ArrayList(); Connection con = acquireLocalConnection( securityAccess ); PreparedStatement pstmt = null; ResultSet rs = null; try { if ( ns != null && ( !ns.equals( "" ) ) ) { pstmt = con .prepareStatement( "SELECT SEC_SECURED_OBJECTS.ID,SEC_SECURED_OBJECT_TYPES.ID, " + "SEC_SECURABLE_OBJECTS.NAME,SEC_SECURABLE_OBJECTS.TITLE " + "FROM SEC_SECURED_OBJECTS,SEC_SECURED_OBJECT_TYPES,SEC_SECURABLE_OBJECTS " + "WHERE SEC_SECURED_OBJECTS.FK_SECURED_OBJECT_TYPES=SEC_SECURED_OBJECT_TYPES.ID AND " + "SEC_SECURABLE_OBJECTS.ID=SEC_SECURED_OBJECTS.ID AND SEC_SECURED_OBJECT_TYPES.NAME=? " + "AND SEC_SECURABLE_OBJECTS.NAME LIKE ?" ); pstmt.setString( 1, type ); pstmt.setString( 2, ns + ":%" ); } else { pstmt = con .prepareStatement( "SELECT SEC_SECURED_OBJECTS.ID,SEC_SECURED_OBJECT_TYPES.ID, " + "SEC_SECURABLE_OBJECTS.NAME,SEC_SECURABLE_OBJECTS.TITLE " + "FROM SEC_SECURED_OBJECTS,SEC_SECURED_OBJECT_TYPES,SEC_SECURABLE_OBJECTS " + "WHERE SEC_SECURED_OBJECTS.FK_SECURED_OBJECT_TYPES=SEC_SECURED_OBJECT_TYPES.ID AND " + "SEC_SECURABLE_OBJECTS.ID=SEC_SECURED_OBJECTS.ID AND SEC_SECURED_OBJECT_TYPES.NAME=? " + "AND SEC_SECURABLE_OBJECTS.NAME NOT LIKE '%:%'" ); pstmt.setString( 1, type ); } rs = pstmt.executeQuery(); while (rs.next()) { objects.add( new SecuredObject( rs.getInt( 1 ), rs.getInt( 2 ), rs.getString( 3 ), rs.getString( 4 ), this ) ); } } catch (SQLException e) { LOG.logError( e.getMessage(), e ); throw new GeneralSecurityException( e ); } finally { closeResultSet( rs ); closeStatement( pstmt ); releaseLocalConnection( securityAccess, con ); } return (SecuredObject[]) objects.toArray( new SecuredObject[objects.size()] ); } /** * Retrieves all <code>SecuredObject</code> s with the given type from the * <code>Registry</code>. * * @param securityAccess * @param type * @throws GeneralSecurityException */ public SecuredObject[] getAllSecuredObjects( SecurityAccess securityAccess, String type ) throws GeneralSecurityException { ArrayList objects = new ArrayList(); Connection con = acquireLocalConnection( securityAccess ); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = con .prepareStatement( "SELECT SEC_SECURED_OBJECTS.ID,SEC_SECURED_OBJECT_TYPES.ID, " + "SEC_SECURABLE_OBJECTS.NAME,SEC_SECURABLE_OBJECTS.TITLE " + "FROM SEC_SECURED_OBJECTS,SEC_SECURED_OBJECT_TYPES,SEC_SECURABLE_OBJECTS " + "WHERE SEC_SECURED_OBJECTS.FK_SECURED_OBJECT_TYPES=SEC_SECURED_OBJECT_TYPES.ID AND " + "SEC_SECURABLE_OBJECTS.ID=SEC_SECURED_OBJECTS.ID AND SEC_SECURED_OBJECT_TYPES.NAME=?" ); pstmt.setString( 1, type ); rs = pstmt.executeQuery(); while (rs.next()) { objects.add( new SecuredObject( rs.getInt( 1 ), rs.getInt( 2 ), rs.getString( 3 ), rs.getString( 4 ), this ) ); } } catch (SQLException e) { LOG.logError( e.getMessage(), e ); throw new GeneralSecurityException( e ); } finally { closeResultSet( rs ); closeStatement( pstmt ); releaseLocalConnection( securityAccess, con ); } return (SecuredObject[]) objects.toArray( new SecuredObject[objects.size()] ); } /** * Adds a new <code>Privilege</code> to the <code>Registry</code>. * * @param transaction * @param name * @throws GeneralSecurityException * this is a <code>DuplicateException</code> if the <code>Privilege</code> * already existed */ public Privilege registerPrivilege( SecurityTransaction transaction, String name ) throws GeneralSecurityException { try { getPrivilegeByName( transaction, name ); throw new DuplicateException( "Registration of privilege '" + name + "' failed! A privilege with " + "this name already exists." ); } catch (UnknownException e) { } int id = getID( transaction, "SEC_PRIVILEGES" ); Privilege privilege = new Privilege( id, name ); PreparedStatement pstmt = null; try { pstmt = transactionalConnection .prepareStatement( "INSERT INTO SEC_PRIVILEGES (ID, NAME) VALUES (?,?)" ); pstmt.setInt( 1, id ); pstmt.setString( 2, name ); pstmt.executeUpdate(); pstmt.close(); } catch (SQLException e) { LOG.logError( e.getMessage(), e ); closeStatement( pstmt ); abortTransaction( transaction ); throw new GeneralSecurityException( "SQLRegistry.registerPrivilege() failed. Rollback performed. " + "Error message: " + e.getMessage() ); } return privilege; } /** * Removes an existing</code> Privilege</code> from the <code>Registry </code> (including its * relations). * * @param transaction * @param privilege * @throws GeneralSecurityException */ public void deregisterPrivilege( SecurityTransaction transaction, Privilege privilege ) throws GeneralSecurityException { PreparedStatement pstmt = null; try { pstmt = transactionalConnection .prepareStatement( "DELETE FROM SEC_JT_ROLES_PRIVILEGES WHERE FK_PRIVILEGES=?" ); pstmt.setInt( 1, privilege.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; pstmt = transactionalConnection .prepareStatement( "DELETE FROM SEC_PRIVILEGES WHERE ID=?" ); pstmt.setInt( 1, privilege.getID() ); pstmt.executeUpdate(); pstmt.close(); } catch (SQLException e) { LOG.logError( e.getMessage(), e ); closeStatement( pstmt ); abortTransaction( transaction ); throw new GeneralSecurityException( "SQLRegistry.deregisterPrivilege() failed. Rollback performed. " + "Error message: " + e.getMessage() ); } } /** * Retrieves a <code>Privilege</code> from the <code>Registry</code>. * * @param securityAccess * @param name * @throws GeneralSecurityException * this is an <code>UnknownException</code> if the privilege is not known to the * <code>Registry</code> */ public Privilege getPrivilegeByName( SecurityAccess securityAccess, String name ) throws GeneralSecurityException { Privilege privilege = null; Connection con = acquireLocalConnection( securityAccess ); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = con.prepareStatement( "SELECT ID FROM SEC_PRIVILEGES WHERE NAME=?" ); pstmt.setString( 1, name ); rs = pstmt.executeQuery(); if ( rs.next() ) { privilege = new Privilege( rs.getInt( 1 ), name ); } else { throw new UnknownException( "Lookup of privilege '" + name + "' failed! A privilege with this name does not exist." ); } } catch (SQLException e) { LOG.logError( e.getMessage(), e ); throw new GeneralSecurityException( e ); } finally { closeResultSet( rs ); closeStatement( pstmt ); releaseLocalConnection( securityAccess, con ); } return privilege; } /** * Retrieves all <code>Privileges</code> s from the <code>Registry</code> that are * associated DIRECTLY (i.e. not via group memberships) with a given <code>Role</code>. * * @param securityAccess * @param role * @throws GeneralSecurityException */ public Privilege[] getPrivilegesForRole( SecurityAccess securityAccess, Role role ) throws GeneralSecurityException { ArrayList privileges = new ArrayList(); Connection con = acquireLocalConnection( securityAccess ); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = con.prepareStatement( "SELECT SEC_PRIVILEGES.ID,SEC_PRIVILEGES.NAME " + "FROM SEC_JT_ROLES_PRIVILEGES, SEC_PRIVILEGES WHERE " + "SEC_JT_ROLES_PRIVILEGES.FK_ROLES=? AND " + "SEC_JT_ROLES_PRIVILEGES.FK_PRIVILEGES=SEC_PRIVILEGES.ID" ); pstmt.setInt( 1, role.getID() ); rs = pstmt.executeQuery(); while (rs.next()) { privileges.add( new Privilege( rs.getInt( 1 ), rs.getString( 2 ) ) ); } } catch (SQLException e) { LOG.logError( e.getMessage(), e ); throw new GeneralSecurityException( e ); } finally { closeResultSet( rs ); closeStatement( pstmt ); releaseLocalConnection( securityAccess, con ); } return (Privilege[]) privileges.toArray( new Privilege[privileges.size()] ); } /** * Sets all <code>Privilege</code> s that are associated with a given <code>Role</code>. * * @param transaction * @param role * @param privileges * @throws GeneralSecurityException */ public void setPrivilegesForRole( SecurityTransaction transaction, Role role, Privilege[] privileges ) throws GeneralSecurityException { PreparedStatement pstmt = null; try { pstmt = transactionalConnection .prepareStatement( "DELETE FROM SEC_JT_ROLES_PRIVILEGES WHERE FK_ROLES=?" ); pstmt.setInt( 1, role.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; for (int i = 0; i < privileges.length; i++) { pstmt = transactionalConnection .prepareStatement( "INSERT INTO SEC_JT_ROLES_PRIVILEGES (FK_ROLES, FK_PRIVILEGES) VALUES (?,?)" ); pstmt.setInt( 1, role.getID() ); pstmt.setInt( 2, privileges[i].getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; } } catch (SQLException e) { LOG.logError( e.getMessage(), e ); closeStatement( pstmt ); abortTransaction( transaction ); throw new GeneralSecurityException( "SQLRegistry.setPrivilegesForRols() failed. Rollback performed. " + "Error message: " + e.getMessage() ); } } /** * Adds a new <code>Right</code> to the <code>Registry</code>. * * @param transaction * @param name * @throws GeneralSecurityException * this is a <code>DuplicateException</code> if the <code>Right</code> already * existed */ public RightType registerRightType( SecurityTransaction transaction, String name ) throws GeneralSecurityException { try { getRightTypeByName( transaction, name ); throw new DuplicateException( "Registration of right '" + name + "' failed! A right with " + "this name already exists." ); } catch (UnknownException e) { } int id = getID( transaction, "SEC_RIGHTS" ); RightType right = new RightType( id, name ); PreparedStatement pstmt = null; try { pstmt = transactionalConnection .prepareStatement( "INSERT INTO SEC_RIGHTS (ID, NAME) VALUES (?,?)" ); pstmt.setInt( 1, id ); pstmt.setString( 2, name ); pstmt.executeUpdate(); pstmt.close(); } catch (SQLException e) { LOG.logError( e.getMessage(), e ); closeStatement( pstmt ); abortTransaction( transaction ); throw new GeneralSecurityException( "SQLRegistry.registerRight() failed. Rollback " + "performed. Error message: " + e.getMessage() ); } return right; } /** * Removes an existing <code>RightType</code> from the <code>Registry</code> (including its * relations). * * @param transaction * @param type * @throws GeneralSecurityException */ public void deregisterRightType( SecurityTransaction transaction, RightType type ) throws GeneralSecurityException { PreparedStatement pstmt = null; try { pstmt = transactionalConnection .prepareStatement( "DELETE FROM SEC_JT_ROLES_SECOBJECTS WHERE FK_RIGHTS=?" ); pstmt.setInt( 1, type.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; pstmt = transactionalConnection.prepareStatement( "DELETE FROM SEC_RIGHTS WHERE ID=?" ); pstmt.setInt( 1, type.getID() ); pstmt.executeUpdate(); pstmt.close(); } catch (SQLException e) { LOG.logError( e.getMessage(), e ); closeStatement( pstmt ); abortTransaction( transaction ); throw new GeneralSecurityException( "SQLRegistry.deregisterRight() failed. Rollback performed. " + "Error message: " + e.getMessage() ); } } /** * Retrieves a <code>Right</code> from the <code>Registry</code>. * * @param securityAccess * @param name * @throws GeneralSecurityException * this is an <code>UnknownException</code> if the <code>Right</code> is not * known to the <code>Registry</code> */ public RightType getRightTypeByName( SecurityAccess securityAccess, String name ) throws GeneralSecurityException { RightType right = null; Connection con = acquireLocalConnection( securityAccess ); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = con.prepareStatement( "SELECT ID FROM SEC_RIGHTS WHERE NAME=?" ); pstmt.setString( 1, name ); rs = pstmt.executeQuery(); if ( rs.next() ) { right = new RightType( rs.getInt( 1 ), name ); } else { throw new UnknownException( "Lookup of right '" + name + "' failed! A right with this name does not exist." ); } } catch (SQLException e) { LOG.logError( e.getMessage(), e ); throw new GeneralSecurityException( e ); } finally { closeResultSet( rs ); closeStatement( pstmt ); releaseLocalConnection( securityAccess, con ); } return right; } /** * Retrieves the <code>Rights</code> from the <code>Registry</code> that are associated with * a given <code>Role</code> and a <code>SecurableObject</code>. * * @param securityAccess * @param object * @param role * @throws GeneralSecurityException */ public Right[] getRights( SecurityAccess securityAccess, SecurableObject object, Role role ) throws GeneralSecurityException { ArrayList rights = new ArrayList(); Connection con = acquireLocalConnection( securityAccess ); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = con.prepareStatement( "SELECT SEC_RIGHTS.ID,SEC_RIGHTS.NAME," + "SEC_JT_ROLES_SECOBJECTS.CONSTRAINTS FROM SEC_JT_ROLES_SECOBJECTS," + "SEC_RIGHTS WHERE SEC_JT_ROLES_SECOBJECTS.FK_ROLES=? AND " + "SEC_JT_ROLES_SECOBJECTS.FK_SECURABLE_OBJECTS=? AND " + "SEC_JT_ROLES_SECOBJECTS.FK_RIGHTS=SEC_RIGHTS.ID" ); pstmt.setInt( 1, role.getID() ); pstmt.setInt( 2, object.getID() ); rs = pstmt.executeQuery(); ResultSetMetaData metadata = rs.getMetaData(); int constraintType = metadata.getColumnType( 3 ); while (rs.next()) { Right right = null; RightType type = new RightType( rs.getInt( 1 ), rs.getString( 2 ) ); String constraints = null; Object o = rs.getObject( 3 ); if ( o != null ) { if ( constraintType == Types.CLOB ) { Reader reader = ( (Clob) o ).getCharacterStream(); StringBuffer sb = new StringBuffer( 2000 ); int c; try { while (( c = reader.read() ) > -1) { sb.append( (char) c ); } reader.close(); } catch (IOException e) { throw new GeneralSecurityException( "Error converting CLOB to constraint string: " + e.getMessage() ); } constraints = sb.toString(); } else { constraints = o.toString(); } } // check if the right has constraints if ( constraints != null && constraints.length() > 3 ) { right = new Right( object, type, buildFilter( constraints ) ); } else { right = new Right( object, type, null ); } rights.add( right ); } } catch (SQLException e) { LOG.logError( e.getMessage(), e ); throw new GeneralSecurityException( e ); } finally { closeResultSet( rs ); closeStatement( pstmt ); releaseLocalConnection( securityAccess, con ); } return (Right[]) rights.toArray( new Right[rights.size()] ); } /** * Sets the <code>Rights</code> to be associated with a given <code>Role</code> and * <code>SecurableObject</code>. * * @param transaction * @param object * @param role * @param rights * @throws GeneralSecurityException */ public void setRights( SecurityTransaction transaction, SecurableObject object, Role role, Right[] rights ) throws GeneralSecurityException { PreparedStatement pstmt = null; try { pstmt = transactionalConnection .prepareStatement( "DELETE FROM SEC_JT_ROLES_SECOBJECTS WHERE FK_ROLES=? AND FK_SECURABLE_OBJECTS=?" ); pstmt.setInt( 1, role.getID() ); pstmt.setInt( 2, object.getID() ); pstmt.executeUpdate(); pstmt.close(); for (int i = 0; i < rights.length; i++) { String constraints = null; if ( rights[i].getConstraints() != null ) { constraints = rights[i].getConstraints().toXML().toString(); } LOG.logDebug( "constraints to add: ", constraints ); if ( transactionalConnection instanceof OracleConnection ) { handleOracle( object, role, rights[i], constraints ); } else { pstmt = transactionalConnection.prepareStatement( "INSERT INTO SEC_JT_ROLES_SECOBJECTS (FK_ROLES, FK_SECURABLE_OBJECTS, FK_RIGHTS,CONSTRAINTS) VALUES (?,?,?,?)" ); pstmt.setInt( 1, role.getID() ); pstmt.setInt( 2, object.getID() ); pstmt.setInt( 3, rights[i].getType().getID() ); pstmt.setString( 4, constraints ); pstmt.executeUpdate(); pstmt.close(); } } } catch (SQLException e) { LOG.logError( e.getMessage(), e ); closeStatement( pstmt ); abortTransaction( transaction ); throw new GeneralSecurityException( "SQLRegistry.setRights() failed. Rollback performed. " + "Error message: " + e.getMessage() ); } } private void handleOracle( SecurableObject object, Role role, Right right, String constraints ) throws SQLException { PreparedStatement pstmt; pstmt = transactionalConnection.prepareStatement( "INSERT INTO SEC_JT_ROLES_SECOBJECTS (FK_ROLES, FK_SECURABLE_OBJECTS, FK_RIGHTS, CONSTRAINTS) VALUES (?,?,?, EMPTY_CLOB() )" ); pstmt.setInt( 1, role.getID() ); pstmt.setInt( 2, object.getID() ); pstmt.setInt( 3, right.getType().getID() ); pstmt.executeUpdate(); pstmt.close(); transactionalConnection.commit(); if ( constraints != null ) { pstmt = transactionalConnection.prepareStatement( "select CONSTRAINTS from SEC_JT_ROLES_SECOBJECTS where FK_ROLES = ? and FK_SECURABLE_OBJECTS = ? and FK_RIGHTS = ? FOR UPDATE" ); pstmt.setInt( 1, role.getID() ); pstmt.setInt( 2, object.getID() ); pstmt.setInt( 3, right.getType().getID() ); ResultSet rs = pstmt.executeQuery(); rs.next(); CLOB clob = (oracle.sql.CLOB)rs.getClob( 1 ); try { //clob.getAsciiOutputStream().write( constraints.getBytes() ); OutputStream os = clob.getAsciiOutputStream(); OutputStreamWriter osw = new OutputStreamWriter(os); //use that output stream to write character data to the Oracle data store osw.write( constraints.toCharArray() ); //write data and commit osw.flush(); osw.close(); os.close(); } catch ( IOException e ) { e.printStackTrace(); } } pstmt.close(); } /** * Sets one <code>Right</code> to be associated with a given <code>Role</code> and all given * <code>SecurableObjects</code>. * * @param transaction * @param objects * @param role * @param right * @throws GeneralSecurityException */ public void setRights( SecurityTransaction transaction, SecurableObject[] objects, Role role, Right right ) throws GeneralSecurityException { PreparedStatement pstmt = null; try { pstmt = transactionalConnection .prepareStatement( "DELETE FROM SEC_JT_ROLES_SECOBJECTS WHERE FK_ROLES=? AND FK_RIGHTS=?" ); pstmt.setInt( 1, role.getID() ); pstmt.setInt( 2, right.getType().getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; for (int i = 0; i < objects.length; i++) { String constraints = null; if ( right.getConstraints() != null ) { constraints = right.getConstraints().toXML().toString(); } pstmt = transactionalConnection .prepareStatement( "INSERT INTO SEC_JT_ROLES_SECOBJECTS (FK_ROLES, FK_SECURABLE_OBJECTS, FK_RIGHTS, CONSTRAINTS) VALUES (?,?,?,?)" ); pstmt.setInt( 1, role.getID() ); pstmt.setInt( 2, objects[i].getID() ); pstmt.setInt( 3, right.getType().getID() ); pstmt.setString( 4, constraints ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; } } catch (SQLException e) { closeStatement( pstmt ); abortTransaction( transaction ); throw new GeneralSecurityException( "SQLRegistry.setRights() failed. Rollback performed. " + "Error message: " + e.getMessage() ); } } /** * Retrieves all <code>Group</code> s from the <code>Registry</code> that the given * <code>User</code> is a DIRECT (i.e. not via inheritance) member of. * * @param securityAccess * @param user * @throws GeneralSecurityException */ public Group[] getGroupsForUser( SecurityAccess securityAccess, User user ) throws GeneralSecurityException { ArrayList groups = new ArrayList(); Connection con = acquireLocalConnection( securityAccess ); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = con .prepareStatement( "SELECT SEC_GROUPS.ID,SEC_SECURABLE_OBJECTS.NAME,SEC_SECURABLE_OBJECTS.TITLE " + "FROM SEC_SECURABLE_OBJECTS,SEC_GROUPS,SEC_JT_USERS_GROUPS WHERE " + "SEC_SECURABLE_OBJECTS.ID=SEC_GROUPS.ID AND " + "SEC_JT_USERS_GROUPS.FK_GROUPS=SEC_GROUPS.ID AND " + "SEC_JT_USERS_GROUPS.FK_USERS=?" ); pstmt.setInt( 1, user.getID() ); rs = pstmt.executeQuery(); while (rs.next()) { groups .add( new Group( rs.getInt( 1 ), rs.getString( 2 ), rs.getString( 3 ), this ) ); } } catch (SQLException e) { throw new GeneralSecurityException( e ); } finally { closeResultSet( rs ); closeStatement( pstmt ); releaseLocalConnection( securityAccess, con ); } return (Group[]) groups.toArray( new Group[groups.size()] ); } /** * Retrieves all <code>Groups</code> s from the <code>Registry</code> that are members of * another <code>Group</code> DIRECTLY (i.e. not via inheritance). * * @param securityAccess * @param group * @throws GeneralSecurityException */ public Group[] getGroupsInGroup( SecurityAccess securityAccess, Group group ) throws GeneralSecurityException { ArrayList groups = new ArrayList(); Connection con = acquireLocalConnection( securityAccess ); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = con .prepareStatement( "SELECT SEC_GROUPS.ID,SEC_SECURABLE_OBJECTS.NAME,SEC_SECURABLE_OBJECTS.TITLE " + "FROM SEC_GROUPS,SEC_SECURABLE_OBJECTS,SEC_JT_GROUPS_GROUPS " + "WHERE SEC_SECURABLE_OBJECTS.ID=SEC_GROUPS.ID" + " AND SEC_JT_GROUPS_GROUPS.FK_GROUPS_MEMBER=SEC_GROUPS.ID" + " AND SEC_JT_GROUPS_GROUPS.FK_GROUPS=?" ); pstmt.setInt( 1, group.getID() ); rs = pstmt.executeQuery(); while (rs.next()) { groups .add( new Group( rs.getInt( 1 ), rs.getString( 2 ), rs.getString( 3 ), this ) ); } } catch (SQLException e) { throw new GeneralSecurityException( e ); } finally { closeResultSet( rs ); closeStatement( pstmt ); releaseLocalConnection( securityAccess, con ); } return (Group[]) groups.toArray( new Group[groups.size()] ); } /** * Retrieves all <code>Group</code> s from the <code>Registry</code> that the given * <code>Group</code> is a DIRECT member (i.e. not via inheritance) of. * * @param securityAccess * @param group * @throws GeneralSecurityException */ public Group[] getGroupsForGroup( SecurityAccess securityAccess, Group group ) throws GeneralSecurityException { ArrayList groups = new ArrayList(); Connection con = acquireLocalConnection( securityAccess ); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = con .prepareStatement( "SELECT SEC_GROUPS.ID,SEC_SECURABLE_OBJECTS.NAME,SEC_SECURABLE_OBJECTS.TITLE " + "FROM SEC_SECURABLE_OBJECTS,SEC_GROUPS,SEC_JT_GROUPS_GROUPS WHERE " + "SEC_SECURABLE_OBJECTS.ID=SEC_GROUPS.ID AND " + "SEC_JT_GROUPS_GROUPS.FK_GROUPS=SEC_GROUPS.ID AND " + "SEC_JT_GROUPS_GROUPS.FK_GROUPS_MEMBER=?" ); pstmt.setInt( 1, group.getID() ); rs = pstmt.executeQuery(); while (rs.next()) { groups .add( new Group( rs.getInt( 1 ), rs.getString( 2 ), rs.getString( 3 ), this ) ); } } catch (SQLException e) { throw new GeneralSecurityException( e ); } finally { closeResultSet( rs ); closeStatement( pstmt ); releaseLocalConnection( securityAccess, con ); } return (Group[]) groups.toArray( new Group[groups.size()] ); } /** * Retrieves all <code>Group</code> s from the <code>Registry</code> that are associated * with a given <code>Role</code> DIRECTLY (i.e. not via inheritance). * * @param securityAccess * @param role * @throws GeneralSecurityException */ public Group[] getGroupsWithRole( SecurityAccess securityAccess, Role role ) throws GeneralSecurityException { ArrayList groups = new ArrayList(); Connection con = acquireLocalConnection( securityAccess ); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = con .prepareStatement( "SELECT SEC_GROUPS.ID,SEC_SECURABLE_OBJECTS.NAME,SEC_SECURABLE_OBJECTS.TITLE " + "FROM SEC_SECURABLE_OBJECTS,SEC_GROUPS,SEC_JT_GROUPS_ROLES WHERE " + "SEC_SECURABLE_OBJECTS.ID=SEC_GROUPS.ID AND " + "SEC_JT_GROUPS_ROLES.FK_GROUPS=SEC_GROUPS.ID AND " + "SEC_JT_GROUPS_ROLES.FK_ROLES=?" ); pstmt.setInt( 1, role.getID() ); rs = pstmt.executeQuery(); while (rs.next()) { groups .add( new Group( rs.getInt( 1 ), rs.getString( 2 ), rs.getString( 3 ), this ) ); } } catch (SQLException e) { throw new GeneralSecurityException( e ); } finally { closeResultSet( rs ); closeStatement( pstmt ); releaseLocalConnection( securityAccess, con ); } return (Group[]) groups.toArray( new Group[groups.size()] ); } /** * Retrieves all <code>Role</code> s from the <code>Registry</code> that are associated with * a given <code>User</code> DIRECTLY (i.e. not via group memberships). * * @param securityAccess * @param user * @throws GeneralSecurityException */ public Role[] getRolesForUser( SecurityAccess securityAccess, User user ) throws GeneralSecurityException { ArrayList roles = new ArrayList(); Connection con = acquireLocalConnection( securityAccess ); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = con .prepareStatement( "SELECT SEC_ROLES.ID,SEC_SECURABLE_OBJECTS.NAME " + "FROM SEC_SECURABLE_OBJECTS,SEC_ROLES,SEC_JT_USERS_ROLES WHERE " + "SEC_SECURABLE_OBJECTS.ID=SEC_ROLES.ID AND SEC_JT_USERS_ROLES.FK_ROLES=SEC_ROLES.ID " + "AND SEC_JT_USERS_ROLES.FK_USERS=?" ); pstmt.setInt( 1, user.getID() ); rs = pstmt.executeQuery(); while (rs.next()) { roles.add( new Role( rs.getInt( 1 ), rs.getString( 2 ), this ) ); } } catch (SQLException e) { throw new GeneralSecurityException( e ); } finally { closeResultSet( rs ); closeStatement( pstmt ); releaseLocalConnection( securityAccess, con ); } return (Role[]) roles.toArray( new Role[roles.size()] ); } /** * Retrieves all <code>Role</code> s from the <code>Registry</code> that are associated with * a given <code>Group</code> DIRECTLY (i.e. not via inheritance). * * @param securityAccess * @param group * @throws GeneralSecurityException */ public Role[] getRolesForGroup( SecurityAccess securityAccess, Group group ) throws GeneralSecurityException { ArrayList roles = new ArrayList(); Connection con = acquireLocalConnection( securityAccess ); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = con .prepareStatement( "SELECT SEC_ROLES.ID,SEC_SECURABLE_OBJECTS.NAME " + "FROM SEC_SECURABLE_OBJECTS,SEC_ROLES,SEC_JT_GROUPS_ROLES WHERE " + "SEC_SECURABLE_OBJECTS.ID=SEC_ROLES.ID AND SEC_JT_GROUPS_ROLES.FK_ROLES=SEC_ROLES.ID " + "AND SEC_JT_GROUPS_ROLES.FK_GROUPS=?" ); pstmt.setInt( 1, group.getID() ); rs = pstmt.executeQuery(); while (rs.next()) { roles.add( new Role( rs.getInt( 1 ), rs.getString( 2 ), this ) ); } } catch (SQLException e) { throw new GeneralSecurityException( e ); } finally { closeResultSet( rs ); closeStatement( pstmt ); releaseLocalConnection( securityAccess, con ); } return (Role[]) roles.toArray( new Role[roles.size()] ); } /** * Sets the <code>Group</code> s that a given <code>User</code> is member of DIRECTLY (i.e. * not via inheritance). * * @param transaction * @param user * @param groups * @throws GeneralSecurityException */ public void setGroupsForUser( SecurityTransaction transaction, User user, Group[] groups ) throws GeneralSecurityException { PreparedStatement pstmt = null; try { pstmt = transactionalConnection .prepareStatement( "DELETE FROM SEC_JT_USERS_GROUPS WHERE FK_USERS=?" ); pstmt.setInt( 1, user.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; for (int i = 0; i < groups.length; i++) { pstmt = transactionalConnection .prepareStatement( "INSERT INTO SEC_JT_USERS_GROUPS (FK_USERS, FK_GROUPS) VALUES (?,?)" ); pstmt.setInt( 1, user.getID() ); pstmt.setInt( 2, groups[i].getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; } } catch (SQLException e) { closeStatement( pstmt ); abortTransaction( transaction ); throw new GeneralSecurityException( "SQLRegistry.setGroupsForUser() failed. Rollback performed. " + "Error message: " + e.getMessage() ); } } /** * Sets the <code>Group</code> s that a given <code>Group</code> is member of DIRECTLY (i.e. * not via inheritance). * * @param transaction * @param group * @param groups * @throws GeneralSecurityException */ public void setGroupsForGroup( SecurityTransaction transaction, Group group, Group[] groups ) throws GeneralSecurityException { PreparedStatement pstmt = null; try { pstmt = transactionalConnection .prepareStatement( "DELETE FROM SEC_JT_GROUPS_GROUPS WHERE FK_GROUPS_MEMBER=?" ); pstmt.setInt( 1, group.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; for (int i = 0; i < groups.length; i++) { pstmt = transactionalConnection .prepareStatement( "INSERT INTO SEC_JT_GROUPS_GROUPS (FK_GROUPS_MEMBER, FK_GROUPS) VALUES (?,?)" ); pstmt.setInt( 1, group.getID() ); pstmt.setInt( 2, groups[i].getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; } } catch (SQLException e) { closeStatement( pstmt ); abortTransaction( transaction ); throw new GeneralSecurityException( "SQLRegistry.setGroupsForGroup() failed. Rollback performed. " + "Error message: " + e.getMessage() ); } } /** * Sets the <code>Group</code> s that a given <code>Role</code> is associated to DIRECTLY * (i.e. not via inheritance). * * @param transaction * @param role * @param groups * @throws GeneralSecurityException */ public void setGroupsWithRole( SecurityTransaction transaction, Role role, Group[] groups ) throws GeneralSecurityException { PreparedStatement pstmt = null; try { pstmt = transactionalConnection .prepareStatement( "DELETE FROM SEC_JT_GROUPS_ROLES WHERE FK_ROLES=?" ); pstmt.setInt( 1, role.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; for (int i = 0; i < groups.length; i++) { pstmt = transactionalConnection .prepareStatement( "INSERT INTO SEC_JT_GROUPS_ROLES (FK_GROUPS, FK_ROLES) VALUES (?,?)" ); pstmt.setInt( 1, groups[i].getID() ); pstmt.setInt( 2, role.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; } } catch (SQLException e) { closeStatement( pstmt ); abortTransaction( transaction ); throw new GeneralSecurityException( "SQLRegistry.setGroupsWithRole() failed. Rollback performed. " + "Error message: " + e.getMessage() ); } } /** * Sets the <code>User</code> s that a given <code>Role</code> is associated to DIRECTLY * (i.e. not via <code>Group</code> membership). * * @param transaction * @param role * @param users * @throws GeneralSecurityException */ public void setUsersWithRole( SecurityTransaction transaction, Role role, User[] users ) throws GeneralSecurityException { PreparedStatement pstmt = null; try { pstmt = transactionalConnection .prepareStatement( "DELETE FROM SEC_JT_USERS_ROLES WHERE FK_ROLES=?" ); pstmt.setInt( 1, role.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; for (int i = 0; i < users.length; i++) { pstmt = transactionalConnection .prepareStatement( "INSERT INTO SEC_JT_USERS_ROLES (FK_USERS, FK_ROLES) VALUES (?,?)" ); pstmt.setInt( 1, users[i].getID() ); pstmt.setInt( 2, role.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; } } catch (SQLException e) { closeStatement( pstmt ); abortTransaction( transaction ); throw new GeneralSecurityException( "SQLRegistry.setUsersWithRole() failed. Rollback performed. " + "Error message: " + e.getMessage() ); } } /** * Sets the <code>User</code> s that are members of a given <code>Group</code> DIRECTLY * (i.e. not via inheritance). * * @param transaction * @param group * @param users * @throws GeneralSecurityException */ public void setUsersInGroup( SecurityTransaction transaction, Group group, User[] users ) throws GeneralSecurityException { PreparedStatement pstmt = null; try { pstmt = transactionalConnection .prepareStatement( "DELETE FROM SEC_JT_USERS_GROUPS WHERE FK_GROUPS=?" ); pstmt.setInt( 1, group.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; for (int i = 0; i < users.length; i++) { closeStatement( pstmt ); pstmt = transactionalConnection .prepareStatement( "INSERT INTO SEC_JT_USERS_GROUPS (FK_USERS, FK_GROUPS) VALUES (?,?)" ); pstmt.setInt( 1, users[i].getID() ); pstmt.setInt( 2, group.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; } } catch (SQLException e) { closeStatement( pstmt ); abortTransaction( transaction ); throw new GeneralSecurityException( "SQLRegistry.setUsersInGroup() failed. Rollback performed. " + "Error message: " + e.getMessage() ); } } /** * Sets the <code>Groups</code> s that are members of a given <code>Group</code> DIRECTLY * (i.e. not via inheritance). * * @param transaction * @param group * @param groups * @throws GeneralSecurityException */ public void setGroupsInGroup( SecurityTransaction transaction, Group group, Group[] groups ) throws GeneralSecurityException { PreparedStatement pstmt = null; try { pstmt = transactionalConnection .prepareStatement( "DELETE FROM SEC_JT_GROUPS_GROUPS WHERE FK_GROUPS=?" ); pstmt.setInt( 1, group.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; for (int i = 0; i < groups.length; i++) { pstmt = transactionalConnection .prepareStatement( "INSERT INTO SEC_JT_GROUPS_GROUPS (FK_GROUPS_MEMBER, FK_GROUPS) VALUES (?,?)" ); pstmt.setInt( 1, groups[i].getID() ); pstmt.setInt( 2, group.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; } } catch (SQLException e) { closeStatement( pstmt ); abortTransaction( transaction ); throw new GeneralSecurityException( "SQLRegistry.setGroupsInGroup() failed. Rollback performed. " + "Error message: " + e.getMessage() ); } } /** * Sets the <code>Role</code> s that a given <code>User</code> is directly associated to * (i.e. not via <code>Group</code> membership). * * @param transaction * @param user * @param roles * @throws GeneralSecurityException */ public void setRolesForUser( SecurityTransaction transaction, User user, Role[] roles ) throws GeneralSecurityException { PreparedStatement pstmt = null; try { pstmt = transactionalConnection .prepareStatement( "DELETE FROM SEC_JT_USERS_ROLES WHERE FK_USERS=?" ); pstmt.setInt( 1, user.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; for (int i = 0; i < roles.length; i++) { pstmt = transactionalConnection .prepareStatement( "INSERT INTO SEC_JT_USERS_ROLES (FK_USERS, FK_ROLES) VALUES (?,?)" ); pstmt.setInt( 1, user.getID() ); pstmt.setInt( 2, roles[i].getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; } } catch (SQLException e) { closeStatement( pstmt ); abortTransaction( transaction ); throw new GeneralSecurityException( "SQLRegistry.setRolesForUser() failed. Rollback performed. " + "Error message: " + e.getMessage() ); } } /** * Sets the <code>Role</code> s that a given <code>Group</code> is associated to directly * (i.e. not via inheritance). * * @param transaction * @param group * @param roles * @throws GeneralSecurityException */ public void setRolesForGroup( SecurityTransaction transaction, Group group, Role[] roles ) throws GeneralSecurityException { PreparedStatement pstmt = null; try { pstmt = transactionalConnection .prepareStatement( "DELETE FROM SEC_JT_GROUPS_ROLES WHERE FK_GROUPS=?" ); pstmt.setInt( 1, group.getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; for (int i = 0; i < roles.length; i++) { pstmt = transactionalConnection .prepareStatement( "INSERT INTO SEC_JT_GROUPS_ROLES (FK_GROUPS, FK_ROLES) VALUES (?,?)" ); pstmt.setInt( 1, group.getID() ); pstmt.setInt( 2, roles[i].getID() ); pstmt.executeUpdate(); pstmt.close(); pstmt = null; } } catch (SQLException e) { closeStatement( pstmt ); abortTransaction( transaction ); throw new GeneralSecurityException( "SQLRegistry.setRolesForGroup() failed. Rollback performed. " + "Error message: " + e.getMessage() ); } } /** * Initializes the <code>SQLRegistry</code> -instance according to the contents of the * submitted <code>Properties</code>. * * @param properties * @throws GeneralSecurityException */ public void initialize( Properties properties ) throws GeneralSecurityException { this.dbDriver = properties.getProperty( "driver" ); this.dbName = properties.getProperty( "url" ); this.dbUser = properties.getProperty( "user" ); this.dbPassword = properties.getProperty( "password" ); } /** * Signals the <code>SQLRegistry</code> that a new transaction begins. * * Only one transaction can be active at a time. * * * @param transaction * @throws GeneralSecurityException */ public synchronized void beginTransaction( SecurityTransaction transaction ) throws GeneralSecurityException { try { transactionalConnection = DBConnectionPool.getInstance().acquireConnection( dbDriver, dbName, dbUser, dbPassword ); // transactionalConnection.setAutoCommit(false); } catch (Exception e) { throw new GeneralSecurityException( e ); } } /** * Signals the <code>SQLRegistry</code> that the current transaction ends, i.e. the changes * made by the transaction are made persistent. * * @param transaction * @throws GeneralSecurityException */ public void commitTransaction( SecurityTransaction transaction ) throws GeneralSecurityException { try { transactionalConnection.commit(); } catch (SQLException e) { throw new GeneralSecurityException( "Committing of transaction failed: " + e.getMessage() ); } finally { try { DBConnectionPool.getInstance().releaseConnection( transactionalConnection, dbDriver, dbName, dbUser, dbPassword ); } catch (Exception e) { e.printStackTrace(); } } } /** * Signals the <code>SQLRegistry</code> that the current transaction shall be aborted. Changes * made during the transaction are undone. * * @param transaction * @throws GeneralSecurityException */ public void abortTransaction( SecurityTransaction transaction ) throws GeneralSecurityException { try { transactionalConnection.rollback(); } catch (SQLException e) { throw new GeneralSecurityException( "Aborting of transaction failed: " + e.getMessage() ); } finally { try { DBConnectionPool.getInstance().releaseConnection( transactionalConnection, dbDriver, dbName, dbUser, dbPassword ); } catch (Exception e) { e.printStackTrace(); } } } /** * Acquires a new <code>Connection</code>. If the given securityAccess is the exclusive * Read/Write-transaction holder, the transactionalConnection is returned, else a new * <code>Connection</code> is taken from the pool. * * @param securityAccess * @return * @throws GeneralSecurityException */ private Connection acquireLocalConnection( SecurityAccess securityAccess ) throws GeneralSecurityException { Connection con = null; if ( securityAccess instanceof SecurityTransaction ) { con = transactionalConnection; } else { try { con = DBConnectionPool.getInstance().acquireConnection( dbDriver, dbName, dbUser, dbPassword ); // con.setAutoCommit(false); } catch (Exception e) { throw new GeneralSecurityException( e ); } } return con; } /** * Releases a <code>Connection</code>. If the given securityAccess is the exclusive * Read/Write-transaction holder, nothing happens, else it is returned to the pool. * * @param securityAccess * @param con * @return * @throws GeneralSecurityException */ private void releaseLocalConnection( SecurityAccess securityAccess, Connection con ) throws GeneralSecurityException { if ( !( securityAccess instanceof SecurityTransaction ) ) { if ( con != null ) { try { DBConnectionPool.getInstance().releaseConnection( con, dbDriver, dbName, dbUser, dbPassword ); } catch (Exception e) { throw new GeneralSecurityException( e ); } } } } /** * Closes the given <code>Statement</code> if it is not null. * * @param stmt * @throws GeneralSecurityException */ private void closeStatement( Statement stmt ) throws GeneralSecurityException { if ( stmt != null ) { try { stmt.close(); } catch (SQLException e) { throw new GeneralSecurityException( e ); } } } /** * Closes the given <code>ResultSet</code> if it is not null. * * @param rs * @throws GeneralSecurityException */ private void closeResultSet( ResultSet rs ) throws GeneralSecurityException { if ( rs != null ) { try { rs.close(); } catch (SQLException e) { throw new GeneralSecurityException( e ); } } } /** * Retrieves an unused PrimaryKey-value for the given table. The table must have its PrimaryKey * in an Integer-field named 'ID'. * * @param table * @return */ private int getID( SecurityTransaction transaction, String table ) throws GeneralSecurityException { int id = 0; Connection con = acquireLocalConnection( transaction ); try { DataBaseIDGenerator idGenerator = IDGeneratorFactory.createIDGenerator( con, table, "ID" ); Object o = idGenerator.generateUniqueId(); if ( !( o instanceof Integer ) ) { throw new GeneralSecurityException( "Error generating new PrimaryKey for table '" + table + "'." ); } id = ( (Integer) o ).intValue(); } catch (SQLException e) { throw new GeneralSecurityException( e ); } finally { releaseLocalConnection( transaction, con ); } return id; } /** * Tries to build a <code>ComplexFilter</code> from the given string representation. * * @param constraints * @return * @throws GeneralSecurityException */ private ComplexFilter buildFilter( String constraints ) throws GeneralSecurityException { Filter filter = null; try { Document document = XMLTools.parse( new StringReader( constraints ) ); Element element = document.getDocumentElement(); filter = AbstractFilter.buildFromDOM( element ); } catch (FilterConstructionException e) { throw new GeneralSecurityException( "The stored constraint is not a valid filter: " + e.getMessage() ); } catch (Exception e) { throw new GeneralSecurityException( "Error parsing the stored constraint: " + e.getMessage() ); } if ( !( filter instanceof ComplexFilter ) ) { throw new GeneralSecurityException( "The stored constraint is not of type 'ComplexFilter'." ); } return (ComplexFilter) filter; } } /* ******************************************************************** Changes to this class. What the people have been up to: $Log: SQLRegistry.java,v $ Revision 1.23 2006/05/16 07:57:50 poth commentation completed useless imports removed ********************************************************************** */