You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by sm...@apache.org on 2014/10/22 17:44:40 UTC

[21/51] [partial] Rename packages from org.openldap.fortress to org.apache.directory.fortress.core. Change default suffix to org.apache. Switch default ldap api from unbound to apache ldap.

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/687ee1ad/src/main/java/org/apache/directory/fortress/core/rbac/RoleUtil.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/rbac/RoleUtil.java b/src/main/java/org/apache/directory/fortress/core/rbac/RoleUtil.java
new file mode 100755
index 0000000..67ce3c5
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/rbac/RoleUtil.java
@@ -0,0 +1,358 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.fortress.core.rbac;
+
+
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.jgrapht.graph.SimpleDirectedGraph;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.directory.fortress.core.GlobalIds;
+import org.apache.directory.fortress.core.SecurityException;
+import org.apache.directory.fortress.core.ValidationException;
+import org.apache.directory.fortress.core.util.attr.VUtil;
+import org.apache.directory.fortress.core.util.cache.Cache;
+import org.apache.directory.fortress.core.util.cache.CacheMgr;
+
+
+/**
+ * This utility wraps {@link org.apache.directory.fortress.core.rbac.HierUtil} methods to provide hierarchical functionality for the {@link org.apache.directory.fortress.core.rbac.Role} data set.
+ * The {@code cn=Hierarchies, ou=Roles} data is stored within a cache, {@link #roleCache}, contained within this class.  The parent-child edges are contained in LDAP,
+ * in {@code ftParents} attribute.  The ldap data is retrieved {@link org.apache.directory.fortress.core.rbac.RoleP#getAllDescendants(String)} and loaded into {@code org.jgrapht.graph.SimpleDirectedGraph}.
+ * The graph...
+ * <ol>
+ * <li>is stored as singleton in this class with vertices of {@code String}, and edges, as {@link Relationship}s</li>
+ * <li>utilizes open source library, see <a href="http://www.jgrapht.org/">JGraphT</a>.</li>
+ * <li>contains a general hierarchical data structure i.e. allows multiple inheritance with parents.</li>
+ * <li>is a simple directed graph thus does not allow cycles.</li>
+ * </ol>
+ * After update is performed to ldap, the singleton is refreshed with latest info.
+ * <p/>
+ * Static methods on this class are intended for use by other Fortress classes, i.e. {@link org.apache.directory.fortress.core.rbac.dao.UserDAO} and {@link org.apache.directory.fortress.core.rbac.dao.PermDAO}
+ * and cannot be directly invoked by outside programs.
+ * <p/>
+ * This class contains singleton that can be updated but is thread safe.
+ * <p/>
+ *
+ * @author Shawn McKinney
+ */
+public final class RoleUtil
+{
+    private static final Cache roleCache;
+    private static final RoleP roleP = new RoleP();
+    private static final String CLS_NM = RoleUtil.class.getName();
+    private static final Logger LOG = LoggerFactory.getLogger( CLS_NM );
+
+    /**
+     * Initialize the Role hierarchies.  This will read the {@link org.apache.directory.fortress.core.rbac.Hier} data set from ldap and load into
+     * the JGraphT simple digraph that referenced statically within this class.
+     */
+    static
+    {
+        CacheMgr cacheMgr = CacheMgr.getInstance();
+        roleCache = cacheMgr.getCache( "fortress.roles" );
+    }
+
+
+    /**
+     * Used to determine if one {@link org.apache.directory.fortress.core.rbac.Role} is the parent of another.  This method
+     * will call recursive routine {@link #getAscendants(String, String)} to walk the {@code org.jgrapht.graph.SimpleDirectedGraph} data structure
+     * returning flag indicating if parent-child relationship is valid.
+     *
+     * @param child  maps to logical {@link org.apache.directory.fortress.core.rbac.Role#name} on 'ftRls' object class.
+     * @param parent maps to logical {@link org.apache.directory.fortress.core.rbac.Role#name} on 'ftRels' object class.
+     * @param contextId maps to sub-tree in DIT, for example ou=contextId, dc=jts, dc = com.
+     * @return boolean result, 'true' indicates parent/child relationship exists.
+     */
+    public static boolean isParent( String child, String parent, String contextId )
+    {
+        boolean result = false;
+        Set<String> parents = getAscendants( child, contextId );
+        if ( parents != null && parents.size() > 0 )
+        {
+            result = parents.contains( parent.toUpperCase() );
+        }
+        return result;
+    }
+
+
+    /**
+     * Recursively traverse the {@link org.apache.directory.fortress.core.rbac.Role} graph and return all of the descendants of a given node {@link org.apache.directory.fortress.core.rbac.Role#name}.
+     *
+     * @param roleName {@link org.apache.directory.fortress.core.rbac.Role#name} on 'ftRls' object class.
+     * @param contextId maps to sub-tree in DIT, for example ou=contextId, dc=jts, dc = com.
+     * @return Set of Role names are descendants {@link org.apache.directory.fortress.core.rbac.Role}s of given parent.
+     */
+    public static Set<String> getDescendants( String roleName, String contextId )
+    {
+        return HierUtil.getDescendants( roleName.toUpperCase(), getGraph( contextId ) );
+    }
+
+
+    /**
+     * Traverse the {@link org.apache.directory.fortress.core.rbac.Role} graph and return all children (direct descendants) of a given parent node {@link org.apache.directory.fortress.core.rbac.Role#name}.
+     *
+     * @param roleName {@link org.apache.directory.fortress.core.rbac.Role#name} on 'ftRls' object class.
+     * @param contextId maps to sub-tree in DIT, for example ou=contextId, dc=jts, dc = com.
+     * @return Set of Role names are children {@link org.apache.directory.fortress.core.rbac.Role}s of given parent.
+     */
+    public static Set<String> getChildren( String roleName, String contextId )
+    {
+        return HierUtil.getChildren( roleName.toUpperCase(), getGraph( contextId ) );
+    }
+
+
+    /**
+     * Recursively traverse the hierarchical role graph and return all of the ascendants of a given role.
+     *
+     * @param roleName maps to logical {@link org.apache.directory.fortress.core.rbac.Role#name} on 'ftRls' object class.
+     * @param contextId maps to sub-tree in DIT, for example ou=contextId, dc=jts, dc = com.
+     * @return Set of Role names that are ascendants of given child.
+     */
+    public static Set<String> getAscendants( String roleName, String contextId )
+    {
+        return HierUtil.getAscendants( roleName.toUpperCase(), getGraph( contextId ) );
+    }
+
+
+    /**
+     * Traverse the hierarchical role graph and return all of the parents (direct ascendants) of a given role.
+     *
+     * @param roleName maps to logical {@link org.apache.directory.fortress.core.rbac.Role#name} on 'ftRls' object class.
+     * @param contextId maps to sub-tree in DIT, for example ou=contextId, dc=jts, dc = com.
+     * @return Set of Role names that are parents of given child.
+     */
+    static Set<String> getParents( String roleName, String contextId )
+    {
+        return HierUtil.getParents( roleName.toUpperCase(), getGraph( contextId ) );
+    }
+
+
+    /**
+     * Determine the number of children (direct descendants) a given parent role has.
+     *
+     * @param roleName maps to logical {@link org.apache.directory.fortress.core.rbac.Role#name} on 'ftRls' object class.
+     * @param contextId maps to sub-tree in DIT, for example ou=contextId, dc=jts, dc = com.
+     * @return int value contains the number of children of a given parent nRole.
+     */
+    static int numChildren( String roleName, String contextId )
+    {
+        return HierUtil.numChildren( roleName.toUpperCase(), getGraph( contextId ) );
+    }
+
+
+    /**
+     * Return Set of RBAC {@link org.apache.directory.fortress.core.rbac.Role#name}s ascendants.  Used by {@link org.apache.directory.fortress.core.rbac.dao.PermDAO#checkPermission}
+     * for computing authorized {@link UserRole#name}s.
+     *
+     * @param uRoles contains list of Roles activated within a {@link org.apache.directory.fortress.core.rbac.User}'s {@link org.apache.directory.fortress.core.rbac.Session}.
+     * @param contextId maps to sub-tree in DIT, for example ou=contextId, dc=jts, dc = com.
+     * @return contains Set of all authorized RBAC Roles for a given User.
+     */
+    public static Set<String> getInheritedRoles( List<UserRole> uRoles, String contextId )
+    {
+        // create Set with case insensitive comparator:
+        Set<String> iRoles = new TreeSet<>( String.CASE_INSENSITIVE_ORDER );
+        if ( VUtil.isNotNullOrEmpty( uRoles ) )
+        {
+            for ( UserRole uRole : uRoles )
+            {
+                String rleName = uRole.getName();
+                iRoles.add( rleName );
+                Set<String> parents = HierUtil.getAscendants( rleName, getGraph( contextId ) );
+                if ( VUtil.isNotNullOrEmpty( parents ) )
+                    iRoles.addAll( parents );
+            }
+        }
+        return iRoles;
+    }
+
+
+    /**
+     *
+     * @param roles
+     * @param contextId maps to sub-tree in DIT, for example ou=contextId, dc=jts, dc = com.
+     * @return
+     */
+    static Set<String> getAscendantRoles( List<String> roles, String contextId )
+    {
+        // create Set with case insensitive comparator:
+        Set<String> iRoles = new TreeSet<>( String.CASE_INSENSITIVE_ORDER );
+        if ( VUtil.isNotNullOrEmpty( roles ) )
+        {
+            for ( String role : roles )
+            {
+                iRoles.add( role );
+                Set<String> parents = HierUtil.getAscendants( role, getGraph( contextId ) );
+                if ( VUtil.isNotNullOrEmpty( parents ) )
+                    iRoles.addAll( parents );
+            }
+        }
+        return iRoles;
+    }
+
+
+    /**
+     *
+     * @param roles
+     * @param contextId maps to sub-tree in DIT, for example ou=contextId, dc=jts, dc = com.
+     * @return
+     */
+    static Set<String> getDescendantRoles( Set<String> roles, String contextId )
+    {
+        // create Set with case insensitive comparator:
+        Set<String> iRoles = new TreeSet<>( String.CASE_INSENSITIVE_ORDER );
+        if ( VUtil.isNotNullOrEmpty( roles ) )
+        {
+            for ( String role : roles )
+            {
+                iRoles.add( role );
+                Set<String> children = HierUtil.getDescendants( role, getGraph( contextId ) );
+                if ( VUtil.isNotNullOrEmpty( children ) )
+                    iRoles.addAll( children );
+            }
+        }
+        return iRoles;
+    }
+
+
+    /**
+     * Recursively traverse the hierarchical graph and return all of the ascendants of a given child node.
+     *
+     * @param childName   maps to vertex to determine parentage.
+     * @param parentName  points to top most ascendant where traversal must stop.
+     * @param isInclusive if set to true will include the parentName in the result set.  False will not return specified parentName.
+     * @param contextId maps to sub-tree in DIT, for example ou=contextId, dc=jts, dc = com.
+     * @return Set of names that are parents of given child.
+     */
+    static Set<String> getAscendants( String childName, String parentName, boolean isInclusive, String contextId )
+    {
+        return HierUtil.getAscendants( childName, parentName, isInclusive, getGraph( contextId ) );
+    }
+
+
+    /**
+     * This api is used by {@link AdminMgrImpl} to determine parentage for Hierarchical RBAC processing.
+     * It calls {@link HierUtil#validateRelationship(org.jgrapht.graph.SimpleDirectedGraph, String, String, boolean)} to evaluate three adminRole relationship expressions:
+     * <ol>
+     * <li>If child equals parent</li>
+     * <li>If mustExist true and parent-child relationship exists</li>
+     * <li>If mustExist false and parent-child relationship does not exist</li>
+     * </ol>
+     * Method will throw {@link org.apache.directory.fortress.core.ValidationException} if rule check fails meaning caller failed validation
+     * attempt to add/remove hierarchical relationship failed.
+     *
+     * @param childRole  contains {@link org.apache.directory.fortress.core.rbac.Role#name} of child.
+     * @param parentRole contains {@link org.apache.directory.fortress.core.rbac.Role#name} of parent.
+     * @param mustExist  boolean is used to specify if relationship must be true.
+     * @throws org.apache.directory.fortress.core.ValidationException
+     *          in the event it fails one of the 3 checks.
+     */
+    static void validateRelationship( Role childRole, Role parentRole, boolean mustExist )
+        throws ValidationException
+    {
+        HierUtil.validateRelationship( getGraph( childRole.getContextId() ), childRole.getName(), parentRole.getName(),
+            mustExist );
+    }
+
+
+    /**
+     * This api allows synchronized access to allow updates to hierarchical relationships.
+     * Method will update the hierarchical data set and reload the JGraphT simple digraph with latest.
+     *
+     * @param contextId maps to sub-tree in DIT, for example ou=contextId, dc=jts, dc = com.
+     * @param relationship contains parent-child relationship targeted for addition.
+     * @param op   used to pass the ldap op {@link org.apache.directory.fortress.core.rbac.Hier.Op#ADD}, {@link org.apache.directory.fortress.core.rbac.Hier.Op#MOD}, {@link org.apache.directory.fortress.core.rbac.Hier.Op#REM}
+     * @throws org.apache.directory.fortress.core.SecurityException in the event of a system error.
+     */
+    static void updateHier( String contextId, Relationship relationship, Hier.Op op ) throws SecurityException
+    {
+        HierUtil.updateHier( getGraph( contextId ), relationship, op );
+    }
+
+
+    /**
+     * Read this ldap record,{@code cn=Hierarchies, ou=OS-P} into this entity, {@link Hier}, before loading into this collection class,{@code org.jgrapht.graph.SimpleDirectedGraph}
+     * using 3rd party lib, <a href="http://www.jgrapht.org/">JGraphT</a>.
+     *
+     * @param contextId maps to sub-tree in DIT, for example ou=contextId, dc=jts, dc = com.
+     * @return
+     */
+    private static SimpleDirectedGraph<String, Relationship> loadGraph( String contextId )
+    {
+        Hier inHier = new Hier( Hier.Type.ROLE );
+        inHier.setContextId( contextId );
+        LOG.info( "loadGraph initializing ROLE context [" + inHier.getContextId() + "]" );
+        List<Graphable> descendants = null;
+        try
+        {
+            descendants = roleP.getAllDescendants( inHier.getContextId() );
+        }
+        catch ( SecurityException se )
+        {
+            LOG.info( "loadGraph caught SecurityException=" + se );
+        }
+        Hier hier = HierUtil.loadHier( contextId, descendants );
+        SimpleDirectedGraph<String, Relationship> graph;
+        synchronized ( HierUtil.getLock( contextId, HierUtil.Type.ROLE ) )
+        {
+            graph = HierUtil.buildGraph( hier );
+        }
+        roleCache.put( getKey( contextId ), graph );
+        return graph;
+    }
+
+
+    /**
+     *
+     * @param contextId maps to sub-tree in DIT, for example ou=contextId, dc=jts, dc = com.
+     * @return
+     */
+    private static String getKey( String contextId )
+    {
+        String key = HierUtil.Type.ROLE.toString();
+        if ( VUtil.isNotNullOrEmpty( contextId ) && !contextId.equalsIgnoreCase( GlobalIds.NULL ) )
+        {
+            key += ":" + contextId;
+        }
+        return key;
+    }
+
+
+    /**
+     *
+     * @param contextId maps to sub-tree in DIT, for example ou=contextId, dc=jts, dc = com.
+     * @return
+     */
+    private static SimpleDirectedGraph<String, Relationship> getGraph( String contextId )
+    {
+        SimpleDirectedGraph<String, Relationship> graph = ( SimpleDirectedGraph<String, Relationship> ) roleCache
+            .get( getKey( contextId ) );
+        if ( graph == null )
+        {
+            graph = loadGraph( contextId );
+        }
+        return graph;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/687ee1ad/src/main/java/org/apache/directory/fortress/core/rbac/SDSet.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/rbac/SDSet.java b/src/main/java/org/apache/directory/fortress/core/rbac/SDSet.java
new file mode 100755
index 0000000..81889d3
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/rbac/SDSet.java
@@ -0,0 +1,413 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.fortress.core.rbac;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlEnum;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.UUID;
+
+/**
+ * <h4>Static Separation of Duties Schema</h4>
+ * The Fortress SDSet entity is a composite of the following other Fortress structural and aux object classes:
+ * <p/>
+ * 1. organizationalRole Structural Object Class is used to store basic attributes like cn and description.
+ * <pre>
+ * ------------------------------------------
+ * objectclass ( 2.5.6.8 NAME 'organizationalRole'
+ *  DESC 'RFC2256: an organizational role'
+ *  SUP top STRUCTURAL
+ *  MUST cn
+ *  MAY (
+ *      x121Address $ registeredAddress $ destinationIndicator $
+ *      preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
+ *      telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $
+ *      seeAlso $ roleOccupant $ preferredDeliveryMethod $ street $
+ *      postOfficeBox $ postalCode $ postalAddress $
+ *      physicalDeliveryOfficeName $ ou $ st $ l $ description
+ *  )
+ * )
+ * ------------------------------------------
+ * </pre>
+ * <p/>
+ * 2. The RBAC Separation of14:14 Duties includes:
+ * <p/> Static Separation of Duties
+ * <img src="../doc-files/RbacSSD.png">
+ * <pre>
+ * ------------------------------------------
+ * Fortress Dynamic Separation of Duties Structural Object Class
+ *  objectclass	( 1.3.6.1.4.1.38088.2.5
+ *  NAME 'ftDSDSet'
+ *  DESC 'Fortress Role Dynamic Separation of Duty Set Structural Object Class'
+ *  SUP organizationalrole
+ *  STRUCTURAL
+ *  MUST (
+ *      ftId $
+ *      ftSetName $
+ *      ftSetCardinality
+ *  )
+ *  MAY (
+ *      ftRoles $
+ *      description
+ *  )
+ * )
+ * ------------------------------------------
+ * </pre>
+ * <p/>
+ * OR
+ * <p/> Dynamic Separation of Duties
+ * <img src="../doc-files/RbacDSD.png">
+ * <pre>
+ * ------------------------------------------
+ * Fortress Static Separation of Duties Structural Object Class
+ *  objectclass	( 1.3.6.1.4.1.38088.2.4
+ *  NAME 'ftSSDSet'
+ *  DESC 'Fortress Role Static Separation of Duty Set Structural Object Class'
+ *  SUP organizationalrole
+ *  STRUCTURAL
+ *  MUST (
+ *      ftId $
+ *      ftSetName $
+ *      ftSetCardinality
+ *  )
+ *  MAY (
+ *      ftRoles $
+ *      description
+ *  )
+ *)
+ * ------------------------------------------
+ * </pre>
+ * <p/>
+ * 3. ftMods AUXILIARY Object Class is used to store Fortress audit variables on target entity.
+ * <pre>
+ * ------------------------------------------
+ * Fortress Audit Modification Auxiliary Object Class
+ * objectclass ( 1.3.6.1.4.1.38088.3.4
+ *  NAME 'ftMods'
+ *  DESC 'Fortress Modifiers AUX Object Class'
+ *  AUXILIARY
+ *  MAY (
+ *      ftModifier $
+ *      ftModCode $
+ *      ftModId
+ *  )
+ * )
+ * ------------------------------------------
+ * </pre>
+ * <p/>
+ *
+ * @author Shawn McKinney
+ */
+@XmlRootElement(name = "fortSet")
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "sdset", propOrder = {
+    "name",
+    "id",
+    "description",
+    "cardinality",
+    "members",
+    "type"
+})
+public class SDSet extends FortEntity
+    implements java.io.Serializable, Comparable
+{
+    private String id;
+    private String name;
+    private String description;
+    private Integer cardinality;
+    @XmlElement(nillable = true)
+    private Set<String> members;
+    private SDType type;
+
+
+    /**
+     * enum for SSD or DSD data sets.  Both nodes will be stored in the same LDAP container but use different
+     * object classes.
+     * SDType determines if 'ftSSDSet' or 'ftDSDSet' object class is used.
+     */
+    @XmlType(name = "sdtype")
+    @XmlEnum
+    public enum SDType
+    {
+        /**
+         * Static Separation of Duty data set.
+         */
+        STATIC,
+
+        /**
+         * Dynamic Separation of Duty data set.
+         */
+        DYNAMIC
+    }
+
+    /**
+     * Get the required type of SD Set - 'STATIC' Or 'DYNAMIC'.
+     *
+     * @return type that maps to either 'ftSSDSet' or 'ftDSDSet' object class is used.
+     */
+    public SDType getType()
+    {
+        return type;
+    }
+
+    /**
+     * Set the required type of SD Set - 'STATIC' Or 'DYNAMIC'.
+     *
+     * @param type maps to either 'ftSSDSet' or 'ftDSDSet' object class is used.
+     */
+    public void setType(SDType type)
+    {
+        this.type = type;
+    }
+
+    /**
+     * Create a new, empty map that is used to load Role members.  This method is called by any class
+     * that needs to create an SDSet set.
+     *
+     * @return Set that sorts members by alphabetical order.
+     */
+    private static Set<String> createMembers()
+    {
+        return new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
+    }
+
+
+    /**
+     * Return the name of SDSet entity.  This field is required.
+     *
+     * @return attribute maps to 'cn' attribute on the 'organizationalRole' object class.
+     */
+    public String getName()
+    {
+        return this.name;
+    }
+
+
+    /**
+     * Set the name of SDSet entity.  This field is required.
+     *
+     * @param name maps to 'cn' attribute on the 'organizationalRole' object class.
+     */
+    public void setName(String name)
+    {
+        this.name = name;
+    }
+
+
+    /**
+     * Returns optional description that is associated with SDSet.  This attribute is validated but not constrained by Fortress.
+     *
+     * @return value that is mapped to 'description' in 'organizationalrole' object class.
+     */
+    public String getDescription()
+    {
+        return this.description;
+    }
+
+
+    /**
+     * Sets the optional description that is associated with SDSet.  This attribute is validated but not constrained by Fortress.
+     *
+     * @param description that is mapped to same name in 'organizationalrole' object class.
+     */
+    public void setDescription(String description)
+    {
+        this.description = description;
+    }
+
+
+    /**
+     * Return the internal id that is associated with SDSet.  This attribute is generated automatically
+     * by Fortress when new SDSet is added to directory and is not known or changeable by external client.
+     *
+     * @return attribute maps to 'ftId' in either 'ftSSDSet' or 'ftDSDSet' object class.
+     */
+    public String getId()
+    {
+        return id;
+    }
+
+
+    /**
+     * Generate an internal Id that is associated with SDSet.  This method is used by DAO class and
+     * is not available to outside classes.   The generated attribute maps to 'ftId' in either 'ftSSDSet' or 'ftDSDSet' object class.
+     */
+    public void setId()
+    {
+        // generate a unique id that will be used as the rDn for this entry:
+        UUID uuid = UUID.randomUUID();
+        this.id = uuid.toString();
+    }
+
+
+    /**
+     * Set the internal Id that is associated with Role.  This method is used by DAO class and
+     * is generated automatically by Fortress.  Attribute stored in LDAP cannot be changed by external caller.
+     * This method can be used by client for search purposes only.
+     *
+     * @param id maps to 'ftId' in either 'ftSSDSet' or 'ftDSDSet' object class.
+     */
+    public void setId(String id)
+    {
+        this.id = id;
+    }
+
+
+    /**
+     * Return the numeric value that reflects the membership cardinality for SDSet.  A value of '2' indicates
+     * the Role membership is mutually exclusive amongst members.  A value of '3' indicates no more than two Roles
+     * in set can be assigned to a single User (SSD) or activated within a single Session (DSD).  A value of '4' indicates
+     * no more than three Roles may be used at a time, etc...
+     *
+     * @return attribute maps to 'ftSetCardinality' attribute in either 'ftSSDSet' or 'ftDSDSet' object class.
+     */
+    public Integer getCardinality()
+    {
+        return cardinality;
+    }
+
+    /**
+     * Set the numeric value that reflects the membership cardinality for SDSet.  A value of '2' indicates
+     * the Role membership is mutually exclusive amongst members.  A value of '3' indicates no more than two Roles
+     * in set can be assigned to a single User (SSD) or activated within a single Session (DSD).  A value of '4' indicates
+     * no more than three Roles may be used at a time, etc...
+     *
+     */
+    public void setCardinality(Integer cardinality)
+    {
+        this.cardinality = cardinality;
+    }
+
+    /**
+     * Return the alphabetically sorted Set containing Role membership to SDSet.
+     *
+     * @return attribute maps to 'ftRoles' attribute in either 'ftSSDSet' or 'ftDSDSet' object class.
+     */
+    //@XmlJavaTypeAdapter(SetAdapter.class)
+    public Set<String> getMembers()
+    {
+        return members;
+    }
+
+    /**
+     * Set an alphabetically sorted Set containing Role membership to SDSet.
+     *
+     * @param members attribute maps to 'ftRoles' attribute in either 'ftSSDSet' or 'ftDSDSet' object class.
+     */
+    public void setMembers(Set<String> members)
+    {
+        this.members = members;
+    }
+
+
+    /**
+     * Add a member to the set.
+     *
+     * @param member role name.
+     */
+    public void setMember(String member)
+    {
+        if(this.members == null)
+        {
+            this.members = new HashSet<>();
+        }
+        this.members.add(member);
+    }
+
+
+    /**
+     * Add a member to an alphabetically sorted Set containing Role membership to SDSet.
+     *
+     * @param role attribute maps to 'ftRoles' attribute in either 'ftSSDSet' or 'ftDSDSet' object class.
+     */
+    public void addMember(String role)
+    {
+        if (this.members == null)
+        {
+            this.members = createMembers();
+        }
+        this.members.add(role);
+    }
+
+    /**
+     * Remove a member from the alphabetically sorted Set containing Role membership to SDSet.
+     *
+     * @param role attribute maps to 'ftRoles' attribute in either 'ftSSDSet' or 'ftDSDSet' object class.
+     */
+    public void delMember(String role)
+    {
+        if (this.members == null)
+        {
+            return;
+        }
+        this.members.remove(role);
+    }
+
+    public int compareTo(Object o)
+    {
+        SDSet k1 = this;
+        SDSet k2 = (SDSet) o;
+        String s1 = k1.getName();
+        String s2 = k2.getName();
+        return s1.compareToIgnoreCase(s2);
+    }
+
+    /**
+     * Matches the name from two SDSet entities.
+     *
+     * @param thatObj contains an SDSet entity.
+     * @return boolean indicating both objects contain matching SDSet names.
+     */
+    public boolean equals(Object thatObj)
+    {
+        if (this == thatObj)
+        {
+            return true;
+        }
+        if (this.getName() == null)
+        {
+            return false;
+        }
+        if (!(thatObj instanceof Role ))
+        {
+            return false;
+        }
+        SDSet thatSet = (SDSet) thatObj;
+        if (thatSet.getName() == null)
+        {
+            return false;
+        }
+        return thatSet.getName().equalsIgnoreCase(this.getName());
+    }
+
+    @Override
+    public String toString()
+    {
+        return "SDSet{" +
+            "name='" + name + '\'' +
+            '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/687ee1ad/src/main/java/org/apache/directory/fortress/core/rbac/SDUtil.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/rbac/SDUtil.java b/src/main/java/org/apache/directory/fortress/core/rbac/SDUtil.java
new file mode 100755
index 0000000..0eb4c88
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/rbac/SDUtil.java
@@ -0,0 +1,533 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.fortress.core.rbac;
+
+import org.apache.directory.fortress.core.GlobalErrIds;
+import org.apache.directory.fortress.core.GlobalIds;
+import org.apache.directory.fortress.core.ReviewMgrFactory;
+import org.apache.directory.fortress.core.SecurityException;
+import org.apache.directory.fortress.core.ReviewMgr;
+import org.apache.directory.fortress.core.cfg.Config;
+import org.apache.directory.fortress.core.util.attr.VUtil;
+import org.apache.directory.fortress.core.util.cache.Cache;
+import org.apache.directory.fortress.core.util.cache.CacheMgr;
+import org.apache.directory.fortress.core.util.cache.DsdCacheEntry;
+import org.apache.directory.fortress.core.util.time.Constraint;
+import net.sf.ehcache.search.Attribute;
+import net.sf.ehcache.search.Query;
+import net.sf.ehcache.search.Result;
+import net.sf.ehcache.search.Results;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * This utilty provides functionality necessary for SSD and DSD processing and cannot be called by components outside fortress.
+ * This class also contains utility functions for maintaining the SSD and DSD cache.
+ * <p/>
+ * This class is thread safe.
+ *
+ * @author Shawn McKinney
+ * @created September 3, 2010
+ */
+final class SDUtil
+{
+    private static final Cache m_dsdCache;
+    private static final String FORTRESS_DSDS = "fortress.dsd";
+    private static final Cache m_ssdCache;
+    private static final String FORTRESS_SSDS = "fortress.ssd";
+    private static final SdP sp = new SdP();
+    private static final String IS_DSD_CACHE_DISABLED_PARM = "enable.dsd.cache";
+    private static final String MEMBER = "member";
+    private static final String DSD_NAME = "name";
+    private static final String EMPTY_ELEMENT = "empty";
+    private static final String CONTEXT_ID = "contextId";
+
+    static
+    {
+        // Get a reference to the CacheManager Singleton object:
+        CacheMgr cacheMgr = CacheMgr.getInstance();
+        // This cache contains a wrapper entry for DSD and is searchable by both DSD and Role name:
+        m_dsdCache = cacheMgr.getCache(FORTRESS_DSDS);
+        // This cache is not searchable and contains Lists of SSD objects by Role:
+        m_ssdCache = cacheMgr.getCache(FORTRESS_SSDS);
+    }
+
+    /**
+     * This method is called by AdminMgr.assignUser and is used to validate Static Separation of Duty
+     * constraints when assigning a role to user.
+     *
+     * @param uRole
+     * @throws org.apache.directory.fortress.core.SecurityException
+     *
+     */
+    static void validateSSD(UserRole uRole)
+        throws SecurityException
+    {
+        validateSSD(new User(uRole.getUserId()), new Role(uRole.getName()));
+    }
+
+    /**
+     * This method is called by AdminMgr.assignUser and is used to validate Static Separation of Duty
+     * constraints when assigning a role to user.
+     *
+     * @param user
+     * @param role
+     * @throws org.apache.directory.fortress.core.SecurityException
+     *
+     */
+    static void validateSSD(User user, Role role)
+        throws SecurityException
+    {
+        int matchCount;
+        // get all authorized roles for user
+        ReviewMgr rMgr = ReviewMgrFactory.createInstance(user.getContextId());
+        Set<String> rls = rMgr.authorizedRoles(user);
+        // Need to proceed?
+        if (!VUtil.isNotNullOrEmpty(rls))
+        {
+            return;
+        }
+
+        // get all SSD sets that contain the new role
+        List<SDSet> ssdSets = getSsdCache(role.getName(), user.getContextId());
+        for (SDSet ssd : ssdSets)
+        {
+            matchCount = 0;
+            Set<String> map = ssd.getMembers();
+            // iterate over every authorized role for user:
+            for (String authRole : rls)
+            {
+                // is there a match found between authorized role and SSD set's members?
+                if (map.contains(authRole))
+                {
+                    matchCount++;
+                    // does the match count exceed the cardinality allowed for this particular SSD set?
+                    if (matchCount >= ssd.getCardinality() - 1)
+                    {
+                        String error = "validateSSD new role [" + role.getName() + "] validates SSD Set Name:" + ssd.getName() + " Cardinality:" + ssd.getCardinality();
+                        throw new SecurityException(GlobalErrIds.SSD_VALIDATION_FAILED, error);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * This method is called by AccessMgr.addActiveRole and is used to validate Dynamic Separation of Duty
+     * constraints when activating a role one at a time.  For activation of multiple roles simultaneously use
+     * the DSD.validate API which is used during createSession sequence.
+     *
+     * @param session
+     * @param role
+     * @throws org.apache.directory.fortress.core.SecurityException
+     *
+     */
+    static void validateDSD(Session session, Constraint role)
+        throws SecurityException
+    {
+        // get all activated roles from user's session:
+        List<UserRole> rls = session.getRoles();
+        if (!VUtil.isNotNullOrEmpty(rls))
+        {
+            // An empty list of roles was passed in the session variable.
+            // No need to continue.
+            return;
+        }
+
+        // get all DSD sets that contain the target role
+        Set<SDSet> dsdSets = getDsdCache(role.getName(), session.getContextId());
+        for (SDSet dsd : dsdSets)
+        {
+            // Keeps the number of matched roles to a particular DSD set.
+            int matchCount = 0;
+
+            // Contains the list of roles assigned to a particular DSD set.
+            Set<String> map = dsd.getMembers();
+
+            // iterate over every role active in session for match wth DSD members:
+            for (UserRole actRole : rls)
+            {
+                // is there a match found between active role in session and DSD set members?
+                if (map.contains(actRole.getName()))
+                {
+                    // Yes, we found a match, increment the count.
+                    matchCount++;
+
+                    // Does the match count exceed the cardinality allowed for this particular DSD set?
+                    if (matchCount >= dsd.getCardinality() - 1)
+                    {
+                        // Yes, the target role violates DSD cardinality rule.
+                        String error = "validateDSD failed for role [" + role.getName() + "] DSD Set Name:" + dsd.getName() + " Cardinality:" + dsd.getCardinality();
+                        throw new SecurityException(GlobalErrIds.DSD_VALIDATION_FAILED, error);
+                    }
+                }
+                else // Check the parents of activated role for DSD match:
+                {
+                    // Now pull the activated role's list of parents.
+                    Set<String> parentSet = RoleUtil.getAscendants(actRole.getName(), session.getContextId());
+
+                    // Iterate over the list of parent roles:
+                    for (String parentRole : parentSet)
+                    {
+                        if (map.contains(parentRole)) // is there match between parent and DSD member?
+                        {
+                            matchCount++;
+                            if (matchCount >= dsd.getCardinality() - 1) // Does the counter exceed max per cardinality on this DSD set?
+                            {
+                                String error = "validateDSD failed for role [" + role.getName() + "] parent role [" + parentRole + "] DSD Set Name:" + dsd.getName() + " Cardinality:" + dsd.getCardinality();
+                                throw new SecurityException(GlobalErrIds.DSD_VALIDATION_FAILED, error);
+                            }
+                            // Breaking out of the loop here means the DSD algorithm will only match one
+                            // role per parent of active role candidate.
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Given DSD entry name, clear its corresponding object values from the cache.
+     *
+     * @param name contains the name of object to be cleared.
+     * @param contextId maps to sub-tree in DIT, for example ou=contextId, dc=jts, dc = com.     *
+     * @throws SecurityException in the event of system or rule violation.
+     */
+    static void clearDsdCacheEntry(String name, String contextId)
+    {
+        Attribute<String> context = m_dsdCache.getSearchAttribute(CONTEXT_ID);
+        Attribute<String> dsdName = m_dsdCache.getSearchAttribute(DSD_NAME);
+        Query query = m_dsdCache.createQuery();
+        query.includeKeys();
+        query.includeValues();
+        query.addCriteria(dsdName.eq(name).and(context.eq(contextId)));
+        Results results = query.execute();
+        for (Result result : results.all())
+        {
+            m_dsdCache.clear(result.getKey());
+        }
+    }
+
+    /**
+     * Given a role name, return the set of DSD's that have a matching member.
+     *
+     * @param name contains name of authorized Role used to search the cache.
+     * @param contextId maps to sub-tree in DIT, for example ou=contextId, dc=jts, dc = com.
+     * @return un-ordered set of matching DSD's.
+     * @throws SecurityException in the event of system or rule violation.
+     */
+    private static Set<SDSet> getDsdCache(String name, String contextId)
+        throws SecurityException
+    {
+        contextId = getContextId(contextId);
+        Set<SDSet> finalSet = new HashSet<>();
+        Attribute<String> context = m_dsdCache.getSearchAttribute(CONTEXT_ID);
+        Attribute<String> member = m_dsdCache.getSearchAttribute(MEMBER);
+        Query query = m_dsdCache.createQuery();
+        query.includeKeys();
+        query.includeValues();
+        query.addCriteria(member.eq(name).and(context.eq(contextId)));
+        Results results = query.execute();
+        boolean empty = false;
+        for (Result result : results.all())
+        {
+            DsdCacheEntry entry = (DsdCacheEntry) result.getValue();
+            if (!entry.isEmpty())
+            {
+                finalSet.add(entry.getSdSet());
+                finalSet = putDsdCache(name, contextId);
+            }
+            else
+            {
+                empty = true;
+            }
+            finalSet.add(entry.getSdSet());
+        }
+        // If nothing was found in the cache, determine if it needs to be seeded:
+        if (finalSet.size() == 0 && !empty)
+        {
+            finalSet = putDsdCache(name, contextId);
+        }
+        return finalSet;
+    }
+
+    /**
+     * Given a Set of authorized Roles, return the set of DSD's that have matching members.
+     *
+     * @param authorizedRoleSet contains an un-order Set of authorized Roles.
+     * @param contextId maps to sub-tree in DIT, for example ou=contextId, dc=jts, dc = com.
+     * @return un-ordered set of matching DSD's.
+     * @throws SecurityException in the event of system or rule violation.
+     */
+    static Set<SDSet> getDsdCache(Set<String> authorizedRoleSet, String contextId)
+        throws SecurityException
+    {
+        contextId = getContextId(contextId);
+        Set<SDSet> dsdRetSets = new HashSet<>();
+        // Need to proceed?
+        if (!VUtil.isNotNullOrEmpty(authorizedRoleSet))
+        {
+            return dsdRetSets;
+        }
+        // Was the DSD Cache switched off?
+        boolean isCacheDisabled = Config.getBoolean(IS_DSD_CACHE_DISABLED_PARM, false);
+        // If so, get DSD's from LDAP:
+        if (isCacheDisabled)
+        {
+            SDSet sdSet = new SDSet();
+            sdSet.setType(SDSet.SDType.DYNAMIC);
+            sdSet.setContextId(contextId);
+            dsdRetSets = sp.search(authorizedRoleSet, sdSet);
+        }
+        // Search the DSD cache for matching Role members:
+        else
+        {
+            // Search on roleName attribute which maps to 'member' attr on the cache record:
+            Attribute<String> member = m_dsdCache.getSearchAttribute(MEMBER);
+            Attribute<String> context = m_dsdCache.getSearchAttribute(CONTEXT_ID);
+            Query query = m_dsdCache.createQuery();
+            query.includeKeys();
+            query.includeValues();
+            // Add the passed in authorized Role names to this cache query:
+            Set<String> roles = new HashSet<>(authorizedRoleSet);
+            query.addCriteria(member.in(roles).and(context.eq(contextId)));
+            // Return all DSD cache entries that match roleName to the 'member' attribute in cache entry:
+            Results results = query.execute();
+            for (Result result : results.all())
+            {
+                DsdCacheEntry entry = (DsdCacheEntry) result.getValue();
+                // Do not add dummy DSD sets to the final list:
+                if (!entry.isEmpty())
+                {
+                    dsdRetSets.add(entry.getSdSet());
+                }
+                // Remove role member from authorizedRoleSet to preclude from upcoming DSD search:
+                authorizedRoleSet.remove(entry.getMember());
+            }
+            // Authorized roles remaining in this set correspond to missed cache hits from above:
+            if (authorizedRoleSet.size() > 0)
+            {
+                dsdRetSets = putDsdCache(authorizedRoleSet, contextId);
+            }
+        }
+        return dsdRetSets;
+    }
+
+    /**
+     * Get the matching DSD's from directory and add to the cache (if found).  If matching DSD not found,
+     * add dummy entry to cache to prevent repeated searches.
+     *
+     * @param authorizedRoleSet contains set of Roles used to search directory for matching DSD's.
+     * @param contextId maps to sub-tree in DIT, for example ou=contextId, dc=jts, dc = com.
+     * @return List of DSD's who have matching Role members.
+     * @throws SecurityException in the event of system or rule violation.
+     */
+    private static Set<SDSet> putDsdCache(Set<String> authorizedRoleSet, String contextId)
+        throws SecurityException
+    {
+        contextId = getContextId(contextId);
+        Set<SDSet> dsdSets = new HashSet<>();
+        // Search the DSD's iteratively to seed the DSD cache by Role name:
+        for (String roleName : authorizedRoleSet)
+        {
+            Role role = new Role(roleName);
+            role.setContextId(contextId);
+            List<SDSet> dsdList = sp.search(role, SDSet.SDType.DYNAMIC);
+            if (VUtil.isNotNullOrEmpty(dsdList))
+            {
+                for (SDSet dsd : dsdList)
+                {
+                    dsd.setContextId(contextId);
+                    Set<String> members = dsd.getMembers();
+                    if (members != null)
+                    {
+                        // Seed the cache with DSD objects mapped to role name:
+                        for (String member : members)
+                        {
+                            String key = buildKey(dsd.getName(), member);
+                            DsdCacheEntry entry = new DsdCacheEntry(member, dsd, false);
+                            entry.setName(dsd.getName());
+                            m_dsdCache.put(getKey(key, contextId), entry);
+                        }
+                    }
+                }
+                // Maintain the set of DSD's to be returned to the caller:
+                dsdSets.addAll(dsdList);
+            }
+            else
+            {
+                // Seed the cache with dummy entry for a Role that is not referenced by DSD:
+                String key = buildKey(EMPTY_ELEMENT, roleName);
+                SDSet sdSet = new SDSet();
+                sdSet.setType(SDSet.SDType.DYNAMIC);
+                sdSet.setName(key);
+                sdSet.setMember(roleName);
+                sdSet.setContextId(contextId);
+                DsdCacheEntry entry = new DsdCacheEntry(roleName, sdSet, true);
+                entry.setName(key);
+                m_dsdCache.put(getKey(sdSet.getName(), contextId), entry);
+            }
+        }
+        return dsdSets;
+    }
+
+    /**
+     * Get the matching DSD's from directory and add to the cache (if found).  If matching DSD not found,
+     * add dummy entry to cache to prevent repeated searches.
+     *
+     * @param roleName of Role is used to search directory for matching DSD's.
+     * @param contextId maps to sub-tree in DIT, for example ou=contextId, dc=jts, dc = com.
+     * @return Set of DSD's who have matching Role member.
+     * @throws SecurityException in the event of system or rule violation.
+     */
+    private static Set<SDSet> putDsdCache(String roleName, String contextId)
+        throws SecurityException
+    {
+        contextId = getContextId(contextId);
+        Role role = new Role(roleName);
+        role.setContextId(contextId);
+        List<SDSet> dsdList = sp.search(role, SDSet.SDType.DYNAMIC);
+        Set<SDSet> finalSet = new HashSet<>(dsdList);
+        if (VUtil.isNotNullOrEmpty(dsdList))
+        {
+            for (SDSet dsd : dsdList)
+            {
+                dsd.setContextId(contextId);
+                Set<String> members = dsd.getMembers();
+                if (members != null)
+                {
+                    // Seed the cache with DSD objects mapped to role name:
+                    for (String member : members)
+                    {
+                        String key = buildKey(dsd.getName(), member);
+                        DsdCacheEntry entry = new DsdCacheEntry(member, dsd, false);
+                        entry.setName(dsd.getName());
+                        m_dsdCache.put(getKey(key, contextId), entry);
+                    }
+                }
+            }
+        }
+        else
+        {
+            // Seed the cache with dummy entry for Role that does not have DSD:
+            String key = buildKey(EMPTY_ELEMENT, roleName);
+            SDSet sdSet = new SDSet();
+            sdSet.setType(SDSet.SDType.DYNAMIC);
+            sdSet.setName(key);
+            sdSet.setMember(roleName);
+            sdSet.setContextId(contextId);
+            DsdCacheEntry entry = new DsdCacheEntry(roleName, sdSet, true);
+            entry.setName(key);
+            m_dsdCache.put(getKey(sdSet.getName(), contextId), entry);
+        }
+        return finalSet;
+    }
+
+    /**
+     * Given entry name, clear its corresponding object value from the cache.
+     *
+     * @param name contains the name of object to be cleared.
+     * @param contextId maps to sub-tree in DIT, for example ou=contextId, dc=jts, dc = com.
+     * @throws SecurityException in the event of system or rule violation.
+     */
+    static void clearSsdCacheEntry(String name, String contextId)
+    {
+        contextId = getContextId(contextId);
+        m_ssdCache.clear(getKey(name, contextId));
+    }
+
+    /**
+     * Get the matching SSD's from directory and add to the cache (if found).
+     *
+     * @param name of Role is used to search directory for matching SSD's.
+     * @param contextId maps to sub-tree in DIT, for example ou=contextId, dc=jts, dc = com.
+     * @return List of SSD's who have matching Role member.
+     * @throws SecurityException in the event of system or rule violation.
+     */
+    private static List<SDSet> putSsdCache(String name, String contextId)
+        throws SecurityException
+    {
+        Role role = new Role(name);
+        role.setContextId(contextId);
+        List<SDSet> ssdSets = sp.search(role, SDSet.SDType.STATIC);
+        m_ssdCache.put(getKey(name, contextId), ssdSets);
+        return ssdSets;
+    }
+
+    /**
+     * Look in cache for matching List of SSD's.
+     *
+     * @param name of Role is used to search directory for matching SSD's.
+     * @param contextId maps to sub-tree in DIT, for example ou=contextId, dc=jts, dc = com.
+     * @return List of SSD's who have matching Role member.
+     * @throws SecurityException in the event of system or rule violation.
+     */
+    private static List<SDSet> getSsdCache(String name, String contextId)
+        throws SecurityException
+    {
+        List<SDSet> ssdSets = (List<SDSet>) m_ssdCache.get(getKey(name, contextId));
+        if (ssdSets == null)
+        {
+            ssdSets = putSsdCache(name, contextId);
+        }
+        return ssdSets;
+    }
+
+    /**
+     *
+     * @param parm1
+     * @param parm2
+     * @return
+     */
+    private static String buildKey(String parm1, String parm2)
+    {
+        return parm1 + ":" + parm2;
+    }
+
+    /**
+     *
+     * @param name
+     * @param contextId
+     * @return
+     */
+    private static String getKey(String name, String contextId)
+    {
+        contextId = getContextId(contextId);
+        return name += ":" + contextId;
+    }
+
+    /**
+     *
+     * @param contextId
+     * @return
+     */
+    private static String getContextId(String contextId)
+    {
+        String szContextId = GlobalIds.HOME;
+        if(VUtil.isNotNullOrEmpty(contextId) && !contextId.equals(GlobalIds.NULL))
+        {
+            szContextId = contextId;
+        }
+        return szContextId;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/687ee1ad/src/main/java/org/apache/directory/fortress/core/rbac/SdP.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/rbac/SdP.java b/src/main/java/org/apache/directory/fortress/core/rbac/SdP.java
new file mode 100755
index 0000000..fa06867
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/rbac/SdP.java
@@ -0,0 +1,221 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.fortress.core.rbac;
+
+
+import java.util.List;
+import java.util.Set;
+
+import org.apache.directory.fortress.core.GlobalIds;
+import org.apache.directory.fortress.core.SecurityException;
+import org.apache.directory.fortress.core.rbac.dao.unboundid.SdDAO;
+import org.apache.directory.fortress.core.util.attr.VUtil;
+
+
+/**
+ * Process module for Separation of Duty Relation data sets. The Fortress SD data set can be of two types:
+ * <ol>
+ * <li>Static Separation of Duties (SSD)</li>
+ * <li>Dynamic Separation of Duties (DSD)</li>
+ * </ol>
+ * The SDSet entity itself distinguishes which is being targeted by {@link SDSet.SDType} which is equal to {@link SDSet.SDType#STATIC} or {@link SDSet.SDType#DYNAMIC}.
+ * This class performs data validations and error mapping in addition to calling DAO methods.  It is typically called
+ * by internal Fortress Manager classes ({@link org.apache.directory.fortress.core.AdminMgr}, {@link org.apache.directory.fortress.core.ReviewMgr}) and also by internal SD utils.
+ * This class is not intended to be called externally or outside of Fortress Core itself.  This class will accept {@link SDSet},
+ * validate its contents and forward on to it's corresponding DAO {@link org.apache.directory.fortress.core.rbac.dao.unboundid.SdDAO}.
+ * <p>
+ * Class will throw {@link SecurityException} to caller in the event of security policy, data constraint violation or system
+ * error internal to DAO object. This class will forward DAO exceptions ({@link org.apache.directory.fortress.core.FinderException},
+ * {@link org.apache.directory.fortress.core.CreateException},{@link org.apache.directory.fortress.core.UpdateException},{@link org.apache.directory.fortress.core.RemoveException}),
+ * or {@link org.apache.directory.fortress.core.ValidationException} as {@link SecurityException}s with appropriate
+ * error id from {@link org.apache.directory.fortress.core.GlobalErrIds}.
+ * <p>
+ * This class is thread safe.
+ * <p/>
+
+ *
+ * @author Shawn McKinney
+ * @created September 11, 2010
+ */
+public final class SdP
+{
+    /**
+     * Get the DAO created:
+     */
+    private static final SdDAO sdDao = new SdDAO();
+
+
+    /**
+     * Package private constructor.
+     */
+    SdP()
+    {
+    }
+
+
+    /**
+     * Adds a new SDSet to directory. The OrgUnit SDType enum will determine which data set insertion will
+     * occur - STATIC or DYNAMIC.  The SDSet entity input will be validated to ensure that:
+     * name is present, and reasonability checks on all of the other populated values.
+     *
+     * @param entity SDSet contains data targeted for insertion.
+     * @return SDSet entity copy of input + additional attributes (internalId) that were added by op.
+     * @throws SecurityException in the event of data validation or DAO system error.
+     */
+    final SDSet add( SDSet entity ) throws SecurityException
+    {
+        validate( entity );
+        return sdDao.create( entity );
+    }
+
+
+    /**
+     * Updates existing SDSet in directory. The SDSet type enum will determine which data set insertion will
+     * occur - STATIC or DYNAMIC.  The SDSet entity input will be validated to ensure that:
+     * name is present, and reasonability checks on all of the other populated values.
+     * Null or empty attributes are ignored.
+     *
+     * @param entity SDSet contains data targeted for updating.  Null attributes ignored.
+     * @return SDSet entity copy of input + additional attributes (internalId) that were updated by op.
+     * @throws SecurityException in the event of data validation or DAO system error.
+     */
+    final SDSet update( SDSet entity ) throws SecurityException
+    {
+        validate( entity );
+        return sdDao.update( entity );
+    }
+
+
+    /**
+     * This method performs a "hard" delete.  It completely the SDSet node from the ldap directory.
+     * The SDSet type enum will determine where deletion will occur - STATIC or DYNAMIC data sets.
+     * SDSet entity must exist in directory prior to making this call else exception will be thrown.
+     *
+     * @param entity Contains the name of the SDSet node targeted for deletion.
+     * @return SDSet is a copy of entity.
+     * @throws SecurityException in the event of data validation or DAO system error.
+     */
+    final SDSet delete( SDSet entity ) throws SecurityException
+    {
+        return sdDao.remove( entity );
+    }
+
+
+    /**
+     * Return a fully populated SDSet entity for a given STATIC or DYNAMIC SDSet name.  If matching record not found a
+     * SecurityException will be thrown.
+     *
+     * @param entity contains full SDSet name used for STATIC or DYNAMIC data sets in directory.
+     * @return SDSet entity containing all attributes associated with ou in directory.
+     * @throws SecurityException in the event SDSet not found or DAO search error.
+     */
+    final SDSet read( SDSet entity ) throws SecurityException
+    {
+        SDSet sde;
+        // The assumption is this method is called from ReviewMgr.ssdRoleSetRoles or ReviewMgr.dsdRoleSetRoles.
+        // If called from ReviewMgr, the object class type will be passed in:
+        SDSet.SDType type = entity.getType();
+        sde = sdDao.getSD( entity );
+        // Load the previously saved type onto the return entity:
+        sde.setType( type );
+        return sde;
+    }
+
+
+    /**
+     * Will search using a single RBAC Role name either STATIC or DYNAMIC SDSet depending on which type is passed.
+     * The role entity contains full RBAC Role name associated with SDSet node in directory.
+     *
+     * @param sdSet contains sdset name or partial name along with sdset type of STATIC or DYNAMIC.
+     * @return List of SDSet entities found.
+     * @throws SecurityException in the event of DAO search error.
+     */
+    final List<SDSet> search( SDSet sdSet ) throws SecurityException
+    {
+        return sdDao.search( sdSet );
+    }
+
+
+    /**
+     * Will search using a single RBAC Role name either STATIC or DYNAMIC SDSet depending on which type is passed.
+     * The role entity contains full RBAC Role name associated with SDSet node in directory.
+     *
+     * @param role contains full role name associated with SDSet.
+     * @param type either STATIC or DYNAMIC depending on target search data set.
+     * @return List of SDSet entities found.
+     * @throws SecurityException in the event of DAO search error.
+     */
+    final List<SDSet> search( Role role, SDSet.SDType type ) throws SecurityException
+    {
+        return sdDao.search( role, type );
+    }
+
+
+    /**
+     * Will search using list of input RBAC role names either STATIC or DYNAMIC SDSet depending on which type is passed.
+     * The role entity contains full RBAC Role name associated with SDSet node in directory.
+     *
+     * @param rls  contains set of type String containing full role names associated with SDSet.
+     * @param sdSet contains type either STATIC or DYNAMIC depending on target search data set.
+     * @return List of SDSet entities found.
+     * @throws SecurityException in the event of DAO search error.
+     */
+    final Set<SDSet> search( Set<String> rls, SDSet sdSet ) throws SecurityException
+    {
+        return sdDao.search( rls, sdSet );
+    }
+
+
+    /**
+     * Method will perform simple validations to ensure the integrity of the SDSet entity targeted for insertion
+     * or updating in directory.  This method will ensure the name and type enum are specified.  Method will
+     * also ensure every Role name set is valid RBAC role entity in directory.  It will also perform
+     * reasonability check on description if set.
+     *
+     * @param entity contains the enum type to validate
+     * @throws SecurityException thrown in the event the attribute is null.
+     */
+    private void validate( SDSet entity )
+        throws SecurityException
+    {
+        // TODO: Add more validations here:
+        VUtil.safeText( entity.getName(), GlobalIds.OU_LEN );
+        if ( VUtil.isNotNullOrEmpty( entity.getDescription() ) )
+        {
+            VUtil.description( entity.getDescription() );
+        }
+        Set<String> roles = entity.getMembers();
+        if ( roles != null )
+        {
+            RoleP rp = new RoleP();
+            for ( String key : roles )
+            {
+                // when removing last role member a placeholder must be left in data set:
+                if ( !key.equalsIgnoreCase( GlobalIds.NONE ) )
+                {
+                    // Ensure the name exists:
+                    Role role = new Role( key );
+                    role.setContextId( entity.getContextId() );
+                    rp.read( role );
+                }
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/687ee1ad/src/main/java/org/apache/directory/fortress/core/rbac/Session.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/rbac/Session.java b/src/main/java/org/apache/directory/fortress/core/rbac/Session.java
new file mode 100755
index 0000000..3e95094
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/rbac/Session.java
@@ -0,0 +1,688 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.fortress.core.rbac;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * This contains attributes related to a user's RBAC session.
+ * The following example shows the mapping to Session attributes on this entity:
+ * <p/>
+ * <ul> <li><code>Session</code>
+ * <li> <code>session.getUserId() => demoUser4</code>
+ * <li> <code>session.getInternalUserId() => be2dd2e:12a82ba707e:-7fee</code>
+ * <li> <code>session.getMessage() => Fortress checkPwPolicies userId <demouser4> VALIDATION GOOD</code>
+ * <li> <code>session.getErrorId() => 0</code>
+ * <li> <code>session.getWarningId() => 11</code>
+ * <li> <code>session.getExpirationSeconds() => 469831</code>
+ * <li> <code>session.getGraceLogins() => 0</code>
+ * <li> <code>session.getIsAuthenticated() => true</code>
+ * <li> <code>session.getLastAccess() => 1283623680440</code>
+ * <li> <code>session.getSessionId() => -7410986f:12addeea576:-7fff</code>
+ * <li>  ------------------------------------------
+ * <li> <code>User user = session.getUser();</code>
+ * <ul> <li> <code>user.getUserId() => demoUser4</code>
+ * <li> <code>user.getInternalId() => be2dd2e:12a82ba707e:-7fee</code>
+ * <li> <code>user.getCn() => JoeUser4</code>
+ * <li> <code>user.getDescription() => Demo Test User 4</code>
+ * <li> <code>user.getOu() => test</code>
+ * <li> <code>user.getSn() => User4</code>
+ * <li> <code>user.getBeginDate() => 20090101</code>
+ * <li> <code>user.getEndDate() => none</code>
+ * <li> <code>user.getBeginLockDate() => none</code>
+ * <li> <code>user.getEndLockDate() => none</code>
+ * <li> <code>user.getDayMask() => 1234567</code>
+ * <li> <code>user.getTimeout() => 60</code>
+ * <li> <code>List<UserRole> roles = session.getRoles();</code>
+ * <ul> <li><code>UserRole userRole = roles.get(i);</code>
+ * <li> <code>userRole.getName() => role1</code>
+ * <li> <code>userRole.getBeginTime() => 0000</code>
+ * <li> <code>userRole.getEndTime() => 0000</code>
+ * <li> <code>userRole.getBeginDate() => none</code>
+ * <li> <code>userRole.getEndDate() => none</code>
+ * <li> <code>userRole.getBeginLockDate() => null</code>
+ * <li> <code>userRole.getEndLockDate() => null</code>
+ * <li> <code>userRole.getDayMask() => null</code>
+ * <li> <code>userRole.getTimeout() => 0</code>
+ * <li> <code>List<UserAdminRole> adminRoles = session.getAdminRoles();</code>
+ * </ul>
+ * <ul> <li><code>UserAdminRole userAdminRole = adminRoles.get(i);</code>
+ * <li> <code>userAdminRole.getName() => DemoAdminUsers</code>
+ * <li> <code>userAdminRole.getBeginTime() => 0000</code>
+ * <li> <code>userAdminRole.getEndTime() => 0000</code>
+ * <li> <code>userAdminRole.getBeginDate() => none</code>
+ * <li> <code>userAdminRole.getEndDate() => none</code>
+ * <li> <code>userAdminRole.getBeginLockDate() => null</code>
+ * <li> <code>userAdminRole.getEndLockDate() => null</code>
+ * <li> <code>userAdminRole.getDayMask() => null</code>
+ * <li> <code>userAdminRole.getTimeout() => 0</code>
+ * <li> <code>userAdminRole.getOsPs() => [ftT3POrg10, ftT4POrg10]</code>
+ * <li> <code>userAdminRole.getOsUs() => [ftT1UOrg10, ftT2UOrg10]</code>
+ * <li> <code>userAdminRole.getBeginRange() => ftT14Role1</code>
+ * <li> <code>userAdminRole.getEndRange() => ftT14Role10</code>
+ * <li> <code>userAdminRole.getBeginInclusive() => true</code>
+ * <li> <code>userAdminRole.getEndInclusive() => false</code>
+ * </ul>
+ * </ul>
+ * <p/>
+ * Sample Data data contained within this Entity.
+ * <p/>
+ * Ses UID      [demoUser4]:<br />
+ * Ses IID      [ccbb2929-bf01-413d-b768-529de4d428e5]<br />
+ * Ses ERR      [0]<br />
+ * Ses WARN     [10]<br />
+ * Ses MSG      [checkPwPolicies for userId <demouser4> PASSWORD CHECK SUCCESS]<br />
+ * Ses EXP      [0]<br />
+ * Ses GRAC     [0]<br />
+ * Ses AUTH     [true]<br />
+ * Ses LAST     [1297408501356]<br />
+ * Ses SID      [fc228713-1242-4061-9d8a-d4860bf8d3d8]<br />
+ * ------------------------------------------<br />
+ * Usr UID      [demoUser4]<br />
+ * Usr IID      [ccbb2929-bf01-413d-b768-529de4d428e5]<br />
+ * Usr CN       [JoeUser4]<br />
+ * Usr DESC     [Demo Test User 4]<br />
+ * Usr OU       [demousrs1]<br />
+ * Usr SN       [User4]<br />
+ * Usr BDTE     [20090101]<br />
+ * Usr EDTE     [20990101]<br />
+ * Usr BLDT     [none]<br />
+ * Usr ELDT     [none]<br />
+ * Usr DMSK     [1234567]<br />
+ * Usr TO       [60]<br />
+ * Usr REST     [false]<br />
+ * Usr PROP1    [customerNumber, 3213432]<br />
+ * <p/>
+ * USER RBAC ROLE[0]:<br />
+ * Rle  role name       [role1]<br />
+ * Rle  begin time      [0000]<br />
+ * Rle  end time        [0000]<br />
+ * Rle  begin date      [20110101]<br />
+ * Rle  end date        [none]<br />
+ * Rle  begin lock      [none]<br />
+ * Rle  end lock        [none]<br />
+ * Rle  day mask        [all]<br />
+ * Rle  time out        [60]<br />
+ * <p/>
+ * USER ADMIN ROLE[0]:<br />
+ * Adm  admin role name [DemoAdminUsers]<br />
+ * Adm  OsU             [Dev1]<br />
+ * Adm  OsP             [App1]<br />
+ * Adm  begin range     [role1]<br />
+ * Adm  end range       [role3]<br />
+ * Adm  begin time      [0000]<br />
+ * Adm  end time        [0000]<br />
+ * Adm  begin date      [20110101]<br />
+ * Adm  end date        [none]<br />
+ * Adm  begin lock      [none]<br />
+ * Adm  end lock        [none]<br />
+ * Adm  day mask        [23456]<br />
+ * Adm  time out        [30]<br />
+ * <p/>
+ * @author Shawn McKinney
+ */
+@XmlRootElement(name = "fortSession")
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "session", propOrder = {
+    "user",
+    "isAuthenticated",
+    "sessionId",
+    "lastAccess",
+    "timeout",
+    "errorId",
+    "expirationSeconds",
+    "graceLogins",
+    "message",
+    "warnings"
+/*    "warningId"*/
+})
+public class Session  extends FortEntity implements PwMessage, java.io.Serializable
+{
+    private User user;
+    private String sessionId;
+    private long lastAccess;
+    private int timeout;
+/*    private int warningId;*/
+    private int errorId;
+    private int graceLogins;
+    private int expirationSeconds;
+    private boolean isAuthenticated;
+    private String message;
+    @XmlElement(nillable = true)
+    private List<Warning> warnings;
+
+    /**
+     * A 'true' value here indicates user successfully authenticated with Fortress.
+     *
+     * @return boolean indicating successful authentication.
+     */
+    public boolean isAuthenticated()
+    {
+        return isAuthenticated;
+    }
+
+    private void init()
+    {
+        // generate a unique id that will be used as the id for this session:
+        UUID uuid = UUID.randomUUID();
+        this.sessionId = uuid.toString();
+    }
+
+    /**
+     * Copy values from incoming Session object.
+     *
+     * @param inSession contains Session values.
+     */
+    public void copy(Session inSession)
+    {
+        this.user = inSession.getUser();
+        // don't copy session id:
+        //this.sessionId = inSession.getSessionId();
+        this.lastAccess = inSession.getLastAccess();
+        this.timeout = inSession.getTimeout();
+/*        this.warningId = inSession.getWarningId();*/
+        this.errorId = inSession.getErrorId();
+        this.graceLogins = inSession.getGraceLogins();
+        this.expirationSeconds = inSession.expirationSeconds;
+        this.isAuthenticated = inSession.isAuthenticated();
+        this.message = inSession.getMsg();
+        this.warnings = inSession.getWarnings();
+    }
+
+    /**
+     * Default constructor for Fortress Session.
+     */
+    public Session()
+    {
+        init();
+        // this class will not check for null on user object.
+        this.user = new User();
+    }
+
+    /**
+     * Construct a new Session instance with given User entity.
+     *
+     * @param user contains the User attributes that are associated with the Session.
+     */
+    public Session(User user)
+    {
+        init();
+        this.user = user;
+    }
+
+    /**
+     * Construct a new Session instance with given User entity.
+     *
+     * @param user contains the User attributes that are associated with the Session.
+     */
+    public Session(User user, String sessionId)
+    {
+        this.sessionId = sessionId;
+        this.user = user;
+    }
+
+    /**
+     * Return the unique id that is associated with User.  This attribute is generated automatically
+     * by Fortress when new Session is created and is not known or changeable by external client.
+     *
+     * @return attribute maps to unique sessionId associated with user's session.
+     */
+    public String getSessionId()
+    {
+        return this.sessionId;
+    }
+
+
+    /**
+     * Return the User entity that is associated with this entity.
+     *
+     * Sample User data contained in Session object:
+     * <p/>
+     * ------------------------------------------<br />
+     * U   UID  [demoUser4]<br />
+     * U   IID  [ccbb2929-bf01-413d-b768-529de4d428e5]<br />
+     * U   CN   [JoeUser4]<br />
+     * U   DESC [Demo Test User 4]<br />
+     * U   OU   [demousrs1]<br />
+     * U   SN   [User4]<br />
+     * U   BDTE [20090101]<br />
+     * U   EDTE [20990101]<br />
+     * U   BLDT [none]<br />
+     * U   ELDT [none]<br />
+     * U   DMSK [1234567]<br />
+     * U   TO   [60]<br />
+     * U   REST [false]<br />
+     * U   PROP[0]=customerNumber VAL=3213432<br />
+     * <p/>
+     * USER ROLE[0]:<br />
+     * role name <role1><br />
+     * begin time <0000><br />
+     * end time <0000><br />
+     * begin date <none><br />
+     * end date <none><br />
+     * begin lock <none><br />
+     * end lock <none><br />
+     * day mask <all><br />
+     * time out <0><br />
+     * <p/>
+     * USER ADMIN ROLE[0]:<br />
+     * admin role name <DemoAdminUsers><br />
+     * OsU <null><br />
+     * OsP <null><br />
+     * begin range <null><br />
+     * end range <null><br />
+     * begin time <0000><br />
+     * end time <0000><br />
+     * begin date <none><br />
+     * end date <none><br />
+     * begin lock <none><br />
+     * end lock <none><br />
+     * day mask <all><br />
+     * time out <0><br />
+     * <p/>
+     * @return User entity that contains userid, roles and other attributes valid for Session.
+     */
+    public User getUser()
+    {
+        return this.user;
+    }
+
+    /**
+     * Return the userId that is associated with this Session object.
+     *
+     * @return userId maps to the 'uid' attribute on the 'inetOrgPerson' object class.
+     */
+    public String getUserId()
+    {
+        return this.user.getUserId();
+    }
+
+    /**
+     * Return the internal userId that is associated with User.  This attribute is generated automatically
+     * by Fortress when new User is added to directory and is not known or changeable by external client.
+     *
+     * @return attribute maps to 'ftId' in 'ftUserAttrs' object class.
+     */
+    public String getInternalUserId()
+    {
+        return this.user.getInternalId();
+    }
+
+    /**
+     * Return the list of User's RBAC Roles that have been activated into User's session.  This list will not include
+     * ascendant RBAC roles which may be retrieved using {@link AccessMgrImpl#authorizedRoles(Session)}.
+     *
+     * @return List containing User's RBAC roles.  This list may be empty if User not assigned RBAC.
+     */
+    public List<UserRole> getRoles()
+    {
+        List<UserRole> roles = null;
+
+        if (user != null)
+            roles = user.getRoles();
+
+        return roles;
+    }
+
+    /**
+     * Return a list of User's Admin Roles  that have been activated into User's session.  This list will not include
+     * ascendant ARBAC roles which may be retrieved using {@link org.apache.directory.fortress.core.DelAccessMgr#authorizedAdminRoles(Session)}.
+     *
+     * @return List containing User's Admin roles.  This list may be empty if User not assigned Administrative role.
+     */
+    public List<UserAdminRole> getAdminRoles()
+    {
+        List<UserAdminRole> roles = null;
+
+        if (user != null)
+            roles = user.getAdminRoles();
+
+        return roles;
+    }
+
+    /**
+     * Returns the last access time in milliseconds. Note that while the unit of time of the return value is a millisecond,
+     * the granularity of the value depends on the underlying operating system and may be larger. For example, many
+     * operating systems measure time in units of tens of milliseconds.
+     *
+     * @return the difference, measured in milliseconds, between the last access time and midnight, January 1, 1970 UTC.
+     */
+    public long getLastAccess()
+    {
+        return this.lastAccess;
+    }
+
+    /**
+     * Gets the message that is associated with the user's last authentication attempt.
+     *
+     * @return String contains text explaining result of user's last authentication.
+     */
+    public String getMsg()
+    {
+        return this.message;
+    }
+
+    /**
+     * Gets the attribute that specifies the number of times an expired password can
+     * be used to authenticate before failure.
+     *
+     * @return The number of logins the user has left before password fails.
+     */
+    public int getGraceLogins()
+    {
+        return this.graceLogins;
+    }
+
+    /**
+     * This attribute specifies the maximum number of seconds before a
+     * password is due to expire that expiration warning messages will be
+     * returned to an authenticating user.
+     * <p/>
+     * If this attribute is not present, or if the value is 0 no warnings
+     * will be returned.  If not 0, the value must be smaller than the value
+     * of the pwdMaxAge attribute.
+     *
+     * @return attribute is computed based on last time user has changed their password.
+     */
+    public int getExpirationSeconds()
+    {
+        return this.expirationSeconds;
+    }
+
+    /**
+     * Get the integer timeout that contains max time (in seconds) that User's session may remain inactive.
+     * This attribute is optional but if set will be validated for reasonableness.
+     *
+     * @return int maps to 'ftCstr' attribute in 'ftUserAttrs' object class.
+     */
+    private int getTimeout()
+    {
+        return this.timeout;
+    }
+
+    /**
+     * Get the value that will be set to 'true' if user has successfully authenticated with Fortress for this Session.  This value is set by
+     * the Fortress DAO object.
+     *
+     * @return value indicates result of authentication.
+     */
+    public boolean setAuthenticated()
+    {
+        return this.isAuthenticated;
+    }
+
+    /**
+     * Return the error id that is associated with the password policy checks.  a '0' indicates no errors.
+     * <ul>
+     * <li> <code>INVALID_PASSWORD_MESSAGE = -10;</code>
+     * <li> <code>GOOD = 0;</code>
+     * <li> <code>PASSWORD_HAS_EXPIRED = 100;</code>
+     * <li> <code>ACCOUNT_LOCKED = 101;</code>
+     * <li> <code>CHANGE_AFTER_RESET = 102;</code>
+     * <li> <code>NO_MODIFICATIONS = 103;</code>
+     * <li> <code>MUST_SUPPLY_OLD = 104;</code>
+     * <li> <code>INSUFFICIENT_QUALITY = 105;</code>
+     * <li> <code>PASSWORD_TOO_SHORT = 106;</code>
+     * <li> <code>PASSWORD_TOO_YOUNG = 107;</code>
+     * <li> <code>HISTORY_VIOLATION = 108;</code>
+     * <li> <code>ACCOUNT_LOCKED_CONSTRAINTS = 109;</code>
+     * </ul>
+     * <p/>
+     *
+     * @return int contains the error id that was generated on the user's last authentication.
+     */
+    public int getErrorId()
+    {
+        return this.errorId;
+    }
+
+    /**
+     * Set a User entity into the Session.
+     * Sample User data contained in Session object:
+     * <p/>
+     * ------------------------------------------<br />
+     * U   UID  [demoUser4]<br />
+     * U   IID  [ccbb2929-bf01-413d-b768-529de4d428e5]<br />
+     * U   CN   [JoeUser4]<br />
+     * U   DESC [Demo Test User 4]<br />
+     * U   OU   [demousrs1]<br />
+     * U   SN   [User4]<br />
+     * U   BDTE [20090101]<br />
+     * U   EDTE [20990101]<br />
+     * U   BLDT [none]<br />
+     * U   ELDT [none]<br />
+     * U   DMSK [1234567]<br />
+     * U   TO   [60]<br />
+     * U   REST [false]<br />
+     * U   PROP[0]=customerNumber VAL=3213432<br />
+     * <p/>
+     * USER ROLE[0]:<br />
+     * role name <role1><br />
+     * begin time <0000><br />
+     * end time <0000><br />
+     * begin date <none><br />
+     * end date <none><br />
+     * begin lock <none><br />
+     * end lock <none><br />
+     * day mask <all><br />
+     * time out <0><br />
+     * <p/>
+     * USER ADMIN ROLE[0]:<br />
+     * admin role name <DemoAdminUsers><br />
+     * OsU <null><br />
+     * OsP <null><br />
+     * begin range <null><br />
+     * end range <null><br />
+     * begin time <0000><br />
+     * end time <0000><br />
+     * begin date <none><br />
+     * end date <none><br />
+     * begin lock <none><br />
+     * end lock <none><br />
+     * day mask <all><br />
+     * time out <0><br />
+     * <p/>
+     * @param user Contains userId, roles and other security attributes used for access control.
+     */
+    public void setUser(User user)
+    {
+        this.user = user;
+    }
+
+    /**
+     * Set the internal userId that is associated with User.  This method is used by DAO class and
+     * is generated automatically by Fortress.  Attribute stored in LDAP cannot be changed by external caller.
+     * This method can be used by client for search purposes only.
+     *
+     * @param internalUserId maps to 'ftId' in 'ftUserAttrs' object class.
+     */
+    public void setInternalUserId(String internalUserId)
+    {
+        this.user.setInternalId(internalUserId);
+    }
+
+    /**
+     * Set the value to 'true' indicating that user has successfully authenticated with Fortress.  This value is set by
+     * the Fortress DAO object.
+     *
+     * @param authenticated indicates result of authentication.
+     */
+    public void setAuthenticated(boolean authenticated)
+    {
+        isAuthenticated = authenticated;
+    }
+
+    /**
+     * Set the userId that is associated with User.  UserId is required attribute and must be set on add, update, delete, createSession, authenticate, etc..
+     *
+     * @param userId maps to 'uid' attribute in 'inNetOrgPerson' object class.
+     */
+    public void setUserId(String userId)
+    {
+        this.user.setUserId(userId);
+    }
+
+
+    /**
+     * Add a list of RBAC Roles to this entity that have been activated into Session or are under consideration for activation.
+     *
+     * @param roles List of type UserRole that contains at minimum UserId and Role name.
+     */
+    public void setRoles(List<UserRole> roles)
+    {
+        this.user.setRoles(roles);
+    }
+
+    /**
+     * Add a single user-role object to the list of UserRoles for User.
+     *
+     * @param role UserRole contains at least userId and role name (activation) and additional constraints (assignment)
+     */
+    public void setRole(UserRole role)
+    {
+        user.setRole(role);
+    }
+
+    /**
+     * Set the integer timeout that contains max time (in seconds) that User's session may remain inactive.
+     * This attribute is optional but if set will be validated for reasonableness.
+     *
+     * @param timeout maps to 'ftCstr' attribute in 'ftUserAttrs' object class.
+     */
+    private void setTimeout(int timeout)
+    {
+        this.timeout = timeout;
+    }
+
+    /**
+     * Set the last access time in milliseconds. Note that while the unit of time of the return value is a millisecond,
+     * the granularity of the value depends on the underlying operating system and may be larger. For example, many
+     * operating systems measure time in units of tens of milliseconds.
+     */
+    public void setLastAccess()
+    {
+        this.lastAccess = System.currentTimeMillis();
+    }
+
+    /**
+     * Set the message that is associated with the user's last authentication attempt.
+     *
+     * @param message Contains text explaining result of user's last authentication.
+     */
+    public void setMsg(String message)
+    {
+        this.message = message;
+    }
+
+    /**
+     * Set the error id that is associated with the password policy checks.  a '0' indicates no errors.
+     * <ul>
+     * <li> <code>INVALID_PASSWORD_MESSAGE = -10;</code>
+     * <li> <code>GOOD = 0;</code>
+     * <li> <code>PASSWORD_HAS_EXPIRED = 100;</code>
+     * <li> <code>ACCOUNT_LOCKED = 101;</code>
+     * <li> <code>CHANGE_AFTER_RESET = 102;</code>
+     * <li> <code>NO_MODIFICATIONS = 103;</code>
+     * <li> <code>MUST_SUPPLY_OLD = 104;</code>
+     * <li> <code>INSUFFICIENT_QUALITY = 105;</code>
+     * <li> <code>PASSWORD_TOO_SHORT = 106;</code>
+     * <li> <code>PASSWORD_TOO_YOUNG = 107;</code>
+     * <li> <code>HISTORY_VIOLATION = 108;</code>
+     * <li> <code>ACCOUNT_LOCKED_CONSTRAINTS = 109;</code>
+     * </ul>
+     * <p/>
+     *
+     * @param error contains the error id that was generated on the user's last authentication.
+     */
+    public void setErrorId(int error)
+    {
+        this.errorId = error;
+    }
+
+    /**
+     * This attribute specifies the number of times an expired password can
+     * be used to authenticate.
+     *
+     * @param grace The number of logins the user has left before password fails.
+     */
+    public void setGraceLogins(int grace)
+    {
+        this.graceLogins = grace;
+    }
+
+    /**
+     * This attribute specifies the maximum number of seconds before a
+     * password is due to expire that expiration warning messages will be
+     * returned to an authenticating user.
+     * <p/>
+     * If this attribute is not present, or if the value is 0 no warnings
+     * will be returned.  If not 0, the value must be smaller than the value
+     * of the pwdMaxAge attribute.
+     *
+     * @param expire attribute is computed based on last time user has changed their password.
+     */
+    public void setExpirationSeconds(int expire)
+    {
+        this.expirationSeconds = expire;
+    }
+
+    /**
+     * Get the warnings attached to this Session.  Used for processing password policy scenarios, e.g.. password expiring message.
+     *
+     * @return null value, zero or more objects of type {@link Warning} will be returned.  Note: the caller of this method must ensure a not null condition before use.
+     */
+    public List<Warning> getWarnings()
+    {
+        return warnings;
+    }
+
+    /**
+     * Set the warnings on this Session.  Used for processing password policy scenarios, e.g.. password expiring message.
+     * Not intended for use outside of Fortress packages.
+     *
+     * @param warnings zero or more objects of type warning may be set on a Fortress session.
+     */
+    public void setWarnings( List<Warning> warnings )
+    {
+        this.warnings = warnings;
+    }
+
+    /**
+     * Add a warning to the collection into Fortress Session object.  Used for processing password policy scenarios, e.g.. password expiring message.
+     * Not intended for use outside of Fortress packages.
+     *
+     * @param warning one object of type warning will be added to Fortress session.
+     */
+    public void setWarning( Warning warning )
+    {
+        if ( warnings == null )
+        {
+            warnings = new ArrayList<>();
+        }
+        this.warnings.add( warning );
+    }
+}
\ No newline at end of file