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:45 UTC

[26/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/Graphable.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/rbac/Graphable.java b/src/main/java/org/apache/directory/fortress/core/rbac/Graphable.java
new file mode 100644
index 0000000..ad2909f
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/rbac/Graphable.java
@@ -0,0 +1,90 @@
+/*
+ *   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.Set;
+
+/**
+ * The Fortress Graphable interface prescribes attributes that are used to maintain implementor within a simple directed graph.
+ * {@link org.apache.directory.fortress.core.rbac.Role}, {@link org.apache.directory.fortress.core.rbac.AdminRole}, {@link org.apache.directory.fortress.core.rbac.OrgUnit} entities.
+ * <p/>
+ * <img src="../doc-files/HierRoleAscendants.png">
+ * <p/>
+ * <p/>
+ * <img src="../doc-files/HierRoleDescendants.png">
+ * <p/>
+ * <p/>
+ * <img src="../doc-files/HierRoleSimple.png">
+ * <p/>
+ * <h4>Manageable Schema</h4>
+ * The entity maps to Fortress LDAP attributetype ( 1.3.6.1.4.1.1.38088.1.28
+ * NAME 'ftParents'
+ * DESC 'Fortress Parent Nodes'
+ * EQUALITY caseIgnoreMatch
+ * SUBSTR caseIgnoreSubstringsMatch
+ * SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+ * <p/>
+ *
+ * @author Shawn McKinney
+ */
+public interface Graphable
+{
+    /**
+     * Get the names of roles that are parents (direct ascendants) of this role.
+     *
+     * @return Set of parent role names assigned to this role.
+     */
+    public Set<String> getParents();
+
+    /**
+     * Set the names of roles names that are parents (direct ascendants) of this role.
+     *
+     * @param parents contains the Set of parent role names assigned to this role.
+     */
+    public void setParents(Set<String> parents);
+
+    /**
+     * Set the occupant attribute with the contents of the User dn.
+     *
+     * @param parent maps to 'ftParents' attribute on 'ftRls' object class.
+     */
+    public void setParent(String parent);
+
+    /**
+     * Set the occupant attribute with the contents of the User dn.
+     *
+     * @param parent maps to 'ftParents' attribute on 'ftRls' object class.
+     */
+    public void delParent(String parent);
+
+    /**
+     * Get the name required attribute of the node.
+     *
+     * @return attribute maps to attribute  on 'organizationalUnit' object class.
+     */
+    public String getName();
+
+    /**
+     * Sets the required name attribute on the node.
+     *
+     */
+    public void setName(String name);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/687ee1ad/src/main/java/org/apache/directory/fortress/core/rbac/Hier.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/rbac/Hier.java b/src/main/java/org/apache/directory/fortress/core/rbac/Hier.java
new file mode 100755
index 0000000..9e0db40
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/rbac/Hier.java
@@ -0,0 +1,321 @@
+/*
+ *   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.ArrayList;
+import java.util.List;
+
+/**
+ * All entities (User, Role, Permission, Policy, SDSet, etc...) are used to carry data between Fortress's
+ * layers starting with the (1) Manager layer down thru middle (2) Process layer and it's processing rules into
+ * (3) DAO layer where persistence with the OpenLDAP server occurs.  The clients must instantiate an Fortress entity before use
+ * and must provide enough information to uniquely identity target record for reads.
+ * <p/>
+ * <h4>Hierarchical Relationship Schema</h4>
+ * <p/>
+ * The Fortress ftHier Entity Class is used internal to Fortress and usually does not require manipulation by external program.  The
+ * entity is a composite of 3 different LDAP Schema 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. ftHier AUXILIARY Object Class is used to store parent to child relationships on target entity.
+ * <pre>
+ * ------------------------------------------
+ * Fortress Hierarchies Structural Object Class
+ * objectclass	( 1.3.6.1.4.1.38088.2.7
+ * NAME 'ftHier'
+ * DESC 'Fortress Hierarchy Structural Object Class'
+ * SUP organizationalrole
+ * STRUCTURAL
+ * MUST (
+ *      cn
+ *  )
+ * MAY (
+ *      ftRels $
+ *      description
+ *  )
+ * )
+ * <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
+ */
+public class Hier extends FortEntity
+    implements java.io.Serializable
+{
+    public Op op;
+    public Type type;
+    private List<Relationship> relationships;
+
+    /**
+     * default constructor is used by internal components.
+     */
+    public Hier()
+    {
+    }
+
+    /**
+     * construct hierarchy given a list of parent-child relationships.
+     *
+     * @param relationships maps to 'ftRels' attribute on 'ftHier' object class.
+     */
+    public Hier(List<Relationship> relationships)
+    {
+        this.relationships = relationships;
+    }
+
+    /**
+     * Construct entity given a hierarchy type - ROLE, AROLE, USER, PERM.
+     *
+     * @param type determines where the target node resides.  For example the 'ROLE' type will specify the RBAC Role container as target.
+     */
+    public Hier(Type type)
+    {
+        this.type = type;
+    }
+
+    /**
+     * Construct entity given a parent, child and a hierarchy type.
+     *
+     * @param type   determines where the target node resides.  For example the 'ROLE' type will specify the RBAC Role container as target.
+     * @param child  maps to the 'ftRels' attribute in 'ftHier' object class.
+     * @param parent maps to the 'ftRels' attribute in 'ftHier' object class.
+     */
+    public Hier(Type type, String child, String parent)
+    {
+        this.type = type;
+        setRelationship(child, parent);
+    }
+
+    /**
+     * Construct entity given a parent and child.
+     *
+     * @param child  maps to the 'ftRels' attribute in 'ftHier' object class.
+     * @param parent maps to the 'ftRels' attribute in 'ftHier' object class.
+     */
+    public Hier(String child, String parent)
+    {
+        setRelationship(child, parent);
+    }
+
+    /**
+     * Operation type specifies if Add, Update or Deletion of relationship is being targeted.
+     */
+    public enum Op
+    {
+        /**
+         * Add a new hierarchical relationship to the data set.
+         */
+        ADD,
+
+        /**
+         * Modify an existing hierarchical relationship in the data set.
+         */
+        MOD,
+
+        /**
+         * Remove an existing hierarchical relationship from the data set.
+         */
+        REM
+    }
+
+    /**
+     * Return the operation to execute on behalf of this entity.
+     *
+     * @return Op value which maps to Add, Update or Delete attribute targets.
+     */
+    public Op getOp()
+    {
+        return op;
+    }
+
+    /**
+     * The the operation for which this entity is bound for.  Add, Update or Delete.
+     *
+     * @param op type contains 'ADD', 'MOD', or 'REM'.
+     */
+    public void setOp(Op op)
+    {
+        this.op = op;
+    }
+
+    /**
+     * Enumeration is used to specify which hierarchy node this entity is bound to.  RBAC Role, Admin Roles, User OU or Perm OU.
+     */
+    public enum Type
+    {
+        /**
+         * RBAC Role data set
+         */
+        ROLE,
+
+        /**
+         * Administrative Role data set
+         */
+        AROLE,
+
+        /**
+         * User OU data set
+         */
+        USER,
+
+        /**
+         * Permission OU data set
+         */
+        PERM
+    }
+
+    /**
+     * Return required the type of node this entity is bound to.
+     *
+     * @return variable specifies which directory node the hierarchy entity is bound to.
+     */
+    public Type getType()
+    {
+        return type;
+    }
+
+    /**
+     * Set the required type which determines which directory node this entity is bound to.
+     *
+     * @param type variable specifies which directory node the hierarchy entity is bound to.
+     */
+    public void setType(Type type)
+    {
+        this.type = type;
+    }
+
+
+    /**
+     * Return true if child and parent represent a valid relationship that is contained within the collection of
+     * relationships.
+     *
+     * @param role   attribute maps to the 'ftRels' attribute on 'ftHier' object class.
+     * @param parent attribute maps to the 'ftRels' attribute on 'ftHier' object class.
+     */
+    public boolean isRelationship(String role, String parent)
+    {
+        boolean result = false;
+        if (relationships != null)
+        {
+            result = relationships.contains(new Relationship(role.toUpperCase(), parent.toUpperCase()));
+        }
+
+        return result;
+    }
+
+    /**
+     * Set the child and parent into the collection of valid relationships stored in this entity.
+     *
+     * @param role   attribute maps to the 'ftRels' attribute on 'ftHier' object class.
+     * @param parent attribute maps to the 'ftRels' attribute on 'ftHier' object class.
+     */
+    public void setRelationship(String role, String parent)
+    {
+        if (relationships == null)
+        {
+            relationships = new ArrayList<>();
+        }
+
+        relationships.add(new Relationship(role.toUpperCase(), parent.toUpperCase()));
+    }
+
+    /**
+     * Set the relationship object into the collection of valid relationships stored in this entity.
+     *
+     * @param rel attribute maps to the 'ftRels' attribute on 'ftHier' object class.
+     */
+    public void setRelationship(Relationship rel)
+    {
+        if (relationships == null)
+        {
+            relationships = new ArrayList<>();
+        }
+
+        relationships.add(rel);
+    }
+
+    /**
+     * Remove the specified relationship from the collection of valid relationships stored in this entity.
+     *
+     * @param role   attribute maps to the 'ftRels' attribute on 'ftHier' object class.
+     * @param parent attribute maps to the 'ftRels' attribute on 'ftHier' object class.
+     */
+    public void removeRelationship(String role, String parent)
+    {
+        if (relationships != null)
+        {
+            relationships.remove(new Relationship(role.toUpperCase(), parent.toUpperCase()));
+        }
+    }
+
+    /**
+     * Return the list of relationships that are set in collection on this entity.
+     *
+     * @return List of relationships that map to the 'ftRels' attribute on the 'ftHier' object class.
+     */
+    public List<Relationship> getRelationships()
+    {
+        return relationships;
+    }
+
+    /**
+     * Set the list of relationships that are set in collection on this entity.
+     *
+     * @param relationships that map to the 'ftRels' attribute on the 'ftHier' object class.
+     */
+    public void setRelationships(List<Relationship> relationships)
+    {
+        this.relationships = relationships;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/687ee1ad/src/main/java/org/apache/directory/fortress/core/rbac/HierUtil.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/rbac/HierUtil.java b/src/main/java/org/apache/directory/fortress/core/rbac/HierUtil.java
new file mode 100755
index 0000000..1305190
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/rbac/HierUtil.java
@@ -0,0 +1,716 @@
+/*
+ *   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.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+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.GlobalErrIds;
+import org.apache.directory.fortress.core.SecurityException;
+import org.apache.directory.fortress.core.ValidationException;
+import org.apache.directory.fortress.core.util.attr.VUtil;
+
+
+/**
+ * This utility performs base hierarchical processing using this software <a href="http://www.jgrapht.org/">JGraphT</a></li>.
+ * </p>
+ * It is used to provide hierarchical processing APIs for the following data sets:
+ * <ol>
+ * <li>RBAC Role relations are stored in {@code cn=Hierarchies,ou=Roles,ou=RBAC} ldap node and cached as singleton in {@link RoleUtil}</li>
+ * <li>ARBAC Admin Role relations are stored in {@code cn=Hierarchies,ou=AdminRoles,ou=ARBAC} ldap node and cached as singleton in {@link AdminRoleUtil}</li>
+ * <li>User Organizational Unit relations are stored in {@code cn=Hierarchies,ou=OS-U,ou=ARBAC} node and cached as {@link org.apache.directory.fortress.core.rbac.UsoUtil}</li>
+ * <li>Permission Organizational Unit relations are stored in {@code cn=Hierarchies,ou=OS-P,ou=ARBAC} node and cached as {@link org.apache.directory.fortress.core.rbac.PsoUtil}</li>
+ * </ol>
+ * This class...
+ * <ol>
+ * <li>manipulates data that is stored as singleton inside other classes 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>processes general hierarchical data structure i.e. allows multiple inheritance with parents.</li>
+ * <li>constructs and parses simple directed graphs.</li>
+ * </ol>
+ * Static methods on this class are intended for use by other Fortress classes, and cannot be directly invoked by outside programs.
+ * <p/>
+ * This class is thread safe.
+ * <p/>
+ *
+ * @author Shawn McKinney
+ */
+final class HierUtil
+{
+    /**
+     * Constants used within this class:
+     */
+    private static final String CLS_NM = HierUtil.class.getName();
+    private static final Logger LOG = LoggerFactory.getLogger( CLS_NM );
+    private static final String VERTEX = "Vertex";
+
+    /**
+     * The 'Type' attribute corresponds to what type of hierarchy is being referred to.
+     */
+    static enum Type
+    {
+        ROLE,
+        ARLE,
+        USO,
+        PSO
+    }
+
+    private static final Map<String, Object> synchMap = new HashMap<>();
+
+
+    /**
+     *
+     * @param contextId
+     * @param type
+     * @return
+     */
+    static Object getLock( String contextId, Type type )
+    {
+        Object synchObj = synchMap.get( getSynchKey( contextId, type ) );
+        if ( synchObj == null )
+        {
+            synchObj = new Object();
+            synchMap.put( getSynchKey( contextId, type ), synchObj );
+        }
+        return synchObj;
+    }
+
+
+    /**
+     *
+     * @param contextId
+     * @param type
+     * @return
+     */
+    private static String getSynchKey( String contextId, Type type )
+    {
+        return type.toString() + ":" + contextId;
+    }
+
+
+    /**
+     * This api is used to determine parentage for Hierarchical processing.
+     * It evaluates three 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 graph     contains a reference to simple digraph {@code org.jgrapht.graph.SimpleDirectedGraph}.
+     * @param child     contains name of child.
+     * @param parent    contains 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( SimpleDirectedGraph<String, Relationship> graph, String child, String parent,
+        boolean mustExist )
+        throws ValidationException
+    {
+        // Ensure the two nodes aren't the same:
+        if ( child.equalsIgnoreCase( parent ) )
+        {
+            String error = "validateRelationship child [" + child + "] same as parent [" + parent + "]";
+            throw new ValidationException( GlobalErrIds.HIER_REL_INVLD, error );
+        }
+        Relationship rel = new Relationship( child.toUpperCase(), parent.toUpperCase() );
+        // Ensure there is a valid child to parent relationship.
+        if ( mustExist && !isRelationship( graph, rel ) )
+        {
+            String error = "validateRelationship child [" + child + "] does not have parent [" + parent + "]";
+            throw new ValidationException( GlobalErrIds.HIER_REL_NOT_EXIST, error );
+        }
+        // Ensure the child doesn't already have the parent as an ascendant.
+        else if ( !mustExist && isAscendant( child, parent, graph ) )
+        {
+            String error = "validateRelationship child [" + child + "] already has parent [" + parent + "]";
+            throw new ValidationException( GlobalErrIds.HIER_REL_EXIST, error );
+        }
+        // Prevent cycles by making sure the child isn't an ascendant of parent.
+        else if ( !mustExist && isDescedant( parent, child, graph ) )
+        {
+            String error = "validateRelationship child [" + child + "] is parent of [" + parent + "]";
+            throw new ValidationException( GlobalErrIds.HIER_REL_CYCLIC, error );
+        }
+    }
+
+
+    /**
+     * This method Convert from logical, {@code org.jgrapht.graph.SimpleDirectedGraph} to ldap entity, {@link org.apache.directory.fortress.core.rbac.Hier}.
+     * The conversion iterates over all edges in the graph and loads the corresponding {@link Relationship} data
+     * into the ldap entity.  The ldap entity stores this data physically in the {@code ftRels} attribute of {@code ftHier} object class.
+     *
+     * @param graph contains a reference to simple digraph {@code org.jgrapht.graph.SimpleDirectedGraph}.
+     * @return reference to hierarchical ldap entity {@link org.apache.directory.fortress.core.rbac.Hier}.
+     */
+    static Hier toHier( SimpleDirectedGraph<String, Relationship> graph )
+    {
+        Hier he = new Hier();
+        Set<Relationship> eSet = graph.edgeSet();
+        for ( Relationship edge : eSet )
+        {
+            he.setRelationship( edge );
+        }
+        return he;
+    }
+
+
+    /**
+     * This method converts from physical ldap entity format, {@link Hier} to logical {@code org.jgrapht.graph.SimpleDirectedGraph}.
+     *
+     * @param hier contains parent-child relationship in preparation to storing in ldap {@code ftRels} attribute of {@code ftHier} object class.
+     * @return {@code org.jgrapht.graph.SimpleDirectedGraph} containing the vertices of {@code String}, and edges, as {@link Relationship}s that correspond to relational data.
+     */
+    private static SimpleDirectedGraph<String, Relationship> toGraph( Hier hier )
+    {
+        LOG.debug( "toGraph" );
+        SimpleDirectedGraph<String, Relationship> graph =
+            new SimpleDirectedGraph<>( Relationship.class );
+        List<Relationship> edges = hier.getRelationships();
+        if ( edges != null && edges.size() > 0 )
+        {
+            for ( Relationship edge : edges )
+            {
+                String child = edge.getChild();
+                String parent = edge.getParent();
+
+                try
+                {
+                    graph.addVertex( child );
+                    graph.addVertex( parent );
+                    graph.addEdge( child, parent, edge );
+                }
+                catch (java.lang.IllegalArgumentException e)
+                {
+                    // TODO: determine if this needs to throw exception here:
+                    String error = "toGraph child: " + child + " parent: " + parent + " caught IllegalArgumentException=" + e;
+                    LOG.error( error );
+                }
+                if ( LOG.isDebugEnabled() )
+                    LOG.debug( "toGraph child={}, parent={}", child, parent );
+            }
+        }
+        return graph;
+    }
+
+
+    /**
+     * This method is synchronized and adds an edge and its associated vertices to simple directed graph stored in static memory of this process.
+     *
+     * @param graph synchronized parameter contains a reference to simple digraph {@code org.jgrapht.graph.SimpleDirectedGraph}.
+     * @param relation contains parent-child relationship targeted for addition.
+     * @return {@code org.jgrapht.graph.SimpleDirectedGraph} containing the vertices of {@code String}, and edges, as {@link Relationship}s that correspond to relational data.
+     */
+    private static void addEdge( SimpleDirectedGraph<String, Relationship> graph, Relationship relation )
+    {
+        LOG.debug( "addEdge" );
+        synchronized ( graph )
+        {
+            graph.addVertex( relation.getChild().toUpperCase() );
+            graph.addVertex( relation.getParent().toUpperCase() );
+            graph.addEdge( relation.getChild().toUpperCase(), relation.getParent().toUpperCase(), relation );
+        }
+    }
+
+
+    /**
+     * This method is synchronized and removes an edge from a simple directed graph stored in static memory of this process.
+     *
+     * @param graph synchronized parameter contains a reference to simple digraph {@code org.jgrapht.graph.SimpleDirectedGraph}.
+     * @param relation contains parent-child relationship targeted for removal.
+     * @return {@code org.jgrapht.graph.SimpleDirectedGraph} containing the vertices of {@code String}, and edges, as {@link Relationship}s that correspond to relational data.
+     */
+    private static void removeEdge( SimpleDirectedGraph<String, Relationship> graph, Relationship relation )
+    {
+        LOG.debug( "removeEdge" );
+        synchronized ( graph )
+        {
+            graph.removeEdge( relation );
+        }
+    }
+
+
+    /**
+     * Return number of children (direct descendants) a given parent node has.
+     *
+     * @param name  contains the vertex of graph to gather descendants from.
+     * @param graph contains a reference to simple digraph {@code org.jgrapht.graph.SimpleDirectedGraph}.
+     * @return int value contains the number of children of a given parent vertex.
+     */
+    static int numChildren( String name, SimpleDirectedGraph<String, Relationship> graph )
+    {
+        Map<String, String> vx = new HashMap<>();
+        vx.put( VERTEX, name.toUpperCase() );
+        return numChildren( vx, graph );
+    }
+
+
+    /**
+     * Determine if parent-child relationship exists in supplied digraph.
+     *
+     * @param graph contains a reference to simple digraph {@code org.jgrapht.graph.SimpleDirectedGraph}.
+     * @param rel   contains parent and child names.
+     * @return boolean value.  true indicates parent-child relationship exists in digraph.
+     */
+    private static boolean isRelationship( SimpleDirectedGraph<String, Relationship> graph, Relationship rel )
+    {
+        return graph.containsEdge( rel );
+    }
+
+
+    /**
+     * Determine how many children a given parent node has.
+     *
+     * @param vertex of parent.
+     * @param graph  contains a reference to simple digraph {@code org.jgrapht.graph.SimpleDirectedGraph}.
+     * @return
+     */
+    private static int numChildren( Map<String, String> vertex, SimpleDirectedGraph<String, Relationship> graph )
+    {
+        int numChildren = 0;
+        try
+        {
+            String v = vertex.get( VERTEX );
+            if ( v == null )
+            {
+                //log.debug("getDescendants vertex is null");
+                return 0;
+            }
+            LOG.debug( "hasChildren [{}]", v );
+            numChildren = graph.inDegreeOf( v );
+        }
+        catch ( java.lang.IllegalArgumentException e )
+        {
+            // vertex is leaf.
+        }
+        return numChildren;
+    }
+
+
+    /**
+     * Recursively traverse the hierarchical graph and return all of the ascendants of a given node.
+     *
+     * @param childName maps to vertex to determine parentage.
+     * @param graph     contains a reference to simple digraph {@code org.jgrapht.graph.SimpleDirectedGraph}.
+     * @return Set of names that are parents of given child.
+     */
+    static Set<String> getAscendants( String childName, SimpleDirectedGraph<String, Relationship> graph )
+    {
+        Map<String, String> vx = new HashMap<>();
+        // TreeSet will return in sorted order:
+        // create Set with case insensitive comparator:
+        Set<String> parents = new TreeSet<>( String.CASE_INSENSITIVE_ORDER );
+        vx.put( VERTEX, childName.toUpperCase() );
+        getAscendants( vx, graph, parents );
+        return parents;
+    }
+
+
+    /**
+     * Utility function recursively traverses a given digraph to build a set of all ascendant names.
+     *
+     * @param vertex     contains the position of the cursor for traversal of graph.
+     * @param graph      contains a reference to simple digraph {@code org.jgrapht.graph.SimpleDirectedGraph}.
+     * @param ascendants contains the result set of ascendant names.
+     * @return value contains the vertex of current position.
+     */
+    private static String getAscendants( Map<String, String> vertex, SimpleDirectedGraph<String, Relationship> graph,
+        Set<String> ascendants )
+    {
+        String v = vertex.get( VERTEX );
+        if ( v == null )
+        {
+            return null;
+        }
+        else if ( graph == null )
+        {
+            return null;
+        }
+        LOG.debug( "getAscendants [{}]", v);
+        Set<Relationship> edges;
+        try
+        {
+            edges = graph.outgoingEdgesOf( v );
+
+        }
+        catch ( java.lang.IllegalArgumentException iae )
+        {
+            // vertex is leaf.
+            return null;
+        }
+        for ( Relationship edge : edges )
+        {
+            vertex.put( VERTEX, edge.getParent() );
+            ascendants.add( edge.getParent() );
+            v = getAscendants( vertex, graph, ascendants );
+        }
+        return v;
+    }
+
+
+    /**
+     * Recursively traverse the hierarchical graph and return all of the descendants for a given node.
+     *
+     * @param parentName maps to vertex to determine parentage.
+     * @param graph      contains a reference to simple digraph {@code org.jgrapht.graph.SimpleDirectedGraph}.
+     * @return Set of names that are children of given parent.
+     */
+    static Set<String> getDescendants( String parentName, SimpleDirectedGraph<String, Relationship> graph )
+    {
+        Map<String, String> vx = new HashMap<>();
+        // TreeSet will return in sorted order:
+        // create Set with case insensitive comparator:
+        Set<String> children = new TreeSet<>( String.CASE_INSENSITIVE_ORDER );
+        vx.put( VERTEX, parentName.toUpperCase() );
+        getDescendants( vx, graph, children );
+        return children;
+    }
+
+
+    /**
+     * Recursively traverse the hierarchical graph and determine child node contains a given parent as one of its ascendants.
+     *
+     * @param childName maps to vertex to determine parentage.
+     * @param parentName maps to vertex to determine parentage.
+     * @param graph      contains a reference to simple digraph {@code org.jgrapht.graph.SimpleDirectedGraph}.
+     * @return Set of names that are children of given parent.
+     */
+    private static boolean isAscendant( String childName, String parentName,
+        SimpleDirectedGraph<String, Relationship> graph )
+    {
+        boolean isAscendant = false;
+        Set<String> ascendants = getAscendants( childName, graph );
+        if ( ascendants.contains( parentName ) )
+        {
+            isAscendant = true;
+        }
+        return isAscendant;
+    }
+
+
+    /**
+     * Recursively traverse the hierarchical graph and determine if parent node contains a given child as one of its descendants.
+     *
+     * @param childName maps to vertex to determine parentage.
+     * @param parentName maps to vertex to determine parentage.
+     * @param graph      contains a reference to simple digraph {@code org.jgrapht.graph.SimpleDirectedGraph}.
+     * @return Set of names that are children of given parent.
+     */
+    private static boolean isDescedant( String childName, String parentName,
+        SimpleDirectedGraph<String, Relationship> graph )
+    {
+        boolean isDescendant = false;
+        Set<String> descendants = getDescendants( parentName, graph );
+        if ( descendants.contains( childName ) )
+        {
+            isDescendant = true;
+        }
+        return isDescendant;
+    }
+
+
+    /**
+     * Utility function recursively traverses a given digraph to build a set of all descendants names.
+     *
+     * @param vertex      contains the position of the cursor for traversal of graph.
+     * @param graph       contains a reference to simple digraph {@code org.jgrapht.graph.SimpleDirectedGraph}.
+     * @param descendants contains the result set of names of all descendants of node.
+     * @return value contains the vertex of current position.
+     */
+    private static String getDescendants( Map<String, String> vertex, SimpleDirectedGraph<String, Relationship> graph,
+        Set<String> descendants )
+    {
+        String v = vertex.get( VERTEX );
+        if ( v == null )
+        {
+            //log.debug("getDescendants vertex is null");
+            return null;
+        }
+        else if ( graph == null )
+        {
+            //log.debug("getDescendants graph is null");
+            return null;
+        }
+        LOG.debug( "getDescendants [{}]", v);
+        Set<Relationship> edges;
+        try
+        {
+            edges = graph.incomingEdgesOf( v );
+        }
+        catch ( java.lang.IllegalArgumentException iae )
+        {
+            // vertex is leaf.
+            return null;
+        }
+        for ( Relationship edge : edges )
+        {
+            vertex.put( VERTEX, edge.getChild() );
+            descendants.add( edge.getChild() );
+            v = getDescendants( vertex, graph, descendants );
+        }
+        return v;
+    }
+
+
+    /**
+     * Utility function returns a set of all children (direct descendant) names.
+     *
+     * @param vertex contains the position of the cursor for traversal of graph.
+     * @param graph  contains a reference to simple digraph {@code org.jgrapht.graph.SimpleDirectedGraph}.
+     * @return value contains the vertex of current position.
+     */
+    static Set<String> getChildren( String vertex, SimpleDirectedGraph<String, Relationship> graph )
+    {
+        Set<String> descendants = new HashSet<>();
+        if ( graph == null )
+        {
+            //log.debug("getChildren graph is null");
+            return null;
+        }
+        if ( LOG.isDebugEnabled() )
+            LOG.debug( "getChildren [" + vertex + "]" );
+
+        Set<Relationship> edges;
+        try
+        {
+            edges = graph.incomingEdgesOf( vertex );
+        }
+        catch ( java.lang.IllegalArgumentException iae )
+        {
+            // vertex is leaf.
+            return null;
+        }
+        for ( Relationship edge : edges )
+        {
+            descendants.add( edge.getChild() );
+        }
+        return descendants;
+    }
+
+
+    /**
+     * Recursively traverse the hierarchical graph and return all of the ascendants of a given 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 graph       contains a reference to simple digraph {@code org.jgrapht.graph.SimpleDirectedGraph}.
+     * @return Set of names that are parents of given child.
+     */
+    static Set<String> getAscendants( String childName, String parentName, boolean isInclusive,
+        SimpleDirectedGraph<String, Relationship> graph )
+    {
+        Map<String, String> vx = new HashMap<>();
+        // TreeSet will return in sorted order:
+        // create Set with case insensitive comparator:
+        Set<String> parents = new TreeSet<>( String.CASE_INSENSITIVE_ORDER );
+
+        vx.put( VERTEX, childName.toUpperCase() );
+        getAscendants( vx, graph, parents, parentName, isInclusive );
+        return parents;
+    }
+
+
+    /**
+     * Private utility to recursively traverse the hierarchical graph and return all of the ascendants of a given child node.
+     *
+     * @param vertex      contains node name and acts as cursor for current location.
+     * @param graph       contains a reference to simple digraph {@code org.jgrapht.graph.SimpleDirectedGraph}.
+     * @param parents     contains the result set of parent nodes.
+     * @param stopName    contains the name of node where traversal ends.
+     * @param isInclusive if set to true will include the parentName in the result set. False will not return specified parentName.
+     * @return Set of names that are parents of given child.
+     */
+    private static String getAscendants( Map<String, String> vertex, SimpleDirectedGraph<String, Relationship> graph,
+        Set<String> parents, String stopName, boolean isInclusive )
+    {
+        String v = vertex.get( VERTEX );
+        if ( v == null )
+        {
+            //log.debug("getAscendants vertex is null");
+            return null;
+        }
+        else if ( graph == null )
+        {
+            //log.debug("getAscendants graph is null");
+            return null;
+        }
+        LOG.debug( "getAscendants [{}]", v);
+        Set<Relationship> edges;
+        try
+        {
+            edges = graph.outgoingEdgesOf( v );
+        }
+        catch ( java.lang.IllegalArgumentException iae )
+        {
+            // vertex is leaf.
+            return null;
+        }
+        for ( Relationship edge : edges )
+        {
+            if ( edge.getParent().equalsIgnoreCase( stopName ) )
+            {
+                if ( isInclusive )
+                {
+                    parents.add( edge.getParent() );
+                }
+                break;
+            }
+            else
+            {
+                vertex.put( VERTEX, edge.getParent() );
+                parents.add( edge.getParent() );
+                v = getAscendants( vertex, graph, parents, stopName, isInclusive );
+            }
+        }
+        return v;
+    }
+
+
+    /**
+     * Private utility to return the parents (direct ascendants) of a given child node.
+     *
+     * @param vertex contains node name and acts as cursor for current location.
+     * @param graph  contains a reference to simple digraph {@code org.jgrapht.graph.SimpleDirectedGraph}.
+     * @return Set of names that are parents of given child.
+     */
+    static Set<String> getParents( String vertex, SimpleDirectedGraph<String, Relationship> graph )
+    {
+        Set<String> parents = new HashSet<>();
+        if ( graph == null )
+        {
+            //log.debug("getParents graph is null");
+            return null;
+        }
+        LOG.debug( "getParents [{}]", vertex);
+        Set<Relationship> edges;
+        try
+        {
+            edges = graph.outgoingEdgesOf( vertex );
+        }
+        catch ( java.lang.IllegalArgumentException iae )
+        {
+            // vertex is leaf.
+            return null;
+        }
+        for ( Relationship edge : edges )
+        {
+            parents.add( edge.getParent() );
+        }
+        return parents;
+    }
+
+
+    /**
+     * This method will retrieve the list of all parent-child relationships for a given node.  If the node was not found in
+     * ldap this method will create a new node and store default data.
+     * The following ldap nodes are currently storing hierarchical data:
+     * <ol>
+     * <li>RBAC Role relations are stored in {@code cn=Hierarchies,ou=Roles,ou=RBAC} ldap node and cached as singleton in {@link RoleUtil}</li>
+     * <li>ARBAC Admin Role relations are stored in {@code cn=Hierarchies,ou=AdminRoles,ou=ARBAC} ldap node and cached as singleton in {@link AdminRoleUtil}</li>
+     * <li>User Organizational Unit relations are stored in {@code cn=Hierarchies,ou=OS-U,ou=ARBAC} node and cached as {@link org.apache.directory.fortress.core.rbac.UsoUtil}</li>
+     * <li>Permission Organizational Unit relations are stored in {@code cn=Hierarchies,ou=OS-P,ou=ARBAC} node and cached as {@link org.apache.directory.fortress.core.rbac.PsoUtil}</li>
+     * </ol>
+     *
+     * @param contextId maps to sub-tree in DIT, for example ou=contextId, dc=jts, dc = com.
+     * @return reference the the Hier result set retrieved from ldap.
+     */
+    static Hier loadHier( String contextId, List<Graphable> descendants )
+    {
+        Hier hier = new Hier();
+        if ( VUtil.isNotNullOrEmpty( descendants ) )
+        {
+            hier.setContextId( contextId );
+            for ( Graphable descendant : descendants )
+            {
+                Set<String> parents = descendant.getParents();
+                if ( VUtil.isNotNullOrEmpty( parents ) )
+                {
+                    for ( String parent : parents )
+                    {
+                        Relationship relationship = new Relationship();
+                        relationship.setChild( descendant.getName().toUpperCase() );
+                        relationship.setParent( parent.toUpperCase() );
+                        hier.setRelationship( relationship );
+                    }
+                }
+            }
+        }
+        return hier;
+    }
+
+
+    /**
+     * 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 graph contains a reference to simple digraph {@code org.jgrapht.graph.SimpleDirectedGraph}.
+     * @param relationship contains parent-child relationship targeted for addition.
+     * @param op   used to pass the ldap op {@link Hier.Op#ADD}, {@link 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( SimpleDirectedGraph<String, Relationship> graph, Relationship relationship, Hier.Op op )
+        throws SecurityException
+    {
+        if ( op == Hier.Op.ADD )
+            HierUtil.addEdge( graph, relationship );
+        else if ( op == Hier.Op.REM )
+            HierUtil.removeEdge( graph, relationship );
+        else
+            throw new SecurityException( GlobalErrIds.HIER_CANNOT_PERFORM, CLS_NM
+                + "updateHier Cannot perform hierarchical operation" );
+    }
+
+
+    /**
+     * Method instantiates a new digraph, {@code org.jgrapht.graph.SimpleDirectedGraph}, using data passed in via
+     * {@link Hier} entity.
+     *
+     * @param hier contains the source data for digraph.
+     * @return reference to {@code org.jgrapht.graph.SimpleDirectedGraph}.
+     */
+    static SimpleDirectedGraph<String, Relationship> buildGraph( Hier hier )
+    {
+        SimpleDirectedGraph<String, Relationship> graph;
+        LOG.debug( "buildGraph is initializing" );
+        if ( hier == null )
+        {
+            String error = "buildGraph detected null hier=";
+            LOG.error( error );
+            return null;
+        }
+        graph = toGraph( hier );
+        LOG.debug( "buildGraph success to toGraph" );
+        LOG.debug( "buildGraph is success" );
+        return graph;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/687ee1ad/src/main/java/org/apache/directory/fortress/core/rbac/Manageable.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/rbac/Manageable.java b/src/main/java/org/apache/directory/fortress/core/rbac/Manageable.java
new file mode 100755
index 0000000..196c2e6
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/rbac/Manageable.java
@@ -0,0 +1,156 @@
+/*
+ *   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.SecurityException;
+import org.apache.directory.fortress.core.ValidationException;
+import org.apache.directory.fortress.core.util.attr.VUtil;
+
+/**
+ * Abstract class allows outside clients to manage security and multi-tenant concerns within the Fortress runtime.
+ * The {@link #setAdmin(org.apache.directory.fortress.core.rbac.Session)} method allows A/RBAC sessions to be loaded and allows authorization
+ * to be performed on behalf of the user who is contained within the Session object itself.
+ * The ARBAC permissions will be checked each time outside client makes calls into Fortress API.
+ * This interface also allows Fortress clients to operate in a multi-tenant fashion using {@link #setContextId(String)}.
+ * <p/>
+ * Implementers of this abstract class will NOT be thread safe because of instance variables that may be set.
+ *
+ * @author Shawn McKinney
+ */
+public abstract class Manageable implements org.apache.directory.fortress.core.Manageable
+{
+    // These instance variables are the reason why children of this abstract class will not be thread safe:
+    protected Session adminSess;
+    protected String contextId;
+
+    /**
+     * Use this method to load an administrative user's ARBAC Session object into Manager object will enable authorization to
+     * be performed on behalf of admin user.  Setting Session into this object will enforce ARBAC controls and render this class'
+     * implementer thread unsafe.
+     *
+     * @param session contains a valid Fortress A/RBAC Session object.
+     */
+    public final void setAdmin(Session session)
+    {
+        this.adminSess = session;
+    }
+
+    /**
+     * Use this method to set the tenant id onto function call into Fortress which allows segregation of data by customer.
+     * The contextId is used for multi-tenancy to isolate data sets within a particular sub-tree within DIT.
+     * Setting contextId into this object will render this class' implementer thread unsafe.
+     *
+     * @param contextId maps to sub-tree in DIT, for example ou=contextId, dc=jts, dc = com.
+     */
+    public final void setContextId(String contextId)
+    {
+        this.contextId = contextId;
+    }
+
+    /**
+     * Set A/RBAC session on entity and perform authorization on behalf of the caller if the {@link #adminSess} is set.
+     *
+     * @param className contains the class name.
+     * @param opName contains operation name.
+     * @param entity contains {@link org.apache.directory.fortress.core.rbac.FortEntity} instance.
+     * @throws org.apache.directory.fortress.core.SecurityException
+     *          in the event of data validation or system error.
+     */
+    protected final void setEntitySession(String className, String opName, FortEntity entity) throws SecurityException
+    {
+        entity.setContextId(this.contextId);
+        if (this.adminSess != null)
+        {
+            Permission perm = new Permission(className, opName);
+            perm.setContextId(this.contextId);
+            AdminUtil.setEntitySession( this.adminSess, perm, entity, this.contextId );
+        }
+    }
+
+    /**
+     * Every Fortress Manager API (e.g. addUser, updateUser, addRole, ...) will perform authorization on behalf of the caller IFF the {@link AuditMgrImpl#adminSess} has been set before invocation.
+     *
+     * @param className contains the class name.
+     * @param opName contains operation name.
+     * @throws org.apache.directory.fortress.core.SecurityException
+     *          in the event of data validation or system error.
+     */
+    protected final void checkAccess(String className, String opName) throws SecurityException
+    {
+        if (this.adminSess != null)
+        {
+            Permission perm = new Permission(className, opName);
+            perm.setContextId(this.contextId);
+            AdminUtil.checkAccess(this.adminSess, perm, this.contextId);
+        }
+    }
+
+    /**
+     * Method is called by Manager APIs to load contextual information on {@link FortEntity}.
+     * </p>
+     * The information is used to
+     * <ol>
+     * <li>Load the administrative User's {@link Session} object into entity.  This is used for checking to ensure administrator has privilege to perform administrative operation.</li>
+     * <li>Load the target operation's permission into the audit context.  This is used for Fortress audit log stored in OpenLDAP</li>
+     * </ol>
+     *
+     * @param className contains the class name.
+     * @param opName contains operation name.
+     * @param entity  used to pass contextual information through Fortress layers for administrative security checks and audit.
+     * @throws org.apache.directory.fortress.core.SecurityException
+     *          in the event of data validation or system error.
+     */
+    protected final void setAdminData(String className, String opName, FortEntity entity)
+    {
+        if (this.adminSess != null)
+        {
+            Permission perm = new Permission(className, opName);
+            entity.setAdminSession(this.adminSess);
+            entity.setModCode(AdminUtil.getObjName(perm.getObjName()) + "." + perm.getOpName());
+        }
+        entity.setContextId(this.contextId);
+    }
+
+    /**
+     * Method will throw exception if entity reference is null, otherwise will set the contextId of the tenant onto the supplied entity reference.
+     * @param className contains the class name of caller.
+     * @param opName contains operation name of caller.
+     * @param entity  used here to pass the tenant id into the Fortress DAO layer..
+     * @param errorCode contains the error id to use if null.
+     * @throws org.apache.directory.fortress.core.ValidationException in the event object is null.
+     */
+    protected final void assertContext(String className, String opName, FortEntity entity, int errorCode)
+        throws ValidationException
+    {
+        VUtil.assertNotNull(entity, errorCode, getFullMethodName(className, opName));
+        entity.setContextId(this.contextId);
+    }
+
+    /**
+     * This method is used to generate log statements and returns the concatenation of class name to the operation name.
+     * @param className of the caller
+     * @param opName of the caller
+     * @return className + '.' + opName
+     */
+    protected final String getFullMethodName(String className, String opName)
+    {
+        return className + "." + opName;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/687ee1ad/src/main/java/org/apache/directory/fortress/core/rbac/Mod.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/rbac/Mod.java b/src/main/java/org/apache/directory/fortress/core/rbac/Mod.java
new file mode 100755
index 0000000..3b52bd3
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/rbac/Mod.java
@@ -0,0 +1,326 @@
+/*
+ *   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.io.Serializable;
+import java.util.List;
+
+
+/**
+ * This entity class contains OpenLDAP slapd access log records that correspond to modifications made to the directory.
+ * <p/>
+ * <p/>
+ * The auditModify Structural object class is used to store Fortress update and delete events that can later be queried via ldap API.<br />
+ * The deletions can be recorded in this manner and associated with Fortress context because deletions will perform a modification first
+ * if audit is enabled.
+ * <p/>
+ * <code>The Modify operation contains a description  of  modifications  in  the</code><br />
+ * <code>reqMod  attribute,  which  was  already  described  above  in  the  Add</code><br />
+ * <code>operation. It may optionally  contain  the  previous  contents  of  any</code><br />
+ * <code>modified  attributes  in the reqOld attribute, using the same format as</code><br />
+ * <code>described above for the Delete operation.  The reqOld attribute is only</code><br />
+ * <code>populated  if  the  entry  being modified matches the configured logold</code><br />
+ * <code>filter.</code><br />
+ * <ul>
+ * <li>  ------------------------------------------
+ * <li> <code>objectclass (  1.3.6.1.4.1.4203.666.11.5.2.9</code>
+ * <li> <code>NAME 'auditModify'</code>
+ * <li> <code>DESC 'Modify operation'</code>
+ * <li> <code>SUP auditWriteObject STRUCTURAL</code>
+ * <li> <code>MAY reqOld MUST reqMod )</code>
+ * <li> ------------------------------------------
+ * </ul>
+ * <p/>
+ * Note this class uses descriptions pulled from man pages on slapd access log.
+ * <p/>
+
+ *
+ * @author Shawn McKinney
+ */
+@XmlRootElement(name = "fortMod")
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "mod", propOrder = {
+    "reqSession",
+    "objectClass",
+    "reqAuthzID",
+    "reqDN",
+    "reqResult",
+    "reqStart",
+    "reqEnd",
+    "reqMod",
+    "reqType",
+    "sequenceId"
+})
+public class Mod extends FortEntity implements Serializable
+{
+    private String reqSession;
+    private String objectClass;
+    private String reqAuthzID;
+    private String reqDN;
+    private String reqResult;
+    private String reqStart;
+    private String reqEnd;
+    private String reqType;
+    @XmlElement(nillable = true)
+    private List<String> reqMod;
+    private long sequenceId;
+
+    /**
+     * The reqMod attribute carries all of the attributes of the original entry being added.
+     * (Or in the case of a Modify operation, all of the modifications being performed.)
+     * The values are formatted as attribute:<+|-|=|#> [ value] Where '+' indicates an Add of a value,
+     * '-' for Delete, '=' for Replace, and '#' for Increment. In an Add operation, all of  the
+     * reqMod  values will have the '+' designator.
+     *
+     * @return collection of Strings that map to 'reqMod' attribute on 'auditModify' object class.
+     */
+    public List<String> getReqMod()
+    {
+        return reqMod;
+    }
+
+    /**
+     * The reqMod attribute carries all of the attributes of the original entry being added.
+     * (Or in the case of a Modify operation, all of the modifications being performed.)
+     * The values are formatted as attribute:<+|-|=|#> [ value] Where '+' indicates an Add of a value,
+     * '-' for Delete, '=' for Replace, and '#' for Increment. In an Add operation, all of  the
+     * reqMod  values will have the '+' designator.
+     *
+     * @param reqMod contains collection of Strings that map to 'reqMod' attribute on 'auditModify' object class.
+     */
+    public void setReqMod(List<String> reqMod)
+    {
+        this.reqMod = reqMod;
+    }
+
+    /**
+     * reqEnd provide the end time of the operation. It uses generalizedTime syntax.
+     *
+     * @return value that maps to 'reqEnd' attribute on 'auditModify' object class.
+     */
+    public String getReqEnd()
+    {
+        return reqEnd;
+    }
+
+    /**
+     * reqEnd provide the end time of the operation. It uses generalizedTime syntax.
+     *
+     * @param reqEnd value that maps to same name on 'auditModify' object class.
+     */
+    public void setReqEnd(String reqEnd)
+    {
+        this.reqEnd = reqEnd;
+    }
+
+    /**
+     * The reqSession attribute is an implementation-specific identifier  that
+     * is  common to all the operations associated with the same LDAP session.
+     * Currently this is slapd's internal connection ID, stored in decimal.
+     *
+     * @return value that maps to 'reqSession' attribute on 'auditModify' object class.
+     */
+    public String getReqSession()
+    {
+        return reqSession;
+    }
+
+    /**
+     * The reqSession attribute is an implementation-specific identifier  that
+     * is  common to all the operations associated with the same LDAP session.
+     * Currently this is slapd's internal connection ID, stored in decimal.
+     *
+     * @param reqSession maps to same name on 'auditModify' object class.
+     */
+    public void setReqSession(String reqSession)
+    {
+        this.reqSession = reqSession;
+    }
+
+    /**
+     * Get the object class name of the audit record.  For this entity, this value will always be 'auditModify'.
+     *
+     * @return value that maps to 'objectClass' attribute on 'auditModify' obejct class.
+     */
+    public String getObjectClass()
+    {
+        return objectClass;
+    }
+
+    /**
+     * Set the object class name of the audit record.  For this entity, this value will always be 'auditModify'.
+     *
+     * @param objectClass value that maps to same name on 'auditModify' obejct class.
+     */
+    public void setObjectClass(String objectClass)
+    {
+        this.objectClass = objectClass;
+    }
+
+    /**
+     * The  reqAuthzID  attribute  is  the  distinguishedName of the user that
+     * performed the operation.  This will usually be the  same  name  as  was
+     * established  at  the  start of a session by a Bind request (if any) but
+     * may be altered in various circumstances.
+     * For Fortress bind operations this will map to {@link User#userId}
+     *
+     * @return value that maps to 'reqAuthzID' on 'auditModify' object class.
+     */
+    public String getReqAuthzID()
+    {
+        return reqAuthzID;
+    }
+
+    /**
+     * The  reqAuthzID  attribute  is  the  distinguishedName of the user that
+     * performed the operation.  This will usually be the  same  name  as  was
+     * established  at  the  start of a session by a Bind request (if any) but
+     * may be altered in various circumstances.
+     * For Fortress bind operations this will map to {@link User#userId}
+     *
+     */
+    public void setReqAuthzID(String reqAuthzID)
+    {
+        this.reqAuthzID = reqAuthzID;
+    }
+
+    /**
+     * The reqDN attribute is the  distinguishedName  of  the  target  of  the
+     * operation.  E.g.,for a Bind request, this is the Bind DN. For an Add
+     * request, this is the DN of the entry being added. For a Search request,
+     * this is the base DN of the search.
+     *
+     * @return value that map to 'reqDN' attribute on 'auditModify' object class.
+     */
+    public String getReqDN()
+    {
+        return reqDN;
+    }
+
+    /**
+     * The reqDN attribute is the  distinguishedName  of  the  target  of  the
+     * operation. E.g., for a Bind request, this is the Bind DN. For an Add
+     * request, this is the DN of the entry being added. For a Search request,
+     * this is the base DN of the search.
+     *
+     * @param reqDN maps to 'reqDN' attribute on 'auditModify' object class.
+     */
+    public void setReqDN(String reqDN)
+    {
+        this.reqDN = reqDN;
+    }
+
+    /**
+     * The reqResult attribute is the numeric LDAP result code of the
+     * operation, indicating either success or a particular LDAP  error  code.
+     * An  error code may be accompanied by a text error message which will be
+     * recorded in the reqMessage attribute.
+     *
+     * @return value that maps to 'reqResult' attribute on 'auditModify' object class.
+     */
+    public String getReqResult()
+    {
+        return reqResult;
+    }
+
+    /**
+     * The reqResult attribute is the numeric LDAP result code of the
+     * operation, indicating either success or a particular LDAP  error  code.
+     * An  error code may be accompanied by a text error message which will be
+     * recorded in the reqMessage attribute.
+     *
+     * @param reqResult maps to same name on 'auditModify' object class.
+     */
+    public void setReqResult(String reqResult)
+    {
+        this.reqResult = reqResult;
+    }
+
+    /**
+     * reqStart provide the start of the operation, They use generalizedTime syntax.
+     * The reqStart attribute is also used as the RDN for each log entry.
+     *
+     * @return value that maps to 'reqStart' attribute on 'auditModify' object class.
+     */
+    public String getReqStart()
+    {
+        return reqStart;
+    }
+
+    /**
+     * reqStart provide the start of the operation, They use generalizedTime syntax.
+     * The reqStart attribute is also used as the RDN for each log entry.
+     *
+     * @param reqStart maps to same name on 'auditModify' object class.
+     */
+    public void setReqStart(String reqStart)
+    {
+        this.reqStart = reqStart;
+    }
+
+    /**
+     * The reqType attribute is a simple string containing the type of
+     * operation being logged, e.g.  add, delete, search,  etc.  For  extended
+     * operations, the  type also includes the OID of the extended operation,
+     * e.g. extended(1.1.1.1)
+     *
+     * @return value that maps to 'reqType' attribute on 'auditModify' object class.
+     */
+    public String getReqType()
+    {
+        return reqType;
+    }
+
+    /**
+     * The reqType attribute is a simple string containing the type of
+     * operation being logged, e.g. add, delete, search, etc. For extended
+     * operations,  the  type also includes the OID of the extended operation,
+     * e.g.extended(1.1.1.1)
+     *
+     * @param reqType maps to same name on 'auditModify' object class.
+     */
+    public void setReqType(String reqType)
+    {
+        this.reqType = reqType;
+    }
+
+    /**
+     * Sequence id is used internal to Fortress.
+     * @return long value contains sequence id.
+     */
+    public long getSequenceId()
+    {
+        return sequenceId;
+    }
+
+    /**
+     * Sequence id is used internal to Fortress
+     * @param sequenceId contains sequence to use.
+     */
+    public void setSequenceId(long sequenceId)
+    {
+        this.sequenceId = sequenceId;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/687ee1ad/src/main/java/org/apache/directory/fortress/core/rbac/OrgUnit.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/rbac/OrgUnit.java b/src/main/java/org/apache/directory/fortress/core/rbac/OrgUnit.java
new file mode 100755
index 0000000..ddb20bd
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/rbac/OrgUnit.java
@@ -0,0 +1,420 @@
+/*
+ *   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.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+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 org.apache.directory.fortress.core.rbac.dao.AdminRoleDAO;
+import org.apache.directory.fortress.core.rbac.dao.OrgUnitDAO;
+
+
+/**
+ * All entities ({@link AdminRole}, {@link OrgUnit},
+ * {@link org.apache.directory.fortress.core.rbac.SDSet} etc...) are used to carry data between three Fortress
+ * layers.starting with the (1) Manager layer down thru middle (2) Process layer and it's processing rules into
+ * (3) DAO layer where persistence with the OpenLDAP server occurs.
+ * <h4>Fortress Processing Layers</h4>
+ * <ol>
+ * <li>Manager layer:  {@link DelAdminMgrImpl}, {@link DelAccessMgrImpl}, {@link DelReviewMgrImpl},...</li>
+ * <li>Process layer:  {@link AdminRoleP}, {@link OrgUnitP},...</li>
+ * <li>DAO layer: {@link AdminRoleDAO}, {@link OrgUnitDAO},...</li>
+ * </ol>
+ * Fortress clients first instantiate and populate a data entity before invoking any of the Manager APIs.  The caller must
+ * provide enough information to uniquely identity the entity target within ldap.<br />
+ * For example, this entity requires {@link #name} and {@link #type} set before passing into {@link DelAdminMgrImpl} or  {@link DelReviewMgrImpl} APIs.
+ * Create methods usually require more attributes (than Read) due to constraints enforced between entities.
+ * <p/>
+ * This entity implements both User and Permission OU pool functionality that defines org membership of entities for ARBAC02 style admin checks..
+ * <br />The unique key to locate an OrgUnit entity (which is subsequently assigned both to Users and Permissions) is 'OrgUnit.name' and 'OrgUnit.Type'.<br />
+ * <p/>
+ * An OrgUnit name may contain alphanumeric and simple symbols that are safe text (.,:;-_).  Any non-safe text will be
+ * encoded before persistence.  Valid names include:
+ * <ol>
+ * <li>123</li>
+ * <li>OneTwoThree</li>
+ * <li>One-Two-Three</li>
+ * <li>One_Two_Three</li>
+ * <li>One:2:3</li>
+ * <li>1:2:3</li>
+ * <li>1.2.3</li>
+ * <li>1,2,3</li>
+ * <li>1_2_3</li>
+ * <li>etc...</li>
+ * </ol>
+ * <p/>
+ * There is a Many-to-One relationship between a User and OrgUnit.
+ * <h3>{@link org.apache.directory.fortress.core.rbac.User}*<->1 {@link OrgUnit}</h3>
+ * <p/>
+ * There is a Many-to-One relationship between a {@link PermObj} object and {@link OrgUnit}.
+ * <h3>{@link PermObj}*<->1 {@link OrgUnit}</h3>
+ * <p/>
+ * Example to create new ARBAC User OrgUnit:
+ * <p/>
+ * <code>OrgUnit myUserOU = new OrgUnit("MyUserOrgName", OrgUnit.Type.USER);</code><br />
+ * <code>myUserOU.setDescription("This is a test User OrgUnit");</code><br />
+ * <code>DelAdminMgr delAdminMgr = DelAdminMgrFactory.createInstance();</code><br />
+ * <code>delAdminMgr.add(myUserOU);</code><br />
+ * <p/>
+ * This will create a User OrgUnit that can be used as a target for User OU and AdminRole OS-U assignments.
+ * <p/>
+ * Example to create new ARBAC Perm OrgUnit:
+ * <p/>
+ * <code>OrgUnit myPermOU = new OrgUnit("MyPermOrgName", OrgUnit.Type.PERM);</code><br />
+ * <code>myPermOU.setDescription("This is a test Perm OrgUnit");</code><br />
+ * <code>DelAdminMgr delAdminMgr = DelAdminMgrFactory.createInstance();</code><br />
+ * <code>delAdminMgr.add(myPermOU);</code><br />
+ * <p/>
+ * This will create a Perm OrgUnit that can be used as a target for Perm OU and AdminRole OS-P assignments.
+ * <p/>
+ * <h4>OrgUnit Schema</h4>
+ * The Fortress OrgUnit entity is a composite of the following other Fortress structural and aux object classes:
+ * <p/>
+ * 1. organizationalUnit Structural Object Class is used to store basic attributes like ou and description.
+ * <pre>
+ * ------------------------------------------
+ * objectclass ( 2.5.6.5 NAME 'organizationalUnit'
+ *  DESC 'RFC2256: an organizational unit'
+ *  SUP top STRUCTURAL
+ *  MUST ou
+ *  MAY (
+ *      userPassword $ searchGuide $ seeAlso $ businessCategory $
+ *      x121Address $ registeredAddress $ destinationIndicator $
+ *      preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
+ *      telephoneNumber $ internationaliSDNNumber $
+ *      facsimileTelephoneNumber $ street $ postOfficeBox $ postalCode $
+ *      postalAddress $ physicalDeliveryOfficeName $ st $ l $ description
+ *  )
+ * )
+ * ------------------------------------------
+ * </pre>
+ * <p/>
+ * 2. ftOrgUnit Structural objectclass is used to store the OrgUnit internal id.
+ * <pre>
+ * ------------------------------------------
+ * Fortress Organizational Structural Object Class
+ * objectclass	( 1.3.6.1.4.1.38088.2.6
+ *  NAME 'ftOrgUnit'
+ *  DESC 'Fortress OrgUnit Structural Object Class'
+ *  SUP organizationalunit
+ *  STRUCTURAL
+ *  MUST (
+ *      ftId
+ *  )
+ *  MAY (
+ *      ftParents
+ *  )
+ * )
+ * ------------------------------------------
+ * </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 = "fortOrgUnit")
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "orgUnit", propOrder =
+    {
+        "children",
+        "description",
+        "id",
+        "name",
+        "parents",
+        "type"
+})
+public class OrgUnit extends FortEntity
+    implements Graphable, java.io.Serializable
+{
+    /**
+     * Maps to the location for a particular OrgUnit entity to either the User, {@code ou=OS-U}, or Permission, {@code ou=OS-P}, tree in ldap.
+     *
+     */
+    public Type type;
+    private String name;
+    private String id;
+    private String description;
+    @XmlElement(nillable = true)
+    private Set<String> parents;
+    @XmlElement(nillable = true)
+    private Set<String> children;
+
+
+    /**
+     * Default constructor is used by internal Fortress classes.
+     */
+    public OrgUnit()
+    {
+    }
+
+
+    /**
+     * Construct a OrgUnit entity with a given ou name.
+     *
+     * @param ou maps to same name on on 'organizationalUnit' object class.
+     */
+    public OrgUnit( String ou )
+    {
+        this.name = ou;
+    }
+
+
+    /**
+     * Construct a OrgUnit entity with a given ou name and specified type - 'USER' or 'PERM'.
+     *
+     * @param ou   maps to same name on on 'organizationalUnit' object class.
+     * @param type is used to determine which OrgUnit tree is being targeted - 'USER' or 'PERM'.
+     */
+    public OrgUnit( String ou, Type type )
+    {
+        this.name = ou;
+        this.type = type;
+    }
+
+
+    /**
+     * Get the name required attribute of the OrgUnit object
+     *
+     * @return attribute maps to 'ou' attribute on 'organizationalUnit' object class.
+     */
+    public String getName()
+    {
+        return name;
+    }
+
+
+    /**
+     * Sets the required name attribute on the OrgUnit object
+     *
+     */
+    public void setName( String name )
+    {
+        this.name = name;
+    }
+
+
+    /**
+     * Return the internal id that is associated with OrgUnit.  This attribute is generated automatically
+     * by Fortress when new OrgUnit is added to directory and is not known or changeable by external client.
+     *
+     * @return attribute maps to 'ftId' in 'ftOrgUnit' object class.
+     */
+    public String getId()
+    {
+        return id;
+    }
+
+
+    /**
+     * Set the internal Id that is associated with OrgUnit.  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 'ftOrgUnit' object class.
+     */
+    public void setId( String id )
+    {
+        this.id = id;
+    }
+
+
+    /**
+     * Generate an internal Id that is associated with OrgUnit.  This method is used by DAO class and
+     * is not available to outside classes.   The generated attribute maps to 'ftId' in 'ftOrgUnit' 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();
+    }
+
+    /**
+     * The OrgUnit 'Type' attribute is required and used to specify which OrgUnit tree a particular entity is in reference to.
+     */
+    @XmlType(name = "type")
+    @XmlEnum
+    public enum Type
+    {
+        /**
+         * Type {@link org.apache.directory.fortress.core.rbac.User} nodes reside in User OU pool.
+         */
+        USER,
+        /**
+         * Type {@link Permission} nodes reside in Perm OU pool.
+         */
+        PERM
+    }
+
+
+    /**
+     * Return the type of OrgUnit for this entity.  This field is required for this entity.
+     *
+     * @return Type contains 'PERM' or 'USER'.
+     */
+    public Type getType()
+    {
+        return type;
+    }
+
+
+    /**
+     * Get the type of OrgUnit for this entity.  This field is required for this entity.
+     *
+     * @param type contains 'PERM' or 'USER'.
+     */
+    public void setType( Type type )
+    {
+        this.type = type;
+    }
+
+
+    /**
+     * Returns optional description that is associated with OrgUnit.  This attribute is validated but not constrained by Fortress.
+     *
+     * @return value that is mapped to 'description' in 'organizationalUnit' object class.
+     */
+    public String getDescription()
+    {
+        return description;
+    }
+
+
+    /**
+     * Sets the optional description that is associated with OrgUnit.  This attribute is validated but not constrained by Fortress.
+     *
+     * @param description that is mapped to same name in 'organizationalUnit' object class.
+     */
+    public void setDescription( String description )
+    {
+        this.description = description;
+    }
+
+
+    /**
+     * Get the names of orgUnits that are parents (direct ascendants) of this orgUnit.
+     * @return Set of parent orgUnit names assigned to this orgUnit.
+     */
+    public Set<String> getParents()
+    {
+        return parents;
+    }
+
+
+    /**
+     * Set the names of orgUnit names that are parents (direct ascendants) of this orgUnit.
+     * @param parents contains the Set of parent orgUnit names assigned to this orgUnit.
+     */
+    public void setParents( Set<String> parents )
+    {
+        this.parents = parents;
+    }
+
+
+    /**
+     * Set the occupant attribute with the contents of the User dn.
+     * @param parent maps to 'ftParents' attribute on 'ftRls' object class.
+     */
+    public void setParent( String parent )
+    {
+        if ( this.parents == null )
+        {
+            this.parents = new HashSet<>();
+        }
+        this.parents.add( parent );
+    }
+
+
+    /**
+     * Set the occupant attribute with the contents of the User dn.
+     * @param parent maps to 'ftParents' attribute on 'ftRls' object class.
+     */
+    public void delParent( String parent )
+    {
+        if ( this.parents != null )
+        {
+            this.parents.remove( parent );
+        }
+    }
+
+
+    /**
+     * Return the Set of child orgUnit names (direct descendants) of this orgUnit.
+     * @return Set of child orgUnit names assigned to this orgUnit.
+     */
+    public Set<String> getChildren()
+    {
+        return children;
+    }
+
+
+    /**
+     * Set the Set of child orgUnit names (direct descendants) of this orgUnit
+     * @param children contains the Set of child orgUnit names assigned to this orgUnit.
+     */
+    public void setChildren( Set<String> children )
+    {
+        this.children = children;
+    }
+
+
+    /**
+     * @param thatObj
+     * @return boolean value of 'true if objects match
+     */
+    public boolean equals( Object thatObj )
+    {
+        if ( this == thatObj )
+            return true;
+        if ( this.getName() == null )
+            return false;
+        if ( !( thatObj instanceof OrgUnit ) )
+            return false;
+        OrgUnit thatOrg = ( OrgUnit ) thatObj;
+        if ( thatOrg.getName() == null )
+            return false;
+        return thatOrg.getName().equalsIgnoreCase( this.getName() );
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/687ee1ad/src/main/java/org/apache/directory/fortress/core/rbac/OrgUnitAnt.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/rbac/OrgUnitAnt.java b/src/main/java/org/apache/directory/fortress/core/rbac/OrgUnitAnt.java
new file mode 100755
index 0000000..58ff551
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/rbac/OrgUnitAnt.java
@@ -0,0 +1,61 @@
+/*
+ *   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;
+
+
+/**
+ * Entity is used by custom Apache Ant task for special handling of collections.  This is necessary because the
+ * Ant parser cannot deal with complex data attribute types.  The class extends a base entity.
+ *
+ * @author Shawn McKinney
+ */
+public class OrgUnitAnt extends OrgUnit
+    implements java.io.Serializable
+{
+    private String typeName;
+    /**
+     * Return the type of OU in string format.
+     *
+     * @return String that represents static or dynamic relations.
+     */
+    public String getTypeName()
+    {
+        return typeName;
+    }
+
+    /**
+     * Method accepts a String variable that maps to its parent's set type.
+     *
+     * @param typeName String value represents perm or user ou data sets.
+     */
+    public void setTypeName(String typeName)
+    {
+        this.typeName = typeName;
+        if (typeName != null && typeName.equalsIgnoreCase("PERM"))
+        {
+            setType(OrgUnit.Type.PERM);
+        }
+        else
+        {
+            setType(OrgUnit.Type.USER);
+        }
+    }
+}
+