net.unicon.alchemist.access.rdbms.RdbmsAccessBroker.java Source code

Java tutorial

Introduction

Here is the source code for net.unicon.alchemist.access.rdbms.RdbmsAccessBroker.java

Source

/*
 * Copyright (C) 2007 Unicon, Inc.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this distribution.  It is also available here:
 * http://www.fsf.org/licensing/licenses/gpl.html
 *
 * As a special exception to the terms and conditions of version
 * 2 of the GPL, you may redistribute this Program in connection
 * with Free/Libre and Open Source Software ("FLOSS") applications
 * as described in the GPL FLOSS exception.  You should have received
 * a copy of the text describing the FLOSS exception along with this
 * distribution.
 */

package net.unicon.alchemist.access.rdbms;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import javax.sql.DataSource;

import net.unicon.academus.api.AcademusDataSource;
import net.unicon.alchemist.access.AccessBroker;
import net.unicon.alchemist.access.AccessRule;
import net.unicon.alchemist.access.AccessType;
import net.unicon.alchemist.access.IAccessEntry;
import net.unicon.alchemist.access.Identity;
import net.unicon.alchemist.access.IdentityType;
import net.unicon.alchemist.access.Principal;
import net.unicon.alchemist.rdbms.Sequencer;

import org.dom4j.Attribute;
import org.dom4j.Element;

public class RdbmsAccessBroker extends AccessBroker {

    private static DataSource defaultDataSource = new AcademusDataSource();

    // Member Variables
    private DataSource dataSource = null;
    private int id;
    private boolean initialized = false;
    private Sequencer seq = null;
    private AccessType[] atypes;
    private String name;
    private boolean create;

    public RdbmsAccessBroker(String name, boolean create, DataSource dataSource, AccessType[] atypes, Element e) {
        super(e);
        this.dataSource = dataSource;
        this.seq = new Sequencer(dataSource, "RdbmsAccessBroker", 1);
        this.atypes = atypes;
        this.name = name;
        this.create = create;
    }

    public static AccessBroker parse(Element e) {

        // Assertions.
        if (e == null) {
            String msg = "Argument 'e [Element]' cannot be null.";
            throw new IllegalArgumentException(msg);
        }
        if (!e.getName().equals("access-broker")) {
            String msg = "Argument 'e [Element]' must be an <access-broker> " + "element.";
            throw new IllegalArgumentException(msg);
        }

        // Call parse() in the specified implementation.
        Attribute impl = e.attribute("impl");

        Attribute handle = e.attribute("handle");
        String name = handle.getText();

        // AccessTypes lookup
        Element el = (Element) e.selectSingleNode("access");
        if (el == null)
            throw new IllegalArgumentException("RdbmsAccessBroker requires the <access> element.");
        impl = el.attribute("impl");
        if (impl == null)
            throw new IllegalArgumentException("The element <access> must contain an 'impl' attribute.");
        AccessType[] accessTypes = null;
        try {
            accessTypes = (AccessType[]) Class.forName(impl.getValue()).getMethod("getInstances", null).invoke(null,
                    null);
        } catch (ClassNotFoundException ex1) {
            throw new RuntimeException("Could not find the class " + impl.getValue(), ex1);
        } catch (NoSuchMethodException ex2) {
            throw new RuntimeException("Could not find the Method 'getInstances' on class " + impl.getValue(), ex2);
        } catch (Exception ex3) {
            throw new RuntimeException("Unable to execute Method 'getInstances' on class " + impl.getValue(), ex3);
        }
        if (accessTypes == null || accessTypes.length == 0)
            throw new IllegalArgumentException("No AccessTypes found from <access> element declaration.");

        return getInstance(getDataSource(), name, accessTypes, true, e);

    }

    public static RdbmsAccessBroker getInstance(DataSource dataSource, String name, AccessType[] atypes,
            boolean create, Element e) {

        // assertions
        if (dataSource == null) {
            throw new IllegalArgumentException("Argument 'dataSource' cannot be null");
        }
        if (name == null) {
            throw new IllegalArgumentException("Argument 'name' cannot be null");
        }

        return new RdbmsAccessBroker(name, create, dataSource, atypes, e);
    }

    private void initialize() {

        String getAccessControllerSql = "SELECT ACCESS_CONTROLLER_ID FROM "
                + "ACCESS_CONTROLLER WHERE UPPER(NAME) = UPPER(?)";
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;

        int theId = -1;

        try {
            conn = dataSource.getConnection();
            pstmt = conn.prepareStatement(getAccessControllerSql);
            pstmt.setString(1, name);
            rs = pstmt.executeQuery();

            if (rs.next()) {
                theId = rs.getInt("ACCESS_CONTROLLER_ID");
            }
        } catch (SQLException sqle) {
            StringBuffer msg = new StringBuffer(
                    "Rdbms Access Broker failed to find " + "the instance of the accessController. \n")
                            .append(sqle.getMessage());
            throw new RuntimeException(msg.toString(), sqle);
        } finally {
            if (rs != null)
                closeResultSet(rs);
            if (pstmt != null)
                closeStatement(pstmt);
            if (conn != null)
                closeConnection(conn);
        }
        if (theId == -1) {
            // The AccessController doesn't exist...
            if (create) {
                // We're meant to create one...
                theId = getAccessBrokerUniqueId(dataSource);
                try {
                    conn = dataSource.getConnection();
                    pstmt = conn.prepareStatement(
                            "INSERT INTO ACCESS_CONTROLLER" + "(ACCESS_CONTROLLER_ID, NAME)  VALUES( ?, ?)");
                    pstmt.setInt(1, theId);
                    pstmt.setString(2, name);
                    pstmt.execute();
                } catch (SQLException sqle) {
                    String msg = "Rdbms Access Broker failed to create a new AccessController instance.";
                    throw new RuntimeException(msg, sqle);
                } finally {
                    if (pstmt != null)
                        closeStatement(pstmt);
                    if (conn != null)
                        closeConnection(conn);
                }
            } else {
                throw new RuntimeException("No ID found for name=" + name + " and did not specify to create.");
            }
        }

        this.id = theId;
        initialized = true;
    }

    protected int getId() {
        if (!initialized) {
            initialize();
        }
        return id;
    }

    public IAccessEntry setAccess(Identity principal, AccessRule[] rules, Object target) {

        // assertions
        if (principal == null) {
            String msg = "Argument 'principal' cannot be null.";
            throw new IllegalArgumentException(msg);
        }
        if (target == null) {
            String msg = "Argument 'target' cannot be null.";
            throw new IllegalArgumentException(msg);
        }
        if (rules == null) {
            String msg = "Argument 'rules' cannot be null.";
            throw new IllegalArgumentException(msg);
        }

        // check if the principal already has access for the target for the given domain
        // if exists, update the permissions
        // else insert user with permissions
        StringBuffer sql = new StringBuffer();
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        long accessEntryId = -1;

        try {

            conn = dataSource.getConnection();
            // reflection
            Class c = target.getClass();
            Method mthd = c.getDeclaredMethod("getUrl", null);
            String tUrl = (String) mthd.invoke(target, null);

            // get the accessEntryId
            sql.append("SELECT * FROM ACCESS_ENTRY WHERE UPPER(IDENTITY_NAME) = UPPER(?) "
                    + " AND UPPER(TARGET) = UPPER(?) AND ACCESS_CONTROLLER_ID = ? ");
            pstmt = conn.prepareStatement(sql.toString());
            pstmt.setString(1, principal.getId());
            pstmt.setString(2, tUrl);
            pstmt.setInt(3, getId());

            rs = pstmt.executeQuery();
            if (rs.next()) {
                accessEntryId = rs.getInt("access_Entry_Id");
            }
            sql.delete(0, sql.length());

            if (rules.length > 0) {
                // if the entry exists, delete from the table
                if (accessEntryId != -1) {
                    sql.append("DELETE FROM ACCESS_TYPES WHERE ACCESS_ENTRY_ID = ?");
                    pstmt = conn.prepareStatement(sql.toString());
                    pstmt.setLong(1, accessEntryId);
                    pstmt.executeUpdate();
                } else {
                    sql.delete(0, sql.length());
                    sql.append(
                            "INSERT INTO ACCESS_ENTRY (ACCESS_ENTRY_ID" + ", IDENTITY_TYPE, IDENTITY_NAME, TARGET"
                                    + ", ACCESS_CONTROLLER_ID) VALUES ( ?, ?, ?, ?, ?)");
                    pstmt = conn.prepareStatement(sql.toString());
                    //accessEntryId = getAccessEntryUniqueId();
                    accessEntryId = seq.next();
                    pstmt.setLong(1, accessEntryId);
                    pstmt.setInt(2, principal.getType().toInt());
                    pstmt.setString(3, principal.getId());
                    pstmt.setString(4, tUrl);
                    pstmt.setInt(5, getId());
                    pstmt.executeUpdate();
                }
                if (pstmt != null)
                    closeStatement(pstmt);

                for (int i = 0; i < rules.length; i++) {
                    sql.delete(0, sql.length());
                    sql.append(
                            "INSERT INTO ACCESS_TYPES(ACCESS_ENTRY_ID" + ", ACCESS_TYPE, STATUS) VALUES (?, ?, ?)");
                    pstmt = conn.prepareStatement(sql.toString());
                    pstmt.setLong(1, accessEntryId);
                    pstmt.setInt(2, rules[i].getAccessType().toInt());
                    pstmt.setString(3, rules[i].getStatus() ? "T" : "F");
                    pstmt.executeUpdate();
                    if (pstmt != null)
                        pstmt.close();
                }
                pstmt = null;
            }
            // if the type array is empty, remove all the access from the
            // accessEntry and accessType table for the given principal and target
            else {
                sql.append("DELETE FROM ACCESS_TYPES WHERE ACCESS_ENTRY_ID = ?");
                pstmt = conn.prepareStatement(sql.toString());
                pstmt.setLong(1, accessEntryId);
                pstmt.setLong(2, accessEntryId);
                pstmt.execute();
                if (pstmt != null)
                    closeStatement(pstmt);
                sql.delete(0, sql.length());
                sql.append("DELETE FROM ACCESS_ENTRY WHERE ACCESS_ENTRY_ID = ?");
                pstmt = conn.prepareStatement(sql.toString());
                pstmt.setLong(1, accessEntryId);
                pstmt.setLong(2, accessEntryId);
                pstmt.execute();
            }

        } catch (SQLException se) {
            throw new RuntimeException("Access Controller was unsuccessful in tying to " + "set access.", se);
        } catch (Throwable t) {
            throw new RuntimeException("Access Controller was unsuccessful in tying to " + "set access.", t);
        } finally {
            if (rs != null)
                closeResultSet(rs);
            if (pstmt != null)
                closeStatement(pstmt);
            if (conn != null)
                closeConnection(conn);
        }
        return new AccessEntryImpl(principal, rules, target);
    }

    // TODO to be completed
    // this method will set access for all the identities chosen in the selection basket
    /* public synchronized IAccessEntry[] setAccess(Identity[] principal, List[] types,
        Object target) {
        
    IAccessEntry[] rslt = new IAccessEntry[principal.length];
        
    // assertions
    if (principal == null) {
        String msg = "Argument 'principal' cannot be null.";
        throw new IllegalArgumentException(msg);
    }
    if (target == null) {
        String msg = "Argument 'target' cannot be null.";
        throw new IllegalArgumentException(msg);
    }
    if (types == null) {
        String msg = "Argument 'types' cannot be null.";
        throw new IllegalArgumentException(msg);
    }
    if (principal.length != types.length) {
        String msg = "Argument 'principal' and 'types' must have the same number of elements.";
        throw new IllegalArgumentException(msg);
    }
        
    Connection conn = getConnection();
    PreparedStatement pstmt = null;
    ResultSet rs = null;
        
        
    // delete all the access_types for the given identities and target
    StringBuffer sql = new StringBuffer("delete from access_types where " +
          "access_entry_id in (select access_entry_id from " +
          "access_entry where identity_name in (");
        
    for(int i = 0; i < principal.length; i++){
        if(i == principal.length - 1){
            sql.append(" ? ");
        }else{
            sql.append(" ? , ");
        }
    }
        
    sql.append(") and target = ? and access_controller_id = ? ) ");
        
    try{
        //  reflection
        Class c = target.getClass();
        Method mthd = c.getDeclaredMethod("getUrl", null);
        String tUrl = (String)mthd.invoke(target, null);
        
        pstmt = conn.prepareStatement(sql.toString());
        
        int index = 1;
        // set the parameters for the delete all accessTypes
        for(int i = 0; i < principal.length; i++){
            pstmt.setString(index++, principal[i].getId());
        }
        
        pstmt.setString(index++, tUrl);
        pstmt.setInt(index++, this.id);
        pstmt.executeUpdate();
        if(pstmt != null) pstmt.close();
        sql.delete(0, sql.length());
            
        // select all the identities that are already in the database
        sql.append("select distinct identity_name from access_entry where " +
              "upper(target) = upper(?) and access_controller_id = ? ; ");
        pstmt = conn.prepareStatement(sql.toString());
            
        // set parameters for select all identities from the DB for the given target
        pstmt.setString(1, tUrl);
        pstmt.setInt(2, this.id);
        rs = pstmt.executeQuery();
        
        List identities = new LinkedList();
        while(rs.next()){
            identities.add(rs.getString("identity_name"));
        }
        
        // insert identities in access_entry table and accesstypes in accessTypes table
        List accessTypes = null;
        pstmt = conn.prepareStatement("");
        PreparedStatement tempPstmt = null;
        for(int i = 0; i < principal.length; i++){
            accessTypes = types[i];
            if(accessTypes.size() > 0){
                int accessEntryId = seq.next();
                if( ! identities.contains(principal[i].getId())){
                    sql.delete(0, sql.length());
                    sql.append(" insert into access_entry (access_entry_id, identity_type")
                    .append(", identity_name, target, access_controller_id) select ?, ?")
                    .append(", ?, ?, ? ");
        
                    tempPstmt = conn.prepareStatement(sql.toString());
                    tempPstmt.setInt(1, accessEntryId);
                    tempPstmt.setInt(2, principal[i].getType().toInt());
                    tempPstmt.setString(3, principal[i].getId());
                    tempPstmt.setString(4, tUrl);
                    tempPstmt.setInt(5, this.id);
                    pstmt.addBatch(tempPstmt.toString());
                    //where  not exists(select * from access_entry " +
                    //"where upper(identity_name) = upper(?) and " +
                    //"upper(target) = upper(?) and access_controller_id = ?); ");
                }
                for(int j = 0; j < accessTypes.size(); j++){
                    sql.delete(0, sql.length());
        
                    sql.append("insert into access_types (access_entry_id, access_type)");
                    pstmt.addBatch(tempPstmt.toString());
                        
                    sql.delete(0, sql.length());
                    sql.append("select access_entry_id , ? from access_entry where " +
                          "Upper(identity_name)")
                        .append(" = Upper(?) and upper(target) = upper(?) and " +
                              "access_controller_id = ?");
        
                    tempPstmt = conn.prepareStatement(sql.toString());
                    tempPstmt.setInt(1, ((AccessType)accessTypes.get(j)).toInt());
                    tempPstmt.setString(2, principal[i].getId());
                    tempPstmt.setString(3, tUrl);
                    tempPstmt.setInt(4, this.id);
                    pstmt.addBatch(tempPstmt.toString());
                }
            }else{
                sql.delete(0, sql.length());
        
                sql.append("delete from access_entry where upper(identity_name) = upper(?)")
                   .append("and upper(target) = upper(?) and access_controller_id = ?  ");
        
                tempPstmt = conn.prepareStatement(sql.toString());
                tempPstmt.setString(1, principal[i].getId());
                tempPstmt.setString(2, tUrl);
                tempPstmt.setInt(3, this.id);
                pstmt.addBatch(tempPstmt.toString());
            }
        }
        
        pstmt.executeBatch();
        
    }catch(SQLException se){
        throw new RuntimeException("Access Broker was not able to set access. ", se);
    }catch(Throwable t){
        throw new RuntimeException("Access Broker was not able to get " +
              "the url for the given target. ", t);
    }
        
    return rslt;
     }*/

    public void removeAccess(IAccessEntry[] entries) {
        // assertions
        if (entries == null) {
            String msg = "Argument 'entries' cannot be null.";
            throw new IllegalArgumentException(msg);
        }

        StringBuffer selectIdSql = new StringBuffer();
        StringBuffer deleteSql = new StringBuffer();
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        int accessEntryId = -1;

        if (entries.length == 0) {
            return;
        }

        try {
            conn = dataSource.getConnection();
            // reflection
            Class c = entries[0].getTarget().getClass();
            Method mthd = c.getDeclaredMethod("getUrl", null);
            String tUrl = (String) mthd.invoke(entries[0].getTarget(), null);

            // get the accessEntryIds
            selectIdSql.append("SELECT * FROM ACCESS_ENTRY WHERE UPPER(IDENTITY_NAME) IN ( ");
            for (int i = 0; i < (entries.length - 1); i++) {
                selectIdSql.append(" ? , ");
            }
            selectIdSql.append(" ? ) ");
            selectIdSql.append(" AND UPPER(TARGET) = UPPER(?) AND ACCESS_CONTROLLER_ID = ? ");

            pstmt = conn.prepareStatement(selectIdSql.toString());
            int i = 0;
            for (i = 0; i < entries.length; i++) {
                pstmt.setString(i + 1, entries[i].getIdentity().getId().toUpperCase());
            }
            pstmt.setString(++i, tUrl);
            pstmt.setInt(++i, getId());
            rs = pstmt.executeQuery();

            List accessEntries = new LinkedList();
            while (rs.next()) {
                accessEntries.add(rs.getObject("access_Entry_Id"));
            }
            if (rs != null)
                closeResultSet(rs);

            if (accessEntries.size() == 0) {
                return;
            }
            StringBuffer params = new StringBuffer();
            for (i = 0; i < (accessEntries.size() - 1); i++) {
                params.append(" ? , ");
            }
            params.append(" ? ) ");

            deleteSql.append("DELETE FROM ACCESS_TYPES WHERE ACCESS_ENTRY_ID IN ( ");
            deleteSql.append(params);

            if (pstmt != null)
                closeStatement(pstmt);
            pstmt = conn.prepareStatement(deleteSql.toString());

            int num = accessEntries.size();
            for (i = 0; i < accessEntries.size(); i++) {
                pstmt.setObject(i + 1, accessEntries.get(i));
            }
            pstmt.execute();
            if (pstmt != null)
                pstmt.close();
            pstmt = null;

            deleteSql.delete(0, deleteSql.length());
            deleteSql.append("DELETE FROM ACCESS_ENTRY WHERE ACCESS_ENTRY_ID IN ( ");
            deleteSql.append(params);
            pstmt = conn.prepareStatement(deleteSql.toString());
            for (i = 0; i < accessEntries.size(); i++) {
                pstmt.setObject(i + 1, accessEntries.get(i));
            }
            pstmt.execute();

        } catch (SQLException se) {
            throw new RuntimeException("Access Controller was unsuccessful in trying to " + "remove access.", se);
        } catch (Throwable t) {
            throw new RuntimeException("Access Controller was unsuccessful in trying to " + "remove access.", t);
        } finally {
            if (pstmt != null)
                closeStatement(pstmt);
            if (conn != null)
                closeConnection(conn);
        }

    }

    public IAccessEntry getEntry(Identity principal, Object r) {

        // assertions
        if (principal == null) {
            String msg = "Argument 'principal' cannot be null.";
            throw new IllegalArgumentException(msg);
        }
        if (r == null) {
            String msg = "Argument 'r [Object]' cannot be null.";
            throw new IllegalArgumentException(msg);
        }

        IAccessEntry rslt = null;
        ArrayList rules = new ArrayList();

        String getAccessSql = "SELECT ACCESS_TYPE, STATUS FROM ACCESS_ENTRY AC"
                + ", ACCESS_TYPES AT WHERE AT.ACCESS_ENTRY_ID = AC.ACCESS_ENTRY_ID "
                + "AND AC.ACCESS_CONTROLLER_ID = ? AND UPPER(IDENTITY_NAME) "
                + "= UPPER(?) AND UPPER(TARGET) = UPPER(?)";
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;

        try {

            conn = dataSource.getConnection();
            // reflection
            Class c = r.getClass();
            Method mthd = c.getDeclaredMethod("getUrl", null);
            String tUrl = (String) mthd.invoke(r, null);

            pstmt = conn.prepareStatement(getAccessSql);
            pstmt.setInt(1, getId());
            pstmt.setString(2, principal.getId());
            pstmt.setString(3, tUrl);
            rs = pstmt.executeQuery();

            while (rs.next()) {
                rules.add(new AccessRule(getAccessType(rs.getInt("Access_Type")),
                        rs.getString("status").equalsIgnoreCase("T") ? true : false));
            }
            if (rules.size() > 0) {
                rslt = new AccessEntryImpl(principal, (AccessRule[]) rules.toArray(new AccessRule[rules.size()]),
                        r);
            }

        } catch (SQLException se) {
            throw new RuntimeException(
                    "Access Controller was unsuccessful in getting " + "the AccessRules for the given principal.",
                    se);
        } catch (Throwable t) {
            throw new RuntimeException(
                    "Access Controller was unsuccessful in getting " + "the AccessRules for the given principal.",
                    t);
        } finally {
            if (rs != null)
                closeResultSet(rs);
            if (pstmt != null)
                closeStatement(pstmt);
            if (conn != null)
                closeConnection(conn);
        }
        return rslt;

    }

    public IAccessEntry[] getEntries(Principal p, AccessRule[] rules) {

        // assertions
        if (p == null) {
            String msg = "Argument 'p [Principal]' cannot be null.";
            throw new IllegalArgumentException(msg);
        }
        if (rules == null) {
            String msg = "Argument 'rules' cannot be null.";
            throw new IllegalArgumentException(msg);
        }

        IAccessEntry[] rslt = new IAccessEntry[0];
        List entries = new ArrayList();
        StringBuffer getTargetSql = new StringBuffer("SELECT * FROM " + "ACCESS_ENTRY AE, ACCESS_TYPES AT WHERE "
                + "AE.ACCESS_CONTROLLER_ID = ? AND UPPER(IDENTITY_NAME) IN ( ");
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        StringBuffer params = new StringBuffer();
        Identity[] principals = p.getIdentities();
        int accessEntryId = -1;

        try {
            conn = dataSource.getConnection();

            for (int i = 0; i < principals.length; i++) {
                if (i == principals.length - 1) {
                    getTargetSql.append(" ? ");
                } else {
                    getTargetSql.append(" ? , ");
                }
            }
            getTargetSql.append(" )");

            getTargetSql.append(" AND AE.ACCESS_ENTRY_ID = AT.ACCESS_ENTRY_ID ");
            //  if types is empty, get all of them.
            if (rules.length > 0) {
                getTargetSql.append(" AND ( ");
                for (int i = 0; i < rules.length; i++) {
                    getTargetSql.append(" (ACCESS_TYPE = ? AND STATUS = ?) ");
                    if (i != rules.length - 1) {
                        getTargetSql.append(" OR ");
                    }
                }
                getTargetSql.append(" ) ");
            }

            getTargetSql.append(" ORDER BY AE.ACCESS_ENTRY_ID ");
            pstmt = conn.prepareStatement(getTargetSql.toString());
            pstmt.setInt(1, getId());
            for (int i = 0; i < principals.length; i++) {
                pstmt.setString(i + 2, principals[i].getId().toUpperCase());
            }

            int initialIndex = principals.length + 2;
            for (int i = 0; i < rules.length; i++) {
                pstmt.setInt(initialIndex + (i * 2), rules[i].getAccessType().toInt());
                pstmt.setString(initialIndex + (i * 2) + 1, rules[i].getStatus() ? "T" : "F");
            }

            rs = pstmt.executeQuery();
            List rule = new ArrayList();
            AccessRule tempRule = null;
            if (rs.next()) {
                String principal = rs.getString("identity_name");
                IdentityType idType = IdentityType.getInstance(rs.getInt("identity_type"));
                String target = rs.getString("target");
                accessEntryId = rs.getInt("access_Entry_id");
                Object targetObject = getTargetObject(target);
                rule.add(new AccessRule(getAccessType(rs.getInt("Access_Type")),
                        rs.getString("status").equalsIgnoreCase("T") ? true : false));
                while (rs.next()) {
                    if (rs.getInt("access_entry_id") == accessEntryId) {
                        tempRule = new AccessRule(getAccessType(rs.getInt("Access_Type")),
                                rs.getString("status").equalsIgnoreCase("T") ? true : false);
                        if (!rule.contains(tempRule)) {
                            rule.add(tempRule);
                        }
                    } else {
                        // targets could be repeated in case of shared
                        // check if the entry already exists, if it does, update the access_types
                        entries.add(new AccessEntryImpl(new Identity(principal, idType),
                                (AccessRule[]) rule.toArray(new AccessRule[0]), targetObject));
                        rule.clear();
                        principal = rs.getString("identity_name");
                        idType = IdentityType.getInstance(rs.getInt("identity_type"));
                        target = rs.getString("target");
                        accessEntryId = rs.getInt("access_Entry_id");
                        targetObject = getTargetObject(target);
                        rule.add(new AccessRule(getAccessType(rs.getInt("Access_Type")),
                                rs.getString("status").equalsIgnoreCase("T") ? true : false));
                    }
                }
                if (rule.size() > 0) {
                    entries.add(new AccessEntryImpl(new Identity(principal, idType),
                            (AccessRule[]) rule.toArray(new AccessRule[0]), targetObject));
                    rule.clear();
                }
            }
            rslt = (IAccessEntry[]) entries.toArray(new IAccessEntry[entries.size()]);

        } catch (IllegalArgumentException iae) {
            //TODO this needs to be addressed properly
            // this is coming from the getTargetObject. The factory for the given URL could not be created.
            // delete the entry from the database.
            try {
                if (rs != null)
                    rs.close();
                rs = null;
                if (pstmt != null)
                    closeStatement(pstmt);
                pstmt = conn.prepareStatement("DELETE FROM ACCESS_TYPES WHERE ACCESS_ENTRY_ID = " + accessEntryId);
                pstmt.execute();
                closeStatement(pstmt);
                pstmt = conn.prepareStatement("DELETE FROM ACCESS_ENTRY WHERE ACCESS_ENTRY_ID = " + accessEntryId);
                pstmt.execute();

            } catch (SQLException s) {
                throw new RuntimeException("Access Controller was unsuccessful in getting the "
                        + "targets for the given identity_name and Access_Type.", s);
            }
        } catch (SQLException se) {
            throw new RuntimeException("Access Controller was unsuccessful in getting the "
                    + "targets for the given identity_name and Access_Type.", se);
        } finally {
            if (rs != null)
                closeResultSet(rs);
            if (pstmt != null)
                closeStatement(pstmt);
            if (conn != null)
                closeConnection(conn);
        }
        return rslt;

    }

    /* (non-Javadoc)
     * @see net.unicon.academus.access.AccessBroker#getEntries(net.unicon.academus.access.ITarget, net.unicon.academus.access.AccessType[])
     */
    public IAccessEntry[] getEntries(Object r, AccessRule[] rules) {

        //      assertions
        if (r == null) {
            String msg = "Argument 'r [Object]' cannot be null.";
            throw new IllegalArgumentException(msg);
        }
        if (rules == null) {
            String msg = "Argument 'types' cannot be null.";
            throw new IllegalArgumentException(msg);
        }

        IAccessEntry[] rslt = new IAccessEntry[0];
        List entries = new ArrayList();
        StringBuffer getTargetSql = new StringBuffer("SELECT * FROM " + "ACCESS_ENTRY AE, ACCESS_TYPES AT WHERE "
                + "AE.ACCESS_CONTROLLER_ID = ? AND UPPER(TARGET) = UPPER(?) "
                + "AND AE.ACCESS_ENTRY_ID = AT.ACCESS_ENTRY_ID ");
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        StringBuffer params = new StringBuffer();

        try {

            conn = dataSource.getConnection();

            // reflection
            Class c = r.getClass();
            Method mthd = c.getDeclaredMethod("getUrl", null);
            String tUrl = (String) mthd.invoke(r, null);

            //  if types is empty, get all of them.
            if (rules.length > 0) {
                getTargetSql.append(" AND ( ");
                for (int i = 0; i < rules.length; i++) {
                    getTargetSql.append(" (ACCESS_TYPE = ? AND STATUS = ?) ");
                    if (i != rules.length - 1) {
                        getTargetSql.append(" OR ");
                    }
                }
                getTargetSql.append(" ) ");
            }

            getTargetSql.append(" ORDER BY IDENTITY_NAME, TARGET");
            pstmt = conn.prepareStatement(getTargetSql.toString());
            pstmt.setInt(1, getId());
            pstmt.setString(2, tUrl);

            int initialIndex = 3;
            for (int i = 0; i < rules.length; i++) {
                pstmt.setInt(initialIndex + (i * 2), rules[i].getAccessType().toInt());
                pstmt.setString(initialIndex + (i * 2) + 1, rules[i].getStatus() ? "T" : "F");
            }

            rs = pstmt.executeQuery();

            List rule = new ArrayList();
            String principal = null;
            int accessEntryId = 0;
            int identityType = 0;
            if (rs.next()) {
                // get information for the first item
                principal = rs.getString("identity_name");
                accessEntryId = rs.getInt("access_Entry_id");
                identityType = rs.getInt("identity_type");
                rule.add(new AccessRule(getAccessType(rs.getInt("Access_Type")),
                        rs.getString("status").equalsIgnoreCase("T") ? true : false));
                while (rs.next()) {
                    if (rs.getInt("access_entry_id") == accessEntryId) {
                        rule.add(new AccessRule(getAccessType(rs.getInt("Access_Type")),
                                rs.getString("status").equalsIgnoreCase("T") ? true : false));
                    } else {
                        entries.add(
                                new AccessEntryImpl(new Identity(principal, IdentityType.getInstance(identityType)),
                                        (AccessRule[]) rule.toArray(new AccessRule[0]), r));
                        rule.clear();
                        principal = rs.getString("identity_name");
                        accessEntryId = rs.getInt("access_Entry_id");
                        identityType = rs.getInt("identity_type");
                        rule.add(new AccessRule(getAccessType(rs.getInt("Access_Type")),
                                rs.getString("status").equalsIgnoreCase("T") ? true : false));
                    }
                }
                if (rule.size() > 0) {
                    entries.add(new AccessEntryImpl(new Identity(principal, IdentityType.getInstance(identityType)),
                            (AccessRule[]) rule.toArray(new AccessRule[0]), r));
                    rule.clear();
                }
            }
            rslt = (IAccessEntry[]) entries.toArray(new IAccessEntry[entries.size()]);

        } catch (SQLException se) {
            throw new RuntimeException("Access Controller was unsuccessful in getting the "
                    + "targets for the given identity_name and Access_Type.", se);
        } catch (Throwable t) {
            throw new RuntimeException("Access Controller was unsuccessful in getting the "
                    + "targets for the given identity_name and Access_Type.", t);
        } finally {
            if (rs != null)
                closeResultSet(rs);
            if (pstmt != null)
                closeStatement(pstmt);
            if (conn != null)
                closeConnection(conn);
        }
        return rslt;

    }

    public IAccessEntry[] getEntries() {

        IAccessEntry[] rslt = new IAccessEntry[0];
        List entries = new ArrayList();
        StringBuffer getTargetSql = new StringBuffer(
                "Select * from Access_Entry ae" + ", Access_types at where ae.Access_Controller_ID = ? and "
                        + " ae.access_entry_id = at.access_entry_id ");
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        StringBuffer params = new StringBuffer();

        try {

            conn = dataSource.getConnection();

            getTargetSql.append(" order by identity_name, target");
            pstmt = conn.prepareStatement(getTargetSql.toString());
            pstmt.setInt(1, getId());

            rs = pstmt.executeQuery();

            List rule = new ArrayList();
            String principal = null;
            String target = null;
            int accessEntryId = 0;
            int identityType = 0;
            Object targetObject = null;
            if (rs.next()) {
                // get information for the first item
                principal = rs.getString("identity_name");
                accessEntryId = rs.getInt("access_Entry_id");
                identityType = rs.getInt("identity_type");
                target = rs.getString("target");
                targetObject = getTargetObject(target);
                rule.add(new AccessRule(getAccessType(rs.getInt("Access_Type")),
                        rs.getString("status").equalsIgnoreCase("T") ? true : false));
                while (rs.next()) {
                    if (rs.getInt("access_entry_id") == accessEntryId) {
                        rule.add(new AccessRule(getAccessType(rs.getInt("Access_Type")),
                                rs.getString("status").equalsIgnoreCase("T") ? true : false));
                    } else {
                        entries.add(
                                new AccessEntryImpl(new Identity(principal, IdentityType.getInstance(identityType)),
                                        (AccessRule[]) rule.toArray(new AccessRule[0]), targetObject));
                        rule.clear();
                        principal = rs.getString("identity_name");
                        accessEntryId = rs.getInt("access_Entry_id");
                        identityType = rs.getInt("identity_type");
                        rule.add(new AccessRule(getAccessType(rs.getInt("Access_Type")),
                                rs.getString("status").equalsIgnoreCase("T") ? true : false));
                    }
                }
                if (rule.size() > 0) {
                    entries.add(new AccessEntryImpl(new Identity(principal, IdentityType.getInstance(identityType)),
                            (AccessRule[]) rule.toArray(new AccessRule[0]), targetObject));
                    rule.clear();
                }
            }
            rslt = (IAccessEntry[]) entries.toArray(new IAccessEntry[entries.size()]);

        } catch (SQLException se) {
            throw new RuntimeException("Access Controller was unsuccessful in getting the "
                    + "targets for the given identity_name and Access_Type.", se);
        } catch (Throwable t) {
            throw new RuntimeException("Access Controller was unsuccessful in getting the "
                    + "targets for the given identity_name and Access_Type.", t);
        } finally {
            if (rs != null)
                closeResultSet(rs);
            if (pstmt != null)
                closeStatement(pstmt);
            if (conn != null)
                closeConnection(conn);
        }
        return rslt;

    }

    private static void closeResultSet(ResultSet rs) {
        if (rs == null) {
            return;
        }

        try {
            rs.close();
            rs = null;
        } catch (Throwable t) {
            throw new RuntimeException("DB Connection error.", t);
        }
    }

    private static void closeStatement(Statement stmt) {

        if (stmt == null) {
            return;
        }

        try {
            stmt.close();
            stmt = null;
        } catch (Throwable t) {
            throw new RuntimeException("DB Connection error.", t);
        }
    }

    private static void closeConnection(Connection conn) {

        if (conn == null) {
            return;
        }

        try {
            conn.close();
            conn = null;
        } catch (Throwable t) {
            throw new RuntimeException("DB Connection error.", t);
        }
    }

    public static Object getTargetObject(String url) throws RuntimeException {

        // Assertions.
        if (url == null || url.trim().equals("")) {
            throw new IllegalArgumentException("getTargetObject: The Factory" + " Url must not be null or empty.");
        }

        Object rf = null;

        // URL: protocol://classname/parameters
        // Tokens:
        // 0 = "protocol"
        // 1 = empty string
        // 2 = classname
        // 3+ = parameters
        String[] tokens = url.split("/", 4);
        if (tokens.length < 3)
            throw new IllegalArgumentException("The URL is not correctly formatted: " + url);

        try {
            Class c = Class.forName(tokens[2]);
            Method mthd = c.getDeclaredMethod("fromUrl", new Class[] { String.class });
            rf = mthd.invoke(null, new Object[] { url });
        } catch (Exception e) {
            e.printStackTrace();
        }

        // Make sure a valid response was created.
        // TODO this needs to be handled differently.
        // the quick fix is to remove the entry that is causing the problem.
        if (rf == null) {
            String msg = "Unable to construct the target object from the " + "specified url:  " + url;
            //throw new RuntimeException(msg);
            throw new IllegalArgumentException(msg);
        }

        return rf;
    }

    public static void bootstrap(DataSource ds) {
        if (ds == null)
            throw new IllegalArgumentException("Argument 'ds' cannot be null.");

        defaultDataSource = ds;
    }

    private static DataSource getDataSource() {
        if (defaultDataSource == null) {
            defaultDataSource = new AcademusDataSource();
        }

        return defaultDataSource;
    }

    //  returns a unique AccessObject for the given factory.
    private static synchronized int getAccessBrokerUniqueId(DataSource dataSource) {

        // Assertions.
        if (dataSource == null) {
            String msg = "Argument 'dataSource' cannot be null.";
            throw new IllegalArgumentException(msg);
        }

        int rslt = 0;

        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {

            conn = dataSource.getConnection();
            pstmt = conn.prepareStatement("select max(Access_Controller_ID) " + "from Access_Controller");
            rs = pstmt.executeQuery();

            if (rs.next()) {
                rslt = rs.getInt(1) + 1;
            } else {
                rslt = 1;
            }

        } catch (SQLException sqle) {
            String msg = "Rdbms Access Broker failed to evaluate the next controller id.";
            throw new RuntimeException(msg, sqle);
        } finally {
            if (rs != null)
                closeResultSet(rs);
            if (pstmt != null)
                closeStatement(pstmt);
            if (conn != null)
                closeConnection(conn);
        }

        return rslt;

    }

    private AccessType getAccessType(int id) {
        AccessType rslt = null;
        for (int i = 0; rslt == null && i < atypes.length; i++)
            if (atypes[i] != null && atypes[i].compareInt(id))
                rslt = atypes[i];

        if (rslt == null)
            throw new IllegalArgumentException("Unable to locate a matching AccessType for id: " + id);
        return rslt;
    }

}