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:53 UTC
[34/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/ldap/container/OrganizationalUnitDAO.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/ldap/container/OrganizationalUnitDAO.java b/src/main/java/org/apache/directory/fortress/core/ldap/container/OrganizationalUnitDAO.java
new file mode 100755
index 0000000..f2e05cd
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/ldap/container/OrganizationalUnitDAO.java
@@ -0,0 +1,162 @@
+/*
+ * 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.ldap.container;
+
+
+import org.apache.directory.api.ldap.model.cursor.CursorException;
+import org.apache.directory.api.ldap.model.entry.DefaultEntry;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.fortress.core.CreateException;
+import org.apache.directory.fortress.core.RemoveException;
+import org.apache.directory.ldap.client.api.LdapConnection;
+import org.apache.directory.fortress.core.ldap.ApacheDsDataProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.directory.fortress.core.GlobalErrIds;
+import org.apache.directory.fortress.core.GlobalIds;
+import org.apache.directory.fortress.core.util.attr.VUtil;
+
+
+/**
+ * This class provides data access for the standard ldap object class Organizational Unit. This
+ * entity is used to provide containers in DIT for organization of related nodes..
+ * A container node is used to group other related nodes, i.e. 'ou=People' or 'ou'Roles'.
+ * <br />The organizational unit object class is 'organizationalUnit' <br />
+ * <p/>
+ * The OrganizationalUnitDAO maintains the following structural object class:
+ * <p/>
+ * organizationalUnit Structural Object Class is used to store basic attributes like ou and description.
+ * <ul>
+ * <li> ------------------------------------------
+ * <li> <code>objectclass ( 2.5.6.5 NAME 'organizationalUnit'</code>
+ * <li> <code>DESC 'RFC2256: an organizational unit'</code>
+ * <li> <code>SUP top STRUCTURAL</code>
+ * <li> <code>MUST ou</code>
+ * <li> <code>MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $</code>
+ * <li> <code>x121Address $ registeredAddress $ destinationIndicator $</code>
+ * <li> <code>preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $</code>
+ * <li> <code>telephoneNumber $ internationaliSDNNumber $</code>
+ * <li> <code>facsimileTelephoneNumber $ street $ postOfficeBox $ postalCode $</code>
+ * <li> <code>postalAddress $ physicalDeliveryOfficeName $ st $ l $ description ) )</code>
+ * <li> ------------------------------------------
+ * </ul>
+ * <p/>
+ * This class is thread safe.
+ *
+ * @author Shawn McKinney
+ */
+final class OrganizationalUnitDAO extends ApacheDsDataProvider
+{
+ private static final String CLS_NM = OrganizationalUnitDAO.class.getName();
+ private static final Logger LOG = LoggerFactory.getLogger( CLS_NM );
+ private static final String ORGUNIT_CLASS = "organizationalunit";
+ private static final String[] ORGUNIT_OBJ_CLASS =
+ {
+ ORGUNIT_CLASS
+ };
+
+
+ /**
+ * Package private default constructor.
+ */
+ OrganizationalUnitDAO()
+ {
+ }
+
+
+ private String getSdRoot( String contextId )
+ {
+ return getRootDn( contextId, GlobalIds.SUFFIX );
+ }
+
+
+ /**
+ * @param oe
+ * @throws org.apache.directory.fortress.core.CreateException
+ */
+ final void create( OrganizationalUnit oe )
+ throws CreateException
+ {
+ LdapConnection ld = null;
+ String nodeDn = GlobalIds.OU + "=" + oe.getName() + ",";
+ if ( VUtil.isNotNullOrEmpty( oe.getParent() ) )
+ nodeDn += GlobalIds.OU + "=" + oe.getParent() + ",";
+ nodeDn += getRootDn( oe.getContextId() );
+ try
+ {
+ LOG.info( "create container dn [" + nodeDn + "]" );
+ Entry myEntry = new DefaultEntry( nodeDn );
+ myEntry.add( GlobalIds.OBJECT_CLASS, ORGUNIT_OBJ_CLASS );
+ myEntry.add( GlobalIds.OU, oe.getName() );
+ myEntry.add( GlobalIds.DESC, oe.getDescription() );
+ ld = getAdminConnection();
+ add( ld, myEntry );
+ }
+ catch ( LdapException e )
+ {
+ String error = "create container node dn [" + nodeDn + "] caught LDAPException="
+ + e.getMessage();
+ throw new CreateException( GlobalErrIds.CNTR_CREATE_FAILED, error, e );
+ }
+ finally
+ {
+ closeAdminConnection( ld );
+ }
+ }
+
+
+ /**
+ * @param oe
+ * @throws org.apache.directory.fortress.core.RemoveException
+ */
+ final void remove( OrganizationalUnit oe )
+ throws RemoveException
+ {
+ LdapConnection ld = null;
+ String nodeDn = GlobalIds.OU + "=" + oe.getName() + ",";
+ if ( VUtil.isNotNullOrEmpty( oe.getParent() ) )
+ nodeDn += GlobalIds.OU + "=" + oe.getParent() + ",";
+ nodeDn += getRootDn( oe.getContextId(), GlobalIds.SUFFIX );
+
+ LOG.info( "remove container dn [" + nodeDn + "]" );
+ try
+ {
+ ld = getAdminConnection();
+ deleteRecursive( ld, nodeDn );
+ }
+ catch ( CursorException e )
+ {
+ String error = "remove container node dn [" + nodeDn + "] caught CursorException="
+ + e.getMessage();
+ throw new RemoveException( GlobalErrIds.CNTR_DELETE_FAILED, error, e );
+ }
+ catch ( LdapException e )
+ {
+ String error = "remove container node dn [" + nodeDn + "] caught LDAPException="
+ + e.getMessage();
+ throw new RemoveException( GlobalErrIds.CNTR_DELETE_FAILED, error, e );
+ }
+ finally
+ {
+ closeAdminConnection( ld );
+ }
+ }
+}
\ 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/ldap/container/OrganizationalUnitP.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/ldap/container/OrganizationalUnitP.java b/src/main/java/org/apache/directory/fortress/core/ldap/container/OrganizationalUnitP.java
new file mode 100755
index 0000000..7ce72d8
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/ldap/container/OrganizationalUnitP.java
@@ -0,0 +1,147 @@
+/*
+ * 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.ldap.container;
+
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.directory.fortress.core.GlobalErrIds;
+import org.apache.directory.fortress.core.GlobalIds;
+import org.apache.directory.fortress.core.SecurityException;
+import org.apache.directory.fortress.core.ValidationException;
+import org.apache.directory.fortress.core.util.attr.VUtil;
+
+
+/**
+ * Process module for the container node used for grouping related nodes within Fortress directory structure. The organizational unit represents
+ * the middle nodes that act as containers for other nodes, i.e. ou=People container which groups Users.
+ * The organizational unit data is passed using {@link OrganizationalUnit} class. This class does perform simple data validations.
+ * The {@link org.apache.directory.fortress.core.ant.FortressAntTask#addContainers()} method calls the {@link #add} from this class during initial base loads.
+ * Removal {@link org.apache.directory.fortress.core.ant.FortressAntTask#deleteContainers()} is performed during regression tests and should never
+ * be executed targeting enabled production directory system datasets.<BR>
+ * This class will accept {@link OrganizationalUnit}, and forward on to it's corresponding DAO class {@link OrganizationalUnitDAO} for add/delete of container.
+ * <p>
+ * Class will throw {@link SecurityException} to caller in the event of security policy, data constraint violation or system
+ * error internal to DAO object. This class will forward DAO exceptions (
+ * {@link org.apache.directory.fortress.core.CreateException},,{@link org.apache.directory.fortress.core.RemoveException}),
+ * or {@link org.apache.directory.fortress.core.ValidationException} as {@link org.apache.directory.fortress.core.SecurityException}s with appropriate
+ * error id from {@link org.apache.directory.fortress.core.GlobalErrIds}.
+ * <p>
+ * <font size="3" color="red">
+ * The {@link #delete} method in this class is destructive as it will remove all nodes below the container using recursive delete function.<BR>
+ * Extreme care should be taken during execution to ensure target dn is correct and permanent removal of data is intended. There is no
+ * 'undo' for this operation.
+ * </font>
+ * <p/>
+ * Simple error mapping is performed in {@link #validate} class.
+ * <p/>
+ * This class is thread safe.
+ *
+ * @author Shawn McKinney
+ */
+public class OrganizationalUnitP
+{
+ private static final String CLS_NM = OrganizationalUnitP.class.getName();
+ private static final Logger LOG = LoggerFactory.getLogger( CLS_NM );
+
+
+ /**
+ * Add a new container to the Directory Information Tree (DIT). After added the
+ * node will be inserted after suffix, i.e. ou=NewContainerName, dc=companyName, dc=com.
+ *
+ * @param orgUnit contains the ou name and description for target node.
+ * @throws org.apache.directory.fortress.core.SecurityException in the event node already present, {@link GlobalErrIds#CNTR_CREATE_FAILED}, validation, {@link GlobalErrIds#CNTR_NAME_NULL}, {@link org.apache.directory.fortress.core.GlobalErrIds#CNTR_NAME_INVLD} or system error.
+ */
+ public final void add( OrganizationalUnit orgUnit )
+ throws SecurityException
+ {
+ OrganizationalUnitDAO oDao = new OrganizationalUnitDAO();
+ oDao.create( orgUnit );
+ }
+
+
+ /**
+ * Remove a container from the Directory Information Tree (DIT). After this operation the
+ * node will be removed after suffix.
+ *
+ * <p>
+ * <font size="4" color="red">
+ * The {@link #delete} method in this class is destructive as it will remove all nodes below the container using recursive delete function.<BR>
+ * Extreme care should be taken during execution to ensure target dn is correct and permanent removal of data is intended. There is no
+ * 'undo' for this operation.
+ * </font>
+ * <p/>
+ *
+ * @param orgUnit contains the ou name of container targeted for removal.
+ * @throws org.apache.directory.fortress.core.SecurityException in the event node not present, {@link org.apache.directory.fortress.core.GlobalErrIds#CNTR_DELETE_FAILED}, validation, {@link org.apache.directory.fortress.core.GlobalErrIds#CNTR_NAME_NULL}, {@link org.apache.directory.fortress.core.GlobalErrIds#CNTR_NAME_INVLD} or system error.
+ */
+ public final void delete( OrganizationalUnit orgUnit )
+ throws SecurityException
+ {
+ OrganizationalUnitDAO oDao = new OrganizationalUnitDAO();
+ oDao.remove( orgUnit );
+ }
+
+
+ /**
+ * Method will perform simple validations to ensure the integrity of the {@link OrganizationalUnit} entity targeted for insertion
+ * or deletion in directory.
+ *
+ * @param entity contains the enum type to validate
+ * @throws SecurityException thrown in the event the attribute is null.
+ */
+ private void validate( OrganizationalUnit entity )
+ throws SecurityException
+ {
+ if ( entity.getName().length() > GlobalIds.OU_LEN )
+ {
+ String name = entity.getName();
+ String error = "validate name [" + name + "] invalid length [" + entity.getName().length() + "]";
+ LOG.warn( error );
+ throw new ValidationException( GlobalErrIds.CNTR_NAME_INVLD, error );
+ }
+ if ( !VUtil.isNotNullOrEmpty( entity.getName() ) )
+ {
+ String error = "validate name validation failed, null or empty value";
+ LOG.warn( error );
+ throw new ValidationException( GlobalErrIds.CNTR_NAME_NULL, error );
+ }
+ if ( entity.getParent().length() > GlobalIds.OU_LEN )
+ {
+ String name = entity.getName();
+ String error = "validate parent [" + name + "] invalid length [" + entity.getName().length()
+ + "]";
+ LOG.warn( error );
+ throw new ValidationException( GlobalErrIds.CNTR_PARENT_INVLD, error );
+ }
+ if ( !VUtil.isNotNullOrEmpty( entity.getParent() ) )
+ {
+ String error = "validate parent validation failed, null or empty value";
+ LOG.warn( error );
+ throw new ValidationException( GlobalErrIds.CNTR_PARENT_NULL, error );
+ }
+ VUtil.safeText( entity.getDescription(), GlobalIds.DESC_LEN );
+ if ( VUtil.isNotNullOrEmpty( entity.getDescription() ) )
+ {
+ VUtil.description( entity.getDescription() );
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/687ee1ad/src/main/java/org/apache/directory/fortress/core/ldap/container/package.html
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/ldap/container/package.html b/src/main/java/org/apache/directory/fortress/core/ldap/container/package.html
new file mode 100755
index 0000000..3f386af
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/ldap/container/package.html
@@ -0,0 +1,36 @@
+<!--
+ * 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.
+ *
+-->
+<html>
+ <head>
+ <title>Package Documentation for org.apache.directory.fortress.ldap.container</title>
+ </head>
+ <body>
+ <p>
+ This package contains APIs to perform CRUD on fortress container objects in ldap.
+ </p>
+ <p>
+ The <b>org.apache.directory.fortress.ldap.container</b> package provides apis to add and
+ remove ldap <b>OrganizationalUnit</b> entries. These entries are called 'containers'
+ and are used to organize related fortress nodes. An example container is <b>ou=People</b> which will be placed as a
+ child node of the directory's ldap suffix, i.e. <b>dc=example,dc=com</b>. The container is used to store subentries, i.e. <b>inetOrgPerson</b>.
+ These container APIs are used by buildup/teardown processes.
+ </p>
+ </body>
+</html>
http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/687ee1ad/src/main/java/org/apache/directory/fortress/core/ldap/group/Group.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/ldap/group/Group.java b/src/main/java/org/apache/directory/fortress/core/ldap/group/Group.java
new file mode 100755
index 0000000..2488205
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/ldap/group/Group.java
@@ -0,0 +1,421 @@
+/*
+ * 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.ldap.group;
+
+
+import org.apache.directory.fortress.core.rbac.FortEntity;
+import org.apache.directory.fortress.core.rbac.Props;
+import org.apache.directory.fortress.core.util.attr.AttrHelper;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+@XmlRootElement(name = "fortGroup")
+@XmlAccessorType( XmlAccessType.FIELD)
+@XmlType(name = "group", propOrder =
+ {
+ "name",
+ "description",
+ "protocol",
+ "members",
+ "props",
+ })
+public class Group extends FortEntity implements Serializable
+{
+ private String name;
+ private String description;
+ private String protocol;
+ private List<String> members;
+ private Props props = new Props();
+ boolean memberDn;
+
+ /**
+ * Default constructor used by {@link org.apache.directory.fortress.core.ant.FortressAntTask}
+ */
+ public Group()
+ {
+ }
+
+ /**
+ * Generate instance of group to be loaded as ldap object.
+ *
+ * @param name maps to 'cn' attribute in group object class.
+ */
+ public Group( String name )
+ {
+ this.name = name;
+ }
+
+ /**
+ * Generate instance of group to be loaded as ldap object.
+ *
+ * @param name maps to 'cn' attribute in group object class.
+ * @param description maps to 'description' attribute in group object class.
+ */
+ public Group( String name, String description )
+ {
+ this.name = name;
+ this.description = description;
+ }
+
+ /**
+ * Get the second level qualifier on the domain component. This attribute is required.
+ *
+ * @return name maps to 'dcObject' object class.
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Set the second level qualifier on the domain component. This attribute is required.
+ *
+ * @param name maps to 'dcObject' object class.
+ */
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+
+ /**
+ * Get the description for the domain component. This value is not required or constrained
+ * but is validated on reasonability.
+ *
+ * @return field maps to 'o' attribute on 'dcObject'.
+ */
+ public String getDescription()
+ {
+ return description;
+ }
+
+ /**
+ * Set the description for the domain component. This value is not required or constrained
+ * but is validated on reasonability.
+ *
+ * @param description maps to 'o' attribute on 'dcObject'.
+ */
+ public void setDescription(String description)
+ {
+ this.description = description;
+ }
+
+ /**
+ * Get protocol qualifier for this entity.
+ *
+ * @return protocol.
+ */
+ public String getProtocol()
+ {
+ return protocol;
+ }
+
+ /**
+ * Set the protocol qualifier for this entity.
+ *
+ * @param protocol contains protocol qualifier for this entity.
+ */
+ public void setProtocol( String protocol )
+ {
+ this.protocol = protocol;
+ }
+
+ /**
+ * Add a single userId as member of this entity.
+ *
+ * @param userId
+ */
+ public void setMember( String userId )
+ {
+ if ( members == null )
+ {
+ members = new ArrayList<>();
+ }
+ members.add( userId );
+ }
+
+ /**
+ * Return the members
+ *
+ * @return List of type String containing userIds.
+ */
+ public List<String> getMembers()
+ {
+ return members;
+ }
+
+ /**
+ * Set a member on this entity using a comma delimited String.
+ *
+ * @param members String contains one or more userids in comma delimited format.
+ */
+ public void setMembers( String members )
+ {
+ if (members != null)
+ {
+ StringTokenizer tkn = new StringTokenizer(members, ",");
+ if (tkn.countTokens() > 0)
+ {
+ while (tkn.hasMoreTokens())
+ {
+ String member = tkn.nextToken();
+ setMember( member );
+ }
+ }
+ }
+ }
+
+ /**
+ * Set members onto this entity using a List of userIds.
+ *
+ * @param members List of type String contains userIds to be associated as members of this group.
+ */
+ public void setMembers( List<String> members )
+ {
+ this.members = members;
+ }
+
+ /**
+ * Add name/value pair to list of properties associated with PermObj. These values are not constrained by Fortress.
+ * Properties are optional.
+ *
+ * @param key contains property name and maps to 'ftProps' attribute in 'ftProperties' aux object class.
+ * @param value
+ */
+ public void addProperty( String key, String value )
+ {
+ Props.Entry entry = new Props.Entry();
+ entry.setKey( key );
+ entry.setValue( value );
+ this.props.getEntry().add( entry );
+ }
+
+ /**
+ * Get a name/value pair attribute from list of properties associated with PermObj. These values are not constrained by Fortress.
+ * Properties are optional.
+ *
+ * @param key contains property name and maps to 'ftProps' attribute in 'ftProperties' aux object class.
+ * @return value containing name/value pair that maps to 'ftProps' attribute in 'ftProperties' aux object class.
+ */
+ public String getProperty( String key )
+ {
+ List<Props.Entry> props = this.props.getEntry();
+ Props.Entry keyObj = new Props.Entry();
+ keyObj.setKey( key );
+
+ String value = null;
+ int indx = props.indexOf( keyObj );
+ if ( indx != -1 )
+ {
+ Props.Entry entry = props.get( props.indexOf( keyObj ) );
+ value = entry.getValue();
+ }
+
+ return value;
+ }
+
+ /**
+ * Replace teh collection of name/value pairs to attributes associated with Group entity. These values are not constrained by Fortress.
+ * Properties are optional.
+ *
+ * @param properties contains collection of name/value pairs and maps to 'ftProps' attribute in 'ftProperties' aux object class.
+ */
+ public void setProperties( Properties properties )
+ {
+ if ( properties != null )
+ {
+ // reset the existing properties stored in this entity.
+ props = new Props();
+ for ( Enumeration e = properties.propertyNames(); e.hasMoreElements(); )
+ {
+ // This LDAP attr is stored as a name-value pair separated by a ':'.
+ String key = ( String ) e.nextElement();
+ String val = properties.getProperty( key );
+ addProperty( key, val );
+ }
+ }
+ }
+
+ /**
+ * Add new collection of name=value pairs to attributes associated with Group. These values are not constrained by Fortress.
+ * Properties are optional.
+ *
+ * @param properties contains name=value pairs that are comma delmited.
+ */
+ public void setProperties( String properties )
+ {
+ setProperties( AttrHelper.getProperties( properties, '=', "," ) );
+ }
+
+ /**
+ * Return the collection of name/value pairs to attributes associated with PermObj. These values are not constrained by Fortress.
+ * Properties are optional.
+ *
+ * @return Properties contains collection of name/value pairs and maps to 'ftProps' attribute in 'ftProperties' aux object class.
+ */
+ public Properties getProperties()
+ {
+ Properties properties = null;
+ List<Props.Entry> props = this.props.getEntry();
+ if ( props.size() > 0 )
+ {
+ properties = new Properties();
+ //int size = props.size();
+ for ( Props.Entry entry : props )
+ {
+ String key = entry.getKey();
+ String val = entry.getValue();
+ properties.setProperty( key, val );
+ }
+ }
+ return properties;
+ }
+
+ public List<String> getPropList()
+ {
+ List<Props.Entry> props = this.props.getEntry();
+ List<String> propList = null;
+ if ( props.size() > 0 )
+ {
+ propList = new ArrayList<>( );
+ for ( Props.Entry entry : props )
+ {
+ String key = entry.getKey();
+ String val = entry.getValue();
+ String prop = key + "=" + val;
+ propList.add( prop );
+ }
+ }
+ return propList;
+ }
+
+ /**
+ * Gets the value of the Props property. This method is used by Fortress and En Masse and should not be called by external programs.
+ *
+ * @return {@link Props }
+ *
+ */
+ public Props getProps()
+ {
+ return props;
+ }
+
+ /**
+ * Sets the value of the Props property. This method is used by Fortress and En Masse and should not be called by external programs.
+ *
+ * @param props
+ * allowed object is
+ * {@link Props }
+ *
+ */
+ public void setProps( Props props )
+ {
+ this.props = props;
+ }
+
+ /**
+ * Set if userDn's are loaded in dn format.
+ *
+ * @return true indicates members are in dn format.
+ */
+ public boolean isMemberDn()
+ {
+ return memberDn;
+ }
+
+ /**
+ * Set to 'true' if members are in dn format.
+ *
+ * @param memberDn boolean value, set to 'true' if distinguished name (dn) format, 'false' if relative distinguished name (rdn) format.
+ */
+ public void setMemberDn( boolean memberDn )
+ {
+ this.memberDn = memberDn;
+ }
+
+ @Override
+ public boolean equals( Object o )
+ {
+ if ( this == o )
+ {
+ return true;
+ }
+ if ( o == null || getClass() != o.getClass() )
+ {
+ return false;
+ }
+
+ Group group = ( Group ) o;
+
+/*
+ if ( description != null ? !description.equals( group.description ) : group.description != null )
+ {
+ return false;
+ }
+ if ( members != null ? !members.equals( group.members ) : group.members != null )
+ {
+ return false;
+ }
+*/
+ if(name == null)
+ return false;
+
+ if ( !name.equals( group.name ) )
+ {
+ return false;
+ }
+/*
+ if ( protocol != null ? !protocol.equals( group.protocol ) : group.protocol != null )
+ {
+ return false;
+ }
+*/
+
+ return true;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int result = name.hashCode();
+ result = 31 * result + ( description != null ? description.hashCode() : 0 );
+ result = 31 * result + ( protocol != null ? protocol.hashCode() : 0 );
+ result = 31 * result + ( members != null ? members.hashCode() : 0 );
+ result = 31 * result + ( props != null ? props.hashCode() : 0 );
+ return result;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "Group{" +
+ "name='" + name + '\'' +
+ ", description='" + description + '\'' +
+ '}';
+ }
+}
\ 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/ldap/group/GroupDAO.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/ldap/group/GroupDAO.java b/src/main/java/org/apache/directory/fortress/core/ldap/group/GroupDAO.java
new file mode 100755
index 0000000..fc906ee
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/ldap/group/GroupDAO.java
@@ -0,0 +1,463 @@
+/*
+ * 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.ldap.group;
+
+
+import org.apache.directory.api.ldap.model.cursor.CursorException;
+import org.apache.directory.api.ldap.model.cursor.SearchCursor;
+import org.apache.directory.api.ldap.model.entry.DefaultEntry;
+import org.apache.directory.api.ldap.model.entry.DefaultModification;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.entry.Modification;
+import org.apache.directory.api.ldap.model.entry.ModificationOperation;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
+import org.apache.directory.api.ldap.model.exception.LdapNoSuchObjectException;
+import org.apache.directory.api.ldap.model.message.SearchScope;
+import org.apache.directory.ldap.client.api.LdapConnection;
+import org.apache.directory.fortress.core.FinderException;
+import org.apache.directory.fortress.core.ObjectFactory;
+import org.apache.directory.fortress.core.UpdateException;
+import org.apache.directory.fortress.core.cfg.Config;
+import org.apache.directory.fortress.core.ldap.ApacheDsDataProvider;
+import org.apache.directory.fortress.core.rbac.User;
+import org.apache.directory.fortress.core.util.attr.AttrHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.directory.fortress.core.CreateException;
+import org.apache.directory.fortress.core.GlobalErrIds;
+import org.apache.directory.fortress.core.GlobalIds;
+import org.apache.directory.fortress.core.RemoveException;
+import org.apache.directory.fortress.core.util.attr.VUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Contains the Group node for LDAP Directory Information Tree.
+ * This class is thread safe.
+ *
+ * @author Shawn McKinney
+ */
+final class GroupDAO extends ApacheDsDataProvider
+{
+ private static final String CLS_NM = GroupDAO.class.getName();
+ private static final Logger LOG = LoggerFactory.getLogger( CLS_NM );
+ private static final String GROUP_OBJECT_CLASS = "group.objectclass";
+ private static final String GROUP_OBJECT_CLASS_IMPL = Config.getProperty( GROUP_OBJECT_CLASS );
+ private static final String GROUP_PROTOCOL_ATTR = "group.protocol";
+ private static final String GROUP_PROTOCOL_ATTR_IMPL = Config.getProperty( GROUP_PROTOCOL_ATTR );
+ private static final String GROUP_PROPERTY_ATTR = "group.properties";
+ private static final String GROUP_PROPERTY_ATTR_IMPL = Config.getProperty( GROUP_PROPERTY_ATTR );
+ private static final String GROUP_OBJ_CLASS[] = {GlobalIds.TOP, GROUP_OBJECT_CLASS_IMPL};
+ private static final String MEMBER = "member";
+ private static final String[] GROUP_ATRS = {GlobalIds.CN, GlobalIds.DESC, GROUP_PROTOCOL_ATTR_IMPL, GROUP_PROPERTY_ATTR_IMPL, MEMBER};
+
+ /**
+ * Package private default constructor.
+ */
+ GroupDAO()
+ {
+ }
+
+ /**
+ * @param group
+ * @throws org.apache.directory.fortress.core.CreateException
+ *
+ */
+ final Group create( Group group ) throws CreateException
+ {
+ LdapConnection ld = null;
+ String nodeDn = getDn( group.getName(), group.getContextId() );
+ try
+ {
+ LOG.debug( "create group dn {[]}", nodeDn );
+ Entry myEntry = new DefaultEntry( nodeDn );
+ myEntry.add( GlobalIds.OBJECT_CLASS, GROUP_OBJ_CLASS );
+ myEntry.add( GlobalIds.CN , group.getName() );
+ myEntry.add( GROUP_PROTOCOL_ATTR_IMPL, group.getProtocol() );
+ loadAttrs( group.getMembers(), myEntry, MEMBER );
+ loadProperties( group.getProperties(), myEntry, GROUP_PROPERTY_ATTR_IMPL, '=' );
+ if ( VUtil.isNotNullOrEmpty( group.getDescription() ) )
+ {
+ myEntry.add( GlobalIds.DESC, group.getDescription() );
+ }
+ ld = getAdminConnection();
+ add( ld, myEntry );
+ }
+ catch ( LdapException e )
+ {
+ String error = "create group node dn [" + nodeDn + "] caught LDAPException=" + e.getMessage();
+ throw new CreateException( GlobalErrIds.GROUP_ADD_FAILED, error, e );
+ }
+ finally
+ {
+ closeAdminConnection( ld );
+ }
+ return group;
+ }
+
+ /**
+ * @param group
+ * @return
+ * @throws org.apache.directory.fortress.core.CreateException
+ *
+ */
+ final Group update( Group group ) throws FinderException, UpdateException
+ {
+ LdapConnection ld = null;
+ String nodeDn = getDn( group.getName(), group.getContextId() );
+ try
+ {
+ LOG.debug( "update group dn {[]}", nodeDn );
+ List<Modification> mods = new ArrayList<Modification>();
+ if ( VUtil.isNotNullOrEmpty( group.getDescription() ) )
+ {
+ mods.add( new DefaultModification(
+ ModificationOperation.REPLACE_ATTRIBUTE, GlobalIds.DESC, group.getDescription() ) );
+ }
+ if ( VUtil.isNotNullOrEmpty( group.getProtocol() ) )
+ {
+ mods.add( new DefaultModification(
+ ModificationOperation.REPLACE_ATTRIBUTE, GROUP_PROTOCOL_ATTR_IMPL, group.getProtocol() ) );
+ }
+ loadAttrs( group.getMembers(), mods, MEMBER );
+ loadProperties( group.getProperties(), mods, GROUP_PROPERTY_ATTR_IMPL, true, '=' );
+ if ( mods.size() > 0 )
+ {
+ ld = getAdminConnection();
+ modify( ld, nodeDn, mods, group );
+ }
+ }
+ catch ( LdapException e )
+ {
+ String error = "update group node dn [" + nodeDn + "] caught LDAPException=" + e.getMessage();
+ throw new UpdateException( GlobalErrIds.GROUP_UPDATE_FAILED, error, e );
+ }
+ finally
+ {
+ closeAdminConnection( ld );
+ }
+ return get( group );
+ }
+
+ final Group add( Group group, String key, String value ) throws FinderException, CreateException
+ {
+ LdapConnection ld = null;
+ String nodeDn = getDn( group.getName(), group.getContextId() );
+ try
+ {
+ LOG.debug( "add group property dn {[]}, key {[]}, value {[]}", nodeDn, key, value );
+ List<Modification> mods = new ArrayList<Modification>();
+ mods.add( new DefaultModification(
+ ModificationOperation.ADD_ATTRIBUTE, GROUP_PROPERTY_ATTR_IMPL, key + "=" + value ) );
+ ld = getAdminConnection();
+ modify( ld, nodeDn, mods, group );
+ }
+ catch ( LdapException e )
+ {
+ String error = "update group property node dn [" + nodeDn + "] caught LDAPException=" + e.getMessage();
+ throw new CreateException( GlobalErrIds.GROUP_ADD_PROPERTY_FAILED, error, e );
+ }
+ finally
+ {
+ closeAdminConnection( ld );
+ }
+ return get( group );
+ }
+
+ final Group delete( Group group, String key, String value ) throws FinderException, RemoveException
+ {
+ LdapConnection ld = null;
+ String nodeDn = getDn( group.getName(), group.getContextId() );
+ try
+ {
+ LOG.debug( "delete group property dn {[]}, key {[]}, value {[]}", nodeDn, key, value );
+ List<Modification> mods = new ArrayList<Modification>();
+ mods.add( new DefaultModification(
+ ModificationOperation.REMOVE_ATTRIBUTE, GROUP_PROPERTY_ATTR_IMPL, key + "=" + value ) );
+ ld = getAdminConnection();
+ modify( ld, nodeDn, mods, group );
+ }
+ catch ( LdapException e )
+ {
+ String error = "delete group property node dn [" + nodeDn + "] caught LDAPException=" + e.getMessage();
+ throw new RemoveException( GlobalErrIds.GROUP_DELETE_PROPERTY_FAILED, error, e );
+ }
+ finally
+ {
+ closeAdminConnection( ld );
+ }
+ return get( group );
+ }
+
+ /**
+ * This method will remove group node from diretory.
+ *
+ * @param group
+ * @throws org.apache.directory.fortress.core.RemoveException
+ *
+ */
+ final Group remove( Group group ) throws RemoveException
+ {
+ LdapConnection ld = null;
+ String nodeDn = getDn( group.getName(), group.getContextId() );
+ LOG.debug( "remove group dn {[]}", nodeDn );
+ try
+ {
+ ld = getAdminConnection();
+ deleteRecursive( ld, nodeDn );
+ }
+ catch ( CursorException e )
+ {
+ String error = "remove group node dn [" + nodeDn + "] caught CursorException="
+ + e.getMessage();
+ throw new RemoveException( GlobalErrIds.GROUP_DELETE_FAILED, error, e );
+ }
+ catch ( LdapException e )
+ {
+ String error = "remove group node dn [" + nodeDn + "] caught LDAPException=" + e.getMessage();
+ throw new RemoveException( GlobalErrIds.GROUP_DELETE_FAILED, error, e );
+ }
+ finally
+ {
+ closeAdminConnection( ld );
+ }
+ return group;
+ }
+
+ /**
+ * @param entity
+ * @param userDn
+ * @return
+ * @throws org.apache.directory.fortress.core.UpdateException
+ *
+ */
+ final Group assign( Group entity, String userDn ) throws FinderException, UpdateException
+ {
+ LdapConnection ld = null;
+ String dn = getDn( entity.getName(), entity.getContextId() );
+ LOG.debug( "assign group property dn {[]}, member dn {[]}", dn, userDn );
+ try
+ {
+ List<Modification> mods = new ArrayList<Modification>();
+ mods.add( new DefaultModification(
+ ModificationOperation.ADD_ATTRIBUTE, MEMBER, userDn ) );
+ ld = getAdminConnection();
+ modify( ld, dn, mods, entity );
+ }
+ catch ( LdapException e )
+ {
+ String error = "assign group name [" + entity.getName() + "] user dn [" + userDn + "] caught " +
+ "LDAPException=" + e.getMessage();
+ throw new UpdateException( GlobalErrIds.GROUP_USER_ASSIGN_FAILED, error, e );
+ }
+ finally
+ {
+ closeAdminConnection( ld );
+ }
+ return get( entity );
+ }
+
+ /**
+ * @param entity
+ * @param userDn
+ * @return
+ * @throws org.apache.directory.fortress.core.UpdateException
+ *
+ */
+ final Group deassign( Group entity, String userDn ) throws FinderException, UpdateException
+ {
+ LdapConnection ld = null;
+ String dn = getDn( entity.getName(), entity.getContextId() );
+ LOG.debug( "deassign group property dn {[]}, member dn {[]}", dn, userDn );
+ try
+ {
+ List<Modification> mods = new ArrayList<Modification>();
+ mods.add( new DefaultModification(
+ ModificationOperation.REMOVE_ATTRIBUTE, MEMBER, userDn ) );
+
+ ld = getAdminConnection();
+ modify( ld, dn, mods, entity );
+ }
+ catch ( LdapException e )
+ {
+ String error = "deassign group name [" + entity.getName() + "] user dn [" + userDn + "] caught " +
+ "LDAPException=" + e.getMessage();
+ throw new UpdateException( GlobalErrIds.GROUP_USER_DEASSIGN_FAILED, error, e );
+ }
+ finally
+ {
+ closeAdminConnection( ld );
+ }
+ return get( entity );
+ }
+
+ /**
+ * @param group
+ * @return
+ * @throws org.apache.directory.fortress.core.FinderException
+ *
+ */
+ final Group get( Group group ) throws FinderException
+ {
+ Group entity = null;
+ LdapConnection ld = null;
+ String dn = getDn( group.getName(), group.getContextId() );
+ try
+ {
+ ld = getAdminConnection();
+ Entry findEntry = read( ld, dn, GROUP_ATRS );
+ entity = unloadLdapEntry( findEntry, 0 );
+ if ( entity == null )
+ {
+ String warning = "read no entry found dn [" + dn + "]";
+ throw new FinderException( GlobalErrIds.GROUP_NOT_FOUND, warning );
+ }
+ }
+ catch ( LdapNoSuchObjectException e )
+ {
+ String warning = "read Obj COULD NOT FIND ENTRY for dn [" + dn + "]";
+ throw new FinderException( GlobalErrIds.GROUP_NOT_FOUND, warning );
+ }
+ catch ( LdapException e )
+ {
+ String error = "read dn [" + dn + "] LdapException=" + e.getMessage();
+ throw new FinderException( GlobalErrIds.GROUP_READ_FAILED, error, e );
+ }
+ finally
+ {
+ closeAdminConnection( ld );
+ }
+ return entity;
+ }
+
+ /**
+ * @param group
+ * @return
+ * @throws org.apache.directory.fortress.core.FinderException
+ *
+ */
+ final List<Group> find( Group group ) throws FinderException
+ {
+ List<Group> groupList = new ArrayList<>();
+ LdapConnection ld = null;
+ SearchCursor searchResults;
+ String groupRoot = getRootDn( group.getContextId(), GlobalIds.GROUP_ROOT );
+ String filter = null;
+ try
+ {
+ String searchVal = encodeSafeText( group.getName(), GlobalIds.ROLE_LEN );
+ filter = GlobalIds.FILTER_PREFIX + GROUP_OBJECT_CLASS_IMPL + ")(" + GlobalIds.CN + "=" + searchVal + "*))";
+ ld = getAdminConnection();
+ searchResults = search( ld, groupRoot, SearchScope.ONELEVEL, filter, GROUP_ATRS, false,
+ GlobalIds.BATCH_SIZE );
+ long sequence = 0;
+ while ( searchResults.next() )
+ {
+ groupList.add( unloadLdapEntry( searchResults.getEntry(), sequence++ ) );
+ }
+ }
+ catch ( CursorException e )
+ {
+ String error = "find filter [" + filter + "] caught CursorException=" + e.getMessage();
+ throw new FinderException( GlobalErrIds.GROUP_SEARCH_FAILED, error, e );
+ }
+ catch ( LdapException e )
+ {
+ String error = "find filter [" + filter + "] caught LDAPException=" + e.getMessage();
+ throw new FinderException( GlobalErrIds.GROUP_SEARCH_FAILED, error, e );
+ }
+ finally
+ {
+ closeAdminConnection( ld );
+ }
+ return groupList;
+ }
+
+ /**
+ * @param user
+ * @return
+ * @throws org.apache.directory.fortress.core.FinderException
+ *
+ */
+ final List<Group> find( User user ) throws FinderException
+ {
+ List<Group> groupList = new ArrayList<>();
+ LdapConnection ld = null;
+ SearchCursor searchResults;
+ String groupRoot = getRootDn( user.getContextId(), GlobalIds.GROUP_ROOT );
+ String filter = null;
+ try
+ {
+ String searchVal = encodeSafeText( user.getUserId(), GlobalIds.USERID_LEN );
+ filter = GlobalIds.FILTER_PREFIX + GROUP_OBJECT_CLASS_IMPL + ")(" + MEMBER + "=" + user.getDn() + "))";
+ ld = getAdminConnection();
+ searchResults = search( ld, groupRoot, SearchScope.ONELEVEL, filter, GROUP_ATRS, false,
+ GlobalIds.BATCH_SIZE );
+ long sequence = 0;
+ while ( searchResults.next() )
+ {
+ groupList.add( unloadLdapEntry( searchResults.getEntry(), sequence++ ) );
+ }
+ }
+ catch ( CursorException e )
+ {
+ String error = "find filter [" + filter + "] caught CursorException=" + e.getMessage();
+ throw new FinderException( GlobalErrIds.GROUP_SEARCH_FAILED, error, e );
+ }
+ catch ( LdapException e )
+ {
+ String error = "find filter [" + filter + "] caught LDAPException=" + e.getMessage();
+ throw new FinderException( GlobalErrIds.GROUP_SEARCH_FAILED, error, e );
+ }
+ finally
+ {
+ closeAdminConnection( ld );
+ }
+ return groupList;
+ }
+
+ /**
+ * @param le
+ * @param sequence
+ * @return
+ * @throws LdapException
+ */
+ private Group unloadLdapEntry( Entry le, long sequence )
+ throws LdapInvalidAttributeValueException
+ {
+ Group entity = new ObjectFactory().createGroup();
+ entity.setName( getAttribute( le, GlobalIds.CN ) );
+ entity.setDescription( getAttribute( le, GlobalIds.DESC ) );
+ entity.setProtocol( getAttribute( le, GROUP_PROTOCOL_ATTR_IMPL ) );
+ entity.setMembers( getAttributes( le, MEMBER ) );
+ entity.setMemberDn( true );
+ entity.setProperties( AttrHelper.getProperties( getAttributes( le, GROUP_PROPERTY_ATTR_IMPL ), '=' ) );
+ entity.setSequenceId( sequence );
+ return entity;
+ }
+
+ private String getDn( String name, String contextId )
+ {
+ return GlobalIds.CN + "=" + name + "," + getRootDn( contextId, GlobalIds.GROUP_ROOT );
+ }
+}
\ 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/ldap/group/GroupMgr.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/ldap/group/GroupMgr.java b/src/main/java/org/apache/directory/fortress/core/ldap/group/GroupMgr.java
new file mode 100755
index 0000000..2316de9
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/ldap/group/GroupMgr.java
@@ -0,0 +1,135 @@
+/*
+ * 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.ldap.group;
+
+import org.apache.directory.fortress.core.*;
+import org.apache.directory.fortress.core.SecurityException;
+import org.apache.directory.fortress.core.rbac.User;
+
+import java.util.List;
+
+/**
+ * This interface prescribes CRUD methods used to manage groups stored within the ldap directory.
+ * <p/>
+ * This class is thread safe.
+ * <p/>
+ *
+ * @author Shawn McKinney
+ */
+public interface GroupMgr extends Manageable
+{
+ /**
+ * Create a new group node.,
+ *
+ * @param group contains {@link Group}.
+ * @return {@link Group} containing entity just added.
+ * @throws org.apache.directory.fortress.core.SecurityException in the event system error.
+ */
+ public Group add( Group group ) throws org.apache.directory.fortress.core.SecurityException;
+
+ /**
+ * Modify existing group node. The name is required. Does not update members or properties.
+ * Use {@link GroupMgr#add( Group group, String key, String value )}, {@link GroupMgr#delete( Group group, String key, String value )},
+ * {@link GroupMgr#assign( Group group, String member) }, or {@link GroupMgr#deassign( Group group, String member) } for multi-occurring attributes.
+ *
+ * @param group contains {@link Group}.
+ * @return {@link Group} containing entity just modified.
+ * @throws org.apache.directory.fortress.core.SecurityException in the event system error.
+ */
+ public Group update( Group group ) throws SecurityException;
+
+ /**
+ * Delete existing group node. The name is required.
+ *
+ * @param group contains {@link Group}.
+ * @return {@link Group} containing entity just removed.
+ * @throws org.apache.directory.fortress.core.SecurityException in the event system error.
+ */
+ public Group delete( Group group ) throws SecurityException;
+
+ /**
+ * Add a property to an existing group node. Must have a name and at least one member.
+ *
+ * @param group contains {@link Group}.
+ * @param key contains the property key.
+ * @param value contains contains the property value.
+ * @return {@link Group} containing entity just modified.
+ * @throws org.apache.directory.fortress.core.SecurityException in the event system error.
+ */
+ public Group add( Group group, String key, String value ) throws SecurityException;
+
+ /**
+ * Delete existing group node. The name is required.
+ *
+ * @param group contains {@link Group}.
+ * @param key contains the property key.
+ * @param value contains contains the property value.
+ * @return {@link Group} containing entity just modified.
+ * @throws org.apache.directory.fortress.core.SecurityException in the event system error.
+ */
+ public Group delete( Group group, String key, String value ) throws SecurityException;
+
+ /**
+ * Read an existing group node. The name is required.
+ *
+ * @param group contains {@link Group} with name field set with an existing group name.
+ * @return {@link Group} containing entity found.
+ * @throws org.apache.directory.fortress.core.SecurityException in the event system error.
+ */
+ public Group read( Group group ) throws SecurityException;
+
+ /**
+ * Search using a full or partial group node. The name is required.
+ *
+ * @param group contains {@link Group}.
+ * @return List of type {@link Group} containing entities found.
+ * @throws org.apache.directory.fortress.core.SecurityException in the event system error.
+ */
+ public List<Group> find( Group group ) throws SecurityException;
+
+ /**
+ * Search for groups by userId. Member (maps to userId) and is required.
+ *
+ * @param user contains userId that maps to Group member attribute.
+ * @return {@link Group} containing entity just added.
+ * @throws org.apache.directory.fortress.core.SecurityException in the event system error.
+ */
+ public List<Group> find( User user ) throws SecurityException;
+
+ /**
+ * Assign a user to an existing group node. The group name and member are required.
+ *
+ * @param group contains {@link Group}.
+ * @param member is the relative distinguished name (rdn) of an existing user in ldap.
+ * @return {@link Group} containing entity to assign.
+ * @throws org.apache.directory.fortress.core.SecurityException in the event entry already present or other system error.
+ */
+ public Group assign( Group group, String member ) throws SecurityException;
+
+ /**
+ * Deassign a member from an existing group node. The group name and member are required.
+ *
+ * @param group contains {@link Group}.
+ * @param member is the relative distinguished name (rdn) of an existing user in ldap.
+ * @return {@link Group} containing entity to deassign
+ * @throws org.apache.directory.fortress.core.SecurityException in the event entry already present or other system error.
+ */
+ public Group deassign( Group group, String member ) throws SecurityException;
+}
\ 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/ldap/group/GroupMgrFactory.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/ldap/group/GroupMgrFactory.java b/src/main/java/org/apache/directory/fortress/core/ldap/group/GroupMgrFactory.java
new file mode 100755
index 0000000..102587c
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/ldap/group/GroupMgrFactory.java
@@ -0,0 +1,107 @@
+/*
+ * 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.ldap.group;
+
+import org.apache.directory.fortress.core.GlobalErrIds;
+import org.apache.directory.fortress.core.GlobalIds;
+import org.apache.directory.fortress.core.cfg.Config;
+import org.apache.directory.fortress.core.rbac.ClassUtil;
+import org.apache.directory.fortress.core.SecurityException;
+import org.apache.directory.fortress.core.rbac.Session;
+import org.apache.directory.fortress.core.util.attr.VUtil;
+
+/**
+ * Creates an instance of the ConfigMgr object.
+ * <p/>
+ * The default implementation class is specified as {@link GroupMgrImpl} but can be overridden by
+ * adding the {@link org.apache.directory.fortress.core.GlobalIds#GROUP_IMPLEMENTATION} config property.
+ * <p/>
+
+ *
+ * @author Shawn McKinney
+ */
+public class GroupMgrFactory
+{
+ private static String groupClassName = Config.getProperty( GlobalIds.GROUP_IMPLEMENTATION );
+ private static final String CLS_NM = GroupMgrFactory.class.getName();
+
+ /**
+ * Create and return a reference to {@link GroupMgr} object using HOME context.
+ *
+ * @return instance of {@link org.apache.directory.fortress.core.AdminMgr}.
+ * @throws org.apache.directory.fortress.core.SecurityException in the event of failure during instantiation.
+ */
+ public static GroupMgr createInstance()
+ throws SecurityException
+ {
+ return createInstance( GlobalIds.HOME );
+ }
+
+ /**
+ * Create and return a reference to {@link GroupMgr} object.
+ *
+ * @param contextId maps to sub-tree in DIT, for example ou=contextId, dc=jts, dc = com.
+ * @return instance of {@link GroupMgr}.
+ * @throws org.apache.directory.fortress.core.SecurityException in the event of failure during instantiation.
+ */
+ public static GroupMgr createInstance(String contextId)
+ throws SecurityException
+ {
+ VUtil.assertNotNull( contextId, GlobalErrIds.CONTEXT_NULL, CLS_NM + ".createInstance" );
+ if (!VUtil.isNotNullOrEmpty(groupClassName))
+ {
+ groupClassName = GroupMgrImpl.class.getName();
+ }
+
+ GroupMgr groupMgr = (GroupMgr) ClassUtil.createInstance(groupClassName);
+ groupMgr.setContextId(contextId);
+ return groupMgr;
+ }
+
+
+ /**
+ * Create and return a reference to {@link GroupMgr} object using HOME context.
+ *
+ * @param adminSess contains a valid Fortress A/RBAC Session object.
+ * @return instance of {@link org.apache.directory.fortress.core.AdminMgr}.
+ * @throws SecurityException in the event of failure during instantiation.
+ */
+ public static GroupMgr createInstance(Session adminSess)
+ throws SecurityException
+ {
+ return createInstance( GlobalIds.HOME, adminSess );
+ }
+
+ /**
+ * Create and return a reference to {@link GroupMgr} object.
+ *
+ * @param contextId maps to sub-tree in DIT, for example ou=contextId, dc=jts, dc = com.
+ * @param adminSess contains a valid Fortress A/RBAC Session object.
+ * @return instance of {@link org.apache.directory.fortress.core.AdminMgr}.
+ * @throws SecurityException in the event of failure during instantiation.
+ */
+ public static GroupMgr createInstance(String contextId, Session adminSess)
+ throws SecurityException
+ {
+ GroupMgr groupMgr = createInstance(contextId);
+ groupMgr.setAdmin(adminSess);
+ return groupMgr;
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/687ee1ad/src/main/java/org/apache/directory/fortress/core/ldap/group/GroupMgrImpl.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/ldap/group/GroupMgrImpl.java b/src/main/java/org/apache/directory/fortress/core/ldap/group/GroupMgrImpl.java
new file mode 100755
index 0000000..8c5722a
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/ldap/group/GroupMgrImpl.java
@@ -0,0 +1,244 @@
+/*
+ * 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.ldap.group;
+
+import org.apache.directory.fortress.core.*;
+import org.apache.directory.fortress.core.SecurityException;
+import org.apache.directory.fortress.core.rbac.Manageable;
+import org.apache.directory.fortress.core.rbac.User;
+import org.apache.directory.fortress.core.util.attr.VUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * This Manager impl supplies CRUD methods used to manage groups stored within the ldap directory.
+ * LDAP group nodes are used for utility and security functions within various systems and apps.
+ * <p/>
+ * This class is thread safe.
+ * <p/>
+
+ *
+ * @author Shawn McKinney
+ */
+public class GroupMgrImpl extends Manageable implements GroupMgr
+{
+ private static final String CLS_NM = GroupMgrImpl.class.getName();
+ private static final GroupP groupP = new GroupP();
+
+ /**
+ * Create a new group node. Must have a name and at least one member.
+ *
+ * @param group contains {@link Group}.
+ * @return {@link Group} containing entity just added.
+ * @throws org.apache.directory.fortress.core.SecurityException in the event system error.
+ */
+ @Override
+ public Group add( Group group ) throws org.apache.directory.fortress.core.SecurityException
+ {
+ String methodName = "add";
+ assertContext(CLS_NM, methodName, group, GlobalErrIds.GROUP_NULL);
+ checkAccess(CLS_NM, methodName);
+ if(!group.isMemberDn())
+ {
+ loadUserDns( group );
+ }
+
+ return groupP.add( group );
+ }
+
+ /**
+ * Modify existing group node. The name is required. Does not update members or properties.
+ * Use {@link GroupMgr#add( Group group, String key, String value )}, {@link GroupMgr#delete( Group group, String key, String value )},
+ * {@link GroupMgr#assign( Group group, String member) }, or {@link GroupMgr#deassign( Group group, String member) } for multi-occurring attributes.
+ *
+ * @param group contains {@link Group}.
+ * @return {@link Group} containing entity just modified.
+ * @throws org.apache.directory.fortress.core.SecurityException in the event system error.
+ */
+ @Override
+ public Group update( Group group ) throws SecurityException
+ {
+ String methodName = "update";
+ assertContext(CLS_NM, methodName, group, GlobalErrIds.GROUP_NULL);
+ checkAccess(CLS_NM, methodName);
+ return groupP.update( group );
+ }
+
+ /**
+ * Delete existing group node. The name is required.
+ *
+ * @param group contains {@link Group}.
+ * @return {@link Group} containing entity just removed.
+ * @throws org.apache.directory.fortress.core.SecurityException in the event system error.
+ */
+ @Override
+ public Group delete( Group group ) throws SecurityException
+ {
+ String methodName = "delete";
+ assertContext(CLS_NM, methodName, group, GlobalErrIds.GROUP_NULL);
+ checkAccess(CLS_NM, methodName);
+ return groupP.delete( group );
+ }
+
+ /**
+ * Add a property to an existing group node. The name is required.
+ *
+ * @param group contains {@link Group}.
+ * @param key contains the property key.
+ * @param value contains contains the property value.
+ * @return {@link Group} containing entity just modified.
+ * @throws org.apache.directory.fortress.core.SecurityException in the event system error.
+ */
+ public Group add( Group group, String key, String value ) throws SecurityException
+ {
+ String methodName = "addProperty";
+ assertContext(CLS_NM, methodName, group, GlobalErrIds.GROUP_NULL);
+ checkAccess(CLS_NM, methodName);
+ return groupP.add( group, key, value );
+ }
+
+ /**
+ * Delete existing group node. The name is required.
+ *
+ * @param group contains {@link Group}.
+ * @param key contains the property key.
+ * @param value contains contains the property value.
+ * @return {@link Group} containing entity just modified.
+ * @throws org.apache.directory.fortress.core.SecurityException in the event system error.
+ */
+ public Group delete( Group group, String key, String value ) throws SecurityException
+ {
+ String methodName = "deleteProperty";
+ assertContext(CLS_NM, methodName, group, GlobalErrIds.GROUP_NULL);
+ checkAccess(CLS_NM, methodName);
+ return groupP.delete( group, key, value );
+ }
+
+ /**
+ * Read an existing group node. The name is required.
+ *
+ * @param group contains {@link Group} with name field set with an existing group name.
+ * @return {@link Group} containing entity found.
+ * @throws org.apache.directory.fortress.core.SecurityException in the event system error.
+ */
+ @Override
+ public Group read( Group group ) throws SecurityException
+ {
+ String methodName = "read";
+ assertContext(CLS_NM, methodName, group, GlobalErrIds.GROUP_NULL);
+ checkAccess(CLS_NM, methodName);
+ return groupP.read( group );
+ }
+
+ /**
+ * Search using a full or partial group node. The name is required.
+ *
+ * @param group contains {@link Group}.
+ * @return List of type {@link Group} containing entities found.
+ * @throws org.apache.directory.fortress.core.SecurityException in the event system error.
+ */
+ @Override
+ public List<Group> find( Group group ) throws SecurityException
+ {
+ String methodName = "find";
+ assertContext(CLS_NM, methodName, group, GlobalErrIds.GROUP_NULL);
+ checkAccess(CLS_NM, methodName);
+ return groupP.search( group );
+ }
+
+ /**
+ * Search for groups by userId. Member (maps to userId) and is required.
+ *
+ * @param user contains userId that maps to Group member attribute.
+ * @return {@link Group} containing entity just added.
+ * @throws org.apache.directory.fortress.core.SecurityException in the event system error.
+ */
+ public List<Group> find( User user ) throws SecurityException
+ {
+ String methodName = "findWithUsers";
+ assertContext(CLS_NM, methodName, user, GlobalErrIds.USER_NULL);
+ checkAccess(CLS_NM, methodName);
+ loadUserDn( user );
+ return groupP.search( user );
+ }
+
+ /**
+ * Assign a user to an existing group node. The name is required and userDn are required.
+ *
+ * @param group contains {@link Group}.
+ * @param member is the relative distinguished name (rdn) of an existing user in ldap.
+ * @return {@link Group} containing entity to assign.
+ * @throws org.apache.directory.fortress.core.SecurityException in the event entry already present or other system error.
+ */
+ @Override
+ public Group assign( Group group, String member ) throws SecurityException
+ {
+ String methodName = "assign";
+ assertContext(CLS_NM, methodName, group, GlobalErrIds.GROUP_NULL);
+ checkAccess(CLS_NM, methodName);
+ ReviewMgr reviewMgr = ReviewMgrFactory.createInstance();
+ User user = reviewMgr.readUser( new User( member ) );
+ return groupP.assign( group, user.getDn() );
+ }
+
+ /**
+ * Deassign a user from an existing group node. The name is required and userDn are required.
+ *
+ * @param group contains {@link Group}.
+ * @param member is the relative distinguished name (rdn) of an existing user in ldap.
+ * @return {@link Group} containing entity to deassign
+ * @throws org.apache.directory.fortress.core.SecurityException in the event entry already present or other system error.
+ */
+ @Override
+ public Group deassign( Group group, String member ) throws SecurityException
+ {
+ String methodName = "deassign";
+ assertContext(CLS_NM, methodName, group, GlobalErrIds.GROUP_NULL);
+ checkAccess(CLS_NM, methodName);
+ ReviewMgr reviewMgr = ReviewMgrFactory.createInstance();
+ User user = reviewMgr.readUser( new User( member ) );
+ return groupP.deassign( group, user.getDn() );
+ }
+
+ private void loadUserDns( Group group ) throws SecurityException
+ {
+ if( VUtil.isNotNullOrEmpty( group.getMembers() ))
+ {
+ ReviewMgr reviewMgr = ReviewMgrFactory.createInstance();
+ List<String> userDns = new ArrayList<>();
+ for( String member : group.getMembers() )
+ {
+ User user = reviewMgr.readUser( new User( member ) );
+ userDns.add( user.getDn() );
+ }
+ group.setMembers( userDns );
+ }
+ }
+
+ private void loadUserDn( User inUser ) throws SecurityException
+ {
+ ReviewMgr reviewMgr = ReviewMgrFactory.createInstance();
+ String userDns;
+ User outUser = reviewMgr.readUser( inUser );
+ inUser.setDn( outUser.getDn() );
+ }
+}
\ 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/ldap/group/GroupP.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/ldap/group/GroupP.java b/src/main/java/org/apache/directory/fortress/core/ldap/group/GroupP.java
new file mode 100755
index 0000000..c311443
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/ldap/group/GroupP.java
@@ -0,0 +1,213 @@
+/*
+ * 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.ldap.group;
+
+
+import org.apache.directory.fortress.core.ValidationException;
+import org.apache.directory.fortress.core.rbac.User;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.directory.fortress.core.GlobalErrIds;
+import org.apache.directory.fortress.core.GlobalIds;
+import org.apache.directory.fortress.core.SecurityException;
+import org.apache.directory.fortress.core.util.attr.VUtil;
+
+import java.util.List;
+
+
+/**
+ * Process module for the group node of Fortress directory structure.
+ * This class is thread safe.
+ *
+ * @author Shawn McKinney
+ */
+final class GroupP
+{
+ private static final String CLS_NM = GroupP.class.getName();
+ private static final Logger LOG = LoggerFactory.getLogger( CLS_NM );
+ private static GroupDAO gDao = new GroupDAO();
+
+ /**
+ * Add a group node to the Directory Information Tree (DIT).
+ *
+ * @param group contains the group entity for target node.
+ * @throws org.apache.directory.fortress.core.SecurityException
+ * in event of validation or system error.
+ */
+ final Group add( Group group ) throws SecurityException
+ {
+ validate( group );
+ return gDao.create( group );
+ }
+
+ /**
+ * Modify a group node within the Directory Information Tree (DIT).
+ *
+ * @param group contains the group entity for target node.
+ * @throws org.apache.directory.fortress.core.SecurityException
+ * in event of validation or system error.
+ */
+ final Group update( Group group ) throws SecurityException
+ {
+ validate( group );
+ return gDao.update( group );
+ }
+
+ /**
+ * Remove the group node.
+ *
+ * @param group contains the group entity for target node.
+ * @throws SecurityException in event of validation or system error.
+ */
+ final Group delete( Group group ) throws SecurityException
+ {
+ return gDao.remove( group );
+ }
+
+ /**
+ * Add a new property to an existing Group
+ *
+ * @param group
+ * @param key
+ * @param value
+ * @return
+ * @throws org.apache.directory.fortress.core.SecurityException
+ *
+ */
+ final Group add( Group group, String key, String value ) throws SecurityException
+ {
+ return gDao.add( group, key, value );
+ }
+
+ /**
+ * Remove an existing property value from an existing Group
+ *
+ * @param group
+ * @param key
+ * @param value
+ * @return
+ * @throws org.apache.directory.fortress.core.SecurityException
+ *
+ */
+ final Group delete( Group group, String key, String value ) throws SecurityException
+ {
+ return gDao.delete( group, key, value );
+ }
+
+ /**
+ * Method will add the "member" attribute on LDAP entry which represents a Group assignment.
+ *
+ * @param entity contains the group name targeted.
+ * @param userDn String contains the dn for the user entry that is being assigned the RBAC Role.
+ * @return Group containing copy of input data.
+ * @throws SecurityException in the event of data validation or DAO system error.
+ */
+ final Group assign( Group entity, String userDn ) throws SecurityException
+ {
+ return gDao.assign( entity, userDn );
+ }
+
+ /**
+ * Method will remove the "member" attribute on LDAP entry which represents a Group assignment.
+ *
+ * @param entity contains the role name targeted.
+ * @param userDn String contains the dn for the user entry that is being assigned the RBAC Role.
+ * @return Role containing copy of input data.
+ * @throws SecurityException in the event of data validation or DAO system error.
+ */
+ final Group deassign( Group entity, String userDn ) throws SecurityException
+ {
+ return gDao.deassign( entity, userDn );
+ }
+
+ /**
+ * Return a fully populated Group entity for a given name. If matching record not found a
+ * SecurityException will be thrown.
+ *
+ * @param group contains full group name for entry in directory.
+ * @return Group entity containing all attributes associated.
+ * @throws SecurityException in the event not found or DAO search error.
+ */
+ final Group read( Group group ) throws SecurityException
+ {
+ return gDao.get( group );
+ }
+
+ /**
+ * Takes a search string that contains full or partial Group name in directory.
+ *
+ * @param group contains full or partial name.
+ * @return List of type Group containing fully populated matching entities. If no records found this will be empty.
+ * @throws SecurityException in the event of DAO search error.
+ */
+ final List<Group> search( Group group ) throws SecurityException
+ {
+ return gDao.find( group );
+ }
+
+ /**
+ * Takes a search string that contains full or partial Group name in directory.
+ *
+ * @param user contains full dn for existing user.
+ * @return List of type Group containing fully populated matching entities. If no records found this will be empty.
+ * @throws SecurityException in the event of DAO search error.
+ */
+ final List<Group> search( User user ) throws SecurityException
+ {
+ return gDao.find( user );
+ }
+
+ /**
+ * Method will perform simple validations to ensure the integrity of the {@link Group} entity targeted for insertion
+ * or deletion in directory.
+ *
+ * @param entity contains the enum type to validate
+ * @throws org.apache.directory.fortress.core.SecurityException
+ * thrown in the event the attribute is null.
+ */
+ private void validate( Group entity ) throws SecurityException
+ {
+ if ( !VUtil.isNotNullOrEmpty( entity.getName() ) )
+ {
+ String error = "validate name validation failed, null or empty value";
+ LOG.warn( error );
+ throw new ValidationException( GlobalErrIds.GROUP_NAME_NULL, error );
+ }
+ if ( entity.getName().length() > GlobalIds.OU_LEN )
+ {
+ String name = entity.getName();
+ String error = "validate name [" + name + "] invalid length [" + entity.getName().length() + "]";
+ LOG.warn( error );
+ throw new ValidationException( GlobalErrIds.GROUP_NAME_INVLD, error );
+ }
+ if ( entity.getProtocol().length() > GlobalIds.OU_LEN )
+ {
+ String error = "validate protocol [" + entity.getProtocol() + "] invalid length [" + entity.getProtocol()
+ .length() + "]";
+ LOG.warn( error );
+ throw new ValidationException( GlobalErrIds.GROUP_PROTOCOL_INVLD, error );
+ }
+ if ( VUtil.isNotNullOrEmpty( entity.getDescription() ) )
+ {
+ VUtil.description( entity.getDescription() );
+ }
+ }
+}
\ 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/ldap/group/package.html
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/ldap/group/package.html b/src/main/java/org/apache/directory/fortress/core/ldap/group/package.html
new file mode 100755
index 0000000..28db54b
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/ldap/group/package.html
@@ -0,0 +1,33 @@
+<!--
+ * 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.
+ *
+-->
+<html>
+ <head>
+ <title>Package Documentation for org.apache.directory.fortress.ldap.group</title>
+ </head>
+ <body>
+ <p>
+ This package contains APIs to perform create and teardown the ldap group node.
+ </p>
+ <p>
+ The <b>org.apache.directory.fortress.ldap.group</b> package provides apis to add and remove group node, <b>dcObject</b>.
+ The group node is common throughout ldap operartions and is commonly used to define sets of users or other data types.
+ </p>
+ </body>
+</html>