blob: 3ddb83a57872f002ec16131b1c2a05038d76a7c0 [file] [log] [blame]
/*
* 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.impl;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.apache.directory.api.ldap.model.constants.SchemaConstants;
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.fortress.core.CreateException;
import org.apache.directory.fortress.core.FinderException;
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.UpdateException;
import org.apache.directory.fortress.core.ldap.LdapDataProvider;
import org.apache.directory.fortress.core.model.*;
import org.apache.directory.fortress.core.util.Config;
import org.apache.directory.fortress.core.util.PropUtil;
import org.apache.directory.ldap.client.api.LdapConnection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Contains the Group node for LDAP Directory Information Tree.
* This class is thread safe.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
final class GroupDAO extends LdapDataProvider implements PropertyProvider<Group>
{
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 String GROUP_OBJECT_CLASS_IMPL;
private static final String GROUP_PROTOCOL_ATTR = "group.protocol";
private String GROUP_PROTOCOL_ATTR_IMPL;
private static final String GROUP_PROPERTY_ATTR = "group.properties";
private String GROUP_PROPERTY_ATTR_IMPL;
private String[] GROUP_OBJ_CLASS;
private String[] GROUP_ATRS;
/**
* Package private default constructor.
*/
GroupDAO()
{
super();
GROUP_OBJECT_CLASS_IMPL = Config.getInstance().getProperty( GROUP_OBJECT_CLASS );
GROUP_PROTOCOL_ATTR_IMPL = Config.getInstance().getProperty( GROUP_PROTOCOL_ATTR );
GROUP_PROPERTY_ATTR_IMPL = Config.getInstance().getProperty( GROUP_PROPERTY_ATTR );
GROUP_OBJ_CLASS = new String[]{SchemaConstants.TOP_OC, GROUP_OBJECT_CLASS_IMPL };
GROUP_ATRS = new String[]
{
SchemaConstants.CN_AT,
SchemaConstants.DESCRIPTION_AT,
GlobalIds.TYPE,
GROUP_PROTOCOL_ATTR_IMPL,
GROUP_PROPERTY_ATTR_IMPL,
SchemaConstants.MEMBER_AT };
}
/**
* @param group
* @throws org.apache.directory.fortress.core.CreateException
*
*/
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( SchemaConstants.OBJECT_CLASS_AT, GROUP_OBJ_CLASS );
myEntry.add( SchemaConstants.CN_AT, group.getName() );
// protocol is required:
myEntry.add( GROUP_PROTOCOL_ATTR_IMPL, group.getProtocol() );
// type is required:
myEntry.add( GlobalIds.TYPE, group.getType().toString() );
loadAttrs( group.getMembers(), myEntry, SchemaConstants.MEMBER_AT );
loadProperties( group.getProperties(), myEntry, GROUP_PROPERTY_ATTR_IMPL, '=' );
if ( StringUtils.isNotEmpty( group.getDescription() ) )
{
myEntry.add( SchemaConstants.DESCRIPTION_AT, group.getDescription() );
}
ld = getAdminConnection();
add( ld, myEntry );
}
catch ( LdapException e )
{
String error = "create group node dn [" + nodeDn + "] caught LDAPException=" + e;
throw new CreateException( GlobalErrIds.GROUP_ADD_FAILED, error, e );
}
finally
{
closeAdminConnection( ld );
}
return group;
}
/**
* @param group
* @return
* @throws org.apache.directory.fortress.core.CreateException
*
*/
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 ( StringUtils.isNotEmpty( group.getDescription() ) )
{
mods.add( new DefaultModification(
ModificationOperation.REPLACE_ATTRIBUTE, SchemaConstants.DESCRIPTION_AT, group.getDescription() ) );
}
if ( StringUtils.isNotEmpty( group.getProtocol() ) )
{
mods.add( new DefaultModification(
ModificationOperation.REPLACE_ATTRIBUTE, GROUP_PROTOCOL_ATTR_IMPL, group.getProtocol() ) );
}
loadAttrs( group.getMembers(), mods, SchemaConstants.MEMBER_AT );
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;
throw new UpdateException( GlobalErrIds.GROUP_UPDATE_FAILED, error, e );
}
finally
{
closeAdminConnection( ld );
}
return get( group );
}
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;
throw new CreateException( GlobalErrIds.GROUP_ADD_PROPERTY_FAILED, error, e );
}
finally
{
closeAdminConnection( ld );
}
return get( group );
}
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;
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
*
*/
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();
delete( ld, nodeDn, group );
}
catch ( LdapException e )
{
String error = "remove group node dn [" + nodeDn + "] caught LDAPException=" + e;
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
*
*/
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, SchemaConstants.MEMBER_AT, userDn ) );
ld = getAdminConnection();
modify( ld, dn, mods, entity );
}
catch ( LdapException e )
{
String error = "assign group name [" + entity.getName() + "] user dn [" + userDn + "] caught " +
"LDAPException=" + e;
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
*
*/
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, SchemaConstants.MEMBER_AT, userDn ) );
ld = getAdminConnection();
modify( ld, dn, mods, entity );
}
catch ( LdapException e )
{
String error = "deassign group name [" + entity.getName() + "] user dn [" + userDn + "] caught " +
"LDAPException=" + e;
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
*
*/
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 );
if ( findEntry == null )
{
String warning = "No Group entry found dn [" + dn + "]";
throw new FinderException( GlobalErrIds.GROUP_NOT_FOUND, warning );
}
entity = unloadLdapEntry( findEntry, 0 );
}
catch ( LdapNoSuchObjectException e )
{
String warning = "read Obj COULD NOT FIND ENTRY for dn [" + dn + "]";
throw new FinderException( GlobalErrIds.GROUP_NOT_FOUND, warning, e );
}
catch ( LdapException e )
{
String error = "read dn [" + dn + "] LdapException=" + e;
throw new FinderException( GlobalErrIds.GROUP_READ_FAILED, error, e );
}
finally
{
closeAdminConnection( ld );
}
return entity;
}
/**
* @param group
* @return
* @throws org.apache.directory.fortress.core.FinderException
*
*/
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 + ")(" + SchemaConstants.CN_AT + "=" + searchVal
+ "*))";
ld = getAdminConnection();
searchResults = search( ld, groupRoot, SearchScope.ONELEVEL, filter, GROUP_ATRS, false,
Config.getInstance().getInt(GlobalIds.CONFIG_LDAP_MAX_BATCH_SIZE, 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;
throw new FinderException( GlobalErrIds.GROUP_SEARCH_FAILED, error, e );
}
finally
{
closeAdminConnection( ld );
}
return groupList;
}
/**
* @param user
* @return
* @throws org.apache.directory.fortress.core.FinderException
*
*/
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
{
encodeSafeText( user.getUserId(), GlobalIds.USERID_LEN );
filter = GlobalIds.FILTER_PREFIX + GROUP_OBJECT_CLASS_IMPL + ")(" + SchemaConstants.MEMBER_AT + "="
+ user.getDn() + "))";
ld = getAdminConnection();
searchResults = search( ld, groupRoot, SearchScope.ONELEVEL, filter, GROUP_ATRS, false,
Config.getInstance().getInt(GlobalIds.CONFIG_LDAP_MAX_BATCH_SIZE, 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;
throw new FinderException( GlobalErrIds.GROUP_SEARCH_FAILED, error, e );
}
finally
{
closeAdminConnection( ld );
}
return groupList;
}
/**
* @param role
* @return
* @throws org.apache.directory.fortress.core.FinderException
*
*/
List<Group> roleGroups( Role role ) throws FinderException
{
List<Group> groupList = new ArrayList<>();
LdapConnection ld = null;
SearchCursor searchResults;
String groupRoot = getRootDn( role.getContextId(), GlobalIds.GROUP_ROOT );
String filter = null;
try
{
encodeSafeText( role.getName(), GlobalIds.ROLE_LEN );
filter = GlobalIds.FILTER_PREFIX + GROUP_OBJECT_CLASS_IMPL + ")(" + SchemaConstants.MEMBER_AT + "="
+ role.getDn() + "))";
ld = getAdminConnection();
searchResults = search( ld, groupRoot, SearchScope.ONELEVEL, filter, GROUP_ATRS, false,
Config.getInstance().getInt(GlobalIds.CONFIG_LDAP_MAX_BATCH_SIZE, 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;
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, SchemaConstants.CN_AT ) );
entity.setDescription( getAttribute( le, SchemaConstants.DESCRIPTION_AT ) );
String typeAsString = getAttribute( le, GlobalIds.TYPE );
if ( StringUtils.isNotEmpty(typeAsString) )
{
entity.setType( Group.Type.valueOf( typeAsString.toUpperCase() ) );
}
entity.setProtocol( getAttribute( le, GROUP_PROTOCOL_ATTR_IMPL ) );
entity.setMembers( getAttributes( le, SchemaConstants.MEMBER_AT ) );
entity.setMemberDn( true );
entity.setProperties( PropUtil.getProperties( getAttributes( le, GROUP_PROPERTY_ATTR_IMPL ), '=' ) );
entity.setSequenceId( sequence );
return entity;
}
private String getDn( String name, String contextId )
{
return SchemaConstants.CN_AT + "=" + name + "," + getRootDn( contextId, GlobalIds.GROUP_ROOT );
}
@Override
public String getDn( Group entity )
{
return getDn( entity.getName(), entity.getContextId() );
}
@Override
public FortEntity getEntity( Group entity ) throws FinderException
{
return this.get( entity );
}
}