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);
+ }
+ }
+}
+