Author: kayyagari
Date: Thu Nov 13 02:27:45 2008
New Revision: 713699
URL: http://svn.apache.org/viewvc?rev=713699&view=rev
Log:
o added javadoc
o added many new methods
Modified:
directory/sandbox/kayyagari/apacheds-olm/src/main/java/org/apache/directory/olm/util/LdapPersistenceUtil.java
Modified: directory/sandbox/kayyagari/apacheds-olm/src/main/java/org/apache/directory/olm/util/LdapPersistenceUtil.java
URL: http://svn.apache.org/viewvc/directory/sandbox/kayyagari/apacheds-olm/src/main/java/org/apache/directory/olm/util/LdapPersistenceUtil.java?rev=713699&r1=713698&r2=713699&view=diff
==============================================================================
--- directory/sandbox/kayyagari/apacheds-olm/src/main/java/org/apache/directory/olm/util/LdapPersistenceUtil.java (original)
+++ directory/sandbox/kayyagari/apacheds-olm/src/main/java/org/apache/directory/olm/util/LdapPersistenceUtil.java Thu Nov 13 02:27:45 2008
@@ -19,6 +19,7 @@
*/
package org.apache.directory.olm.util;
+
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
@@ -40,6 +41,7 @@
import org.apache.directory.server.core.entry.DefaultServerEntry;
import org.apache.directory.server.core.entry.ServerEntry;
import org.apache.directory.server.core.entry.ServerModification;
+import org.apache.directory.server.core.filtering.EntryFilteringCursor;
import org.apache.directory.server.schema.registries.AttributeTypeRegistry;
import org.apache.directory.server.schema.registries.ObjectClassRegistry;
import org.apache.directory.server.schema.registries.Registries;
@@ -55,26 +57,33 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+
/**
*
- * TODO LdapPersistenceUtil.
- *
+ * Utility class for persisting/updating the user created/fetched entries using CoreSession API.
+ *
+ * TODO a similar class needs to be created with JNDI interface for the users who don't depend on ADS core library.
+ *
* @author Apache Directory Project
* @version $Rev$, $Date$
*/
public class LdapPersistenceUtil
{
+ /** the session of the user*/
private CoreSession session;
+
private Registries registries;
+
private SyntaxRegistry syntaxRegistry;
+
private AttributeTypeRegistry attrRegistry;
-
- private final static Properties NAME_CLASS_MAP = new Properties();
-
- /** static logger */
+
+ /** the map containing the mapping of Attribut/Objectclass names to corresponding FQCN */
+ private final static Properties NAME_CLASS_MAP = new Properties();
+
private static final Logger LOG = LoggerFactory.getLogger( LdapPersistenceUtil.class );
-
- static
+
+ static
{
try
{
@@ -82,52 +91,89 @@
NAME_CLASS_MAP.load( in );
in.close();
}
- catch( Exception e )
+ catch ( Exception e )
{
+ e.printStackTrace();
LOG.error( "could not load class mappings file classmapping.properties" );
}
}
-
- public LdapPersistenceUtil(){}
-
+
+
+ /**
+ *
+ * Creates an instance of LdapPersistenceUtil.
+ *
+ * @param registries the registries containing schema related info
+ * @param session the session oject of the user
+ */
public LdapPersistenceUtil( Registries registries, CoreSession session )
{
- this.session = session;
- this.registries = registries;
- syntaxRegistry = registries.getSyntaxRegistry();
- attrRegistry = registries.getAttributeTypeRegistry();
+ this.session = session;
+ this.registries = registries;
+ syntaxRegistry = registries.getSyntaxRegistry();
+ attrRegistry = registries.getAttributeTypeRegistry();
}
-
-
+
+
+ /**
+ *
+ * Saves a user created entry in the server.
+ *
+ * @param entry the user created entry
+ * @throws Exception if any problems occur during saving an entry
+ */
public void save( Entry entry ) throws Exception
{
ServerEntry serverEntry = new DefaultServerEntry( registries );
-
+
LdapDN dn = new LdapDN( entry.getDN() );
dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
-
+
serverEntry.setDn( dn );
- serverEntry.add( SchemaConstants.OBJECT_CLASS_AT, entry.getName() );
- Set attributes = entry.getAttributes();
- for( Attribute attr: attributes )
+ addAttributesToServerEntry( entry, serverEntry );
+
+ Iterator itr = entry.getAdditionalEntries();
+ while ( itr.hasNext() )
{
+ addAttributesToServerEntry( itr.next(), serverEntry );
+ }
+
+ session.add( serverEntry );
+ }
+
+
+ /*
+ * get all the Attribute and add them to the ServerEntry
+ */
+ private void addAttributesToServerEntry( Entry olmEntry, ServerEntry serverEntry ) throws Exception
+ {
+ serverEntry.add( SchemaConstants.OBJECT_CLASS_AT, olmEntry.getName() );
+
+ Set attributes = olmEntry.getAttributes();
+ for ( Attribute attr : attributes )
+ {
+ if ( attr.isNoUserModification() )
+ {
+ continue;
+ }
+
boolean isHr = syntaxRegistry.lookup( attr.getSyntax() ).isHumanReadable();
- if( isHr )
+ if ( isHr )
{
- if( attr.isSingleValue() )
+ if ( attr.isSingleValue() )
{
- serverEntry.add( attr.getAttrName(), String.valueOf( attr.getAttrValue() ) );
+ serverEntry.add( attr.getName(), String.valueOf( attr.getValue() ) );
}
else
{
- Iterator values = attr.getAttrValues();
- if( values != null )
+ Iterator values = attr.getValues();
+ if ( values != null )
{
- while( values.hasNext() )
+ while ( values.hasNext() )
{
Object v = values.next();
- serverEntry.add( attr.getAttrName(), String.valueOf( v ) );
+ serverEntry.add( attr.getName(), String.valueOf( v ) );
}
}
}
@@ -135,215 +181,473 @@
else
{
// assuming all non-HR values as byte[]
- serverEntry.add( attr.getAttrName(), ( byte[] ) attr.getAttrValue() );
+ serverEntry.add( attr.getName(), ( byte[] ) attr.getValue() );
}
}
-
- session.add( serverEntry );
}
-
+
+ /**
+ *
+ * Fetches an entry from the server associated with the given DN
+ *
+ * @param dn the distinguished name of entry to be fetched
+ * @return an Entry
+ * @throws Exception if any problems occur while fetching the entry
+ */
public Entry fetch( String dn ) throws Exception
{
return fetch( new LdapDN( dn ) );
}
-
- //FIXME need to support extensible objectclasses
+
+
+ /**
+ * @see #fetch(String)
+ */
public Entry fetch( LdapDN dn ) throws Exception
{
- if( ! dn.isNormalized() )
+ if ( !dn.isNormalized() )
{
dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
}
-
- ClonedServerEntry clonedServerEntry = session.lookup( dn );
-
- if( clonedServerEntry == null )
+
+ ClonedServerEntry clonedServerEntry = null;
+
+ try
+ {
+ clonedServerEntry = session.lookup( dn );
+ }
+ catch ( Exception e )
+ {
+ LOG.error( "No entry found with dn '{}'", dn );
+ }
+
+ if ( clonedServerEntry == null )
{
return null;
}
-
+
ServerEntry serverEntry = clonedServerEntry.getOriginalEntry();
-
+
+ return convertToOlmEntry( serverEntry );
+ }
+
+
+ /*
+ * creates a new OLM Entry object and fills with the data from the given ServerEntry object
+ */
+ private Entry convertToOlmEntry( ServerEntry serverEntry ) throws Exception
+ {
EntryAttribute objectClassAttr = serverEntry.get( SchemaConstants.OBJECT_CLASS_AT );
-
+
Iterator> itr = objectClassAttr.iterator();
-
+
List ocList = new ArrayList();
List ocNameList = new ArrayList();
-
+
ObjectClassRegistry ocRegistry = registries.getObjectClassRegistry();
-
- while( itr.hasNext() )
+
+ while ( itr.hasNext() )
{
String objClassName = ( String ) itr.next().get();
ObjectClass oc = ocRegistry.lookup( objClassName );
- if( oc.isStructural() )
+ if ( !oc.getOid().equals( SchemaConstants.TOP_OC_OID ) )
{
ocList.add( oc );
ocNameList.add( objClassName.toLowerCase() );
}
}
-
- for( ObjectClass oc : ocList )
+
+ for ( ObjectClass oc : ocList )
{
- if( oc.getSuperClasses() != null )
+ if ( oc.getSuperClasses() != null )
{
- for( ObjectClass superOc : oc.getSuperClasses() )
+ for ( ObjectClass superOc : oc.getSuperClasses() )
{
- if( superOc.isStructural() )
+ if ( superOc.isStructural() )
{
ocNameList.remove( superOc.getName().toLowerCase() );
}
}
}
}
-
- System.out.println( "ocNameList: " + ocNameList );
- Entry entry = ( Entry ) getClass( ocNameList.get( 0 ) ).newInstance();
+ if ( LOG.isDebugEnabled() )
+ {
+ LOG.debug( "ocNameList: " + ocNameList );
+ }
+
+ Set additionalEntires = new HashSet();
+
+ Entry parentEntry = null;
+
+ for ( String s : ocNameList )
+ {
+ ObjectClass oc = registries.getObjectClassRegistry().lookup( s );
+ Entry entry = null;
+
+ entry = ( Entry ) getClass( s ).newInstance();
+ loadServerEntry( serverEntry, entry );
+
+ if ( oc.isStructural() ) // one and the only one structural class exists
+ {
+ parentEntry = entry;
+ parentEntry.setDN( serverEntry.getDn().getUpName() );
+ }
+
+ // should be set last to avoid any interception during initialization
+ setEntryInterceptor( entry );
+ }
+
+ for ( Entry e : additionalEntires )
+ {
+ parentEntry.addEntry( e );
+ }
- entry.setDN( serverEntry.getDn().getUpName() );
-
+ return parentEntry;
+ }
+
+
+ /*
+ * copies the attributes present in the ServerEntry to the entry object
+ */
+ private void loadServerEntry( ServerEntry serverEntry, Entry entry ) throws Exception
+ {
Field[] fields = entry.getClass().getDeclaredFields();
-
- Map nameToFieldMap = new HashMap();
- for( Field f : fields )
+
+ Map nameToFieldMap = new HashMap();
+ for ( Field f : fields )
{
f.setAccessible( true );
nameToFieldMap.put( f.getName().toLowerCase(), f );
}
-
+
Set attrTypes = serverEntry.getAttributeTypes();
- for( EntryAttribute attr : serverEntry )
+ for ( EntryAttribute attr : serverEntry )
{
Field f = nameToFieldMap.get( attr.getId() );
-
- if( f == null )
+
+ if ( f == null )
{
continue;
}
-
+
Attribute olmAttr = ( Attribute ) f.get( entry );
-
- if( olmAttr == null )
+
+ if ( olmAttr == null )
{
olmAttr = ( Attribute ) Class.forName( f.getType().getName() ).newInstance();
}
- if( attr.isHR() )
+ if ( attr.isHR() )
{
- if( ! registries.getAttributeTypeRegistry().lookup( attr.getId() ).isSingleValue() )
+ if ( !registries.getAttributeTypeRegistry().lookup( attr.getId() ).isSingleValue() )
{
Iterator> values = attr.getAll();
-
+
Set set = new HashSet();
- while( values.hasNext() )
+ while ( values.hasNext() )
{
set.add( values.next().get() );
}
-
+
// java.util.Set is the common container for all the multi valued attribute values
olmAttr.getClass().getDeclaredMethod( "setValues", Set.class ).invoke( olmAttr, set );
}
else
{
- olmAttr.getClass().getDeclaredMethod( "setValue", olmAttr.getJavaType() ).invoke( olmAttr, attr.get().get() );
+ olmAttr.getClass().getDeclaredMethod( "setValue", olmAttr.getJavaType() ).invoke( olmAttr,
+ convertToCorrectType( attr.get().get(), olmAttr.getJavaType() ) );
}
- ( ( InterceptFieldEnabled ) olmAttr ).setInterceptFieldCallback( new AttributeFieldInterceptor( entry ) );
- f.set( entry, olmAttr );
+
+ }
+ else
+ {
+ olmAttr.getClass().getDeclaredMethod( "setValue", olmAttr.getJavaType() ).invoke( olmAttr,
+ attr.get().get() );
}
+
+ ( ( InterceptFieldEnabled ) olmAttr ).setInterceptFieldCallback( new AttributeFieldInterceptor( entry ) );
+ f.set( entry, olmAttr );
}
-
- ( ( InterceptFieldEnabled ) entry ).setInterceptFieldCallback( new EntryFieldInterceptor() );
- return entry;
}
-
-
- public void update( Entry entry ) throws Exception
+
+
+ /**
+ *
+ * updates the given entry.
+ *
+ * @param entry the entry to be updated
+ * @throws Exception if any problems occur during modify operation
+ */
+ public void modify( Entry entry ) throws Exception
{
- ServerEntry serverEntry = new DefaultServerEntry( registries );
-
LdapDN dn = new LdapDN( entry.getDN() );
dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
-
- serverEntry.setDn( dn );
-// serverEntry.add( SchemaConstants.OBJECT_CLASS_AT, entry.getName() );
- EntryFieldInterceptor interceptor = ( EntryFieldInterceptor ) ( ( InterceptFieldEnabled ) entry ).getInterceptFieldCallback();
-
- if( ! interceptor.isDirty() )
+ List modList = new ArrayList();
+
+ EntryFieldInterceptor interceptor = getEntryInterceptor( entry );
+
+ // get the mod items from the main structural entry
+ if ( interceptor.isDirty() )
{
- LOG.debug( "None of the Attributes of Entry changed no need to update" );
- return;
+ collectModItemsFromEntry( entry, interceptor, modList );
+ }
+
+ Iterator itr = entry.getAdditionalEntries();
+ while ( itr.hasNext() )
+ {
+ Entry e = itr.next();
+ interceptor = getEntryInterceptor( e );
+ if ( interceptor == null ) // for a newly added entry the interceptor will be null
+ {
+ EntryAttribute tmpAttr = new DefaultServerAttribute( attrRegistry
+ .lookup( SchemaConstants.OBJECT_CLASS_AT ), e.getName() );
+ Modification mod = new ServerModification( ModificationOperation.ADD_ATTRIBUTE, tmpAttr );
+ modList.add( mod );
+
+ for ( Attribute attr : e.getAttributes() )
+ {
+ tmpAttr = convertToEntryAttribute( attr );
+ mod = new ServerModification( ModificationOperation.ADD_ATTRIBUTE, tmpAttr );
+ modList.add( mod );
+ }
+ }
+ else
+ {
+ collectModItemsFromEntry( e, interceptor, modList );
+ }
}
-
+
+ // then check the dirty *field* map for possible addition of new object classes for adding
+ // Map dirtyFieldMap = interceptor.getDirtyFieldMap();
+ // if( ! dirtyFieldMap.isEmpty() )
+ // {
+ // Set oldEntries = ( Set ) dirtyFieldMap.get( "additionalEntries" );
+ // }
+
+ session.modify( dn, modList );
+ }
+
+
+ /**
+ *
+ * adds an Attribute to an exisitng entry.
+ *
+ * @param dn the DN of existing entry
+ * @param attributeName name of the attribute to be added
+ * @param values one or more values of the attribute to be added
+ * @throws Exception if the attribute cannot be added
+ */
+ public void addAttributeToEntry( LdapDN dn, String attributeName, Object... values ) throws Exception
+ {
+ List modList = new ArrayList( 1 );
+
+ Modification mod = new ServerModification();
+ mod.setOperation( ModificationOperation.ADD_ATTRIBUTE );
+ EntryAttribute attr = new DefaultServerAttribute( attrRegistry.lookup( attributeName ) );
+ mod.setAttribute( attr );
+
+ for ( Object obj : values )
+ {
+ if ( obj == null )
+ {
+ throw new NullPointerException( "Null value for attribute " + attributeName );
+ }
+
+ if ( obj instanceof byte[] )
+ {
+ attr.add( ( byte[] ) obj );
+ }
+ else
+ {
+ attr.add( String.valueOf( obj ) );
+ }
+ }
+
+ modList.add( mod );
+
+ session.modify( dn, modList );
+ }
+
+
+ /**
+ *
+ * replaces an attributes value Or removes an attribute from the entry associated with the given dn.
+ *
+ * @param dn the DN of the entry to be modified
+ * @param attributeName the attribute's name
+ * @param obj value to be replaced, if it is null the attribute will be completely removed from entry
+ * @throws Exception if there are problems in modifying the entry
+ */
+ public void replaceOrRemove( LdapDN dn, String attributeName, Object obj ) throws Exception
+ {
List modList = new ArrayList();
-
+
+ Modification mod = new ServerModification();
+ EntryAttribute attr;
+
+ if ( obj == null )
+ {
+ mod.setOperation( ModificationOperation.REMOVE_ATTRIBUTE );
+ attr = new DefaultServerAttribute( attrRegistry.lookup( attributeName ) );
+ }
+ else
+ {
+ mod.setOperation( ModificationOperation.REPLACE_ATTRIBUTE );
+
+ if ( obj instanceof byte[] )
+ {
+ attr = new DefaultServerAttribute( attrRegistry.lookup( attributeName ), ( byte[] ) obj );
+ }
+ else
+ {
+ attr = new DefaultServerAttribute( attrRegistry.lookup( attributeName ), String.valueOf( obj ) );
+ }
+ }
+
+ mod.setAttribute( attr );
+ modList.add( mod );
+
+ session.modify( dn, modList );
+ }
+
+
+ /**
+ *
+ * searches the server with the given filter.
+ *
+ * @param dn the DN on/under which the search should be performed
+ * @param filter the search filter expression
+ * @return a list of entries
+ * @throws Exception if the search fails
+ */
+ public List search( LdapDN dn, String filter ) throws Exception
+ {
+ List entries = new ArrayList();
+
+ EntryFilteringCursor cursor = session.search( dn, filter );
+
+ while ( cursor.next() )
+ {
+ ServerEntry serverEntry = cursor.get().getOriginalEntry();
+ entries.add( convertToOlmEntry( serverEntry ) );
+ }
+
+ return entries;
+ }
+
+
+ public void modifyDN( LdapDN dn, LdapDN newParent ) throws Exception
+ {
+ session.move( dn, newParent );
+ }
+
+
+ public void delete( String dn ) throws Exception
+ {
+ if ( dn == null )
+ {
+ return;
+ }
+
+ delete( new LdapDN( dn ) );
+ }
+
+
+ public void delete( LdapDN dn ) throws Exception
+ {
+ if ( dn == null )
+ {
+ return;
+ }
+
+ if ( !dn.isNormalized() )
+ {
+ dn.normalize( attrRegistry.getNormalizerMapping() );
+ }
+
+ session.delete( dn );
+ }
+
+
+ /*
+ * created ModItems based on the dirty status of fields present in the given entry
+ */
+ private void collectModItemsFromEntry( Entry entry, EntryFieldInterceptor interceptor, List modList )
+ throws Exception
+ {
Map dirtyMap = interceptor.getDirtyAttrMap();
Class entryClass = entry.getClass();
-
- for( String fieldName : dirtyMap.keySet() )
+
+ for ( String fieldName : dirtyMap.keySet() )
{
- Field f = entryClass.getDeclaredField( fieldName );
- // TODO need to remove this if block, this is for finding errors related to fieldnames during development
- if( f == null )
+ Field f = null;
+ f = entryClass.getDeclaredField( fieldName );
+ if ( f == null )
{
- throw new Exception( "Attribute field not found with name " + fieldName );
+ continue; // TODO need to add support for adding DSA params like timestamp, modifiedUser etc.. as these fields won't exist in any objclass definition
}
-
+
f.setAccessible( true );
-
+
Attribute newAttr = ( Attribute ) f.get( entry );
Attribute oldAttr = dirtyMap.get( fieldName );
- if( newAttr == null ) // remove
+ if ( newAttr == null ) // remove
{
- EntryAttribute tmpAttr = convertToEntryAttribute( oldAttr );
+ EntryAttribute tmpAttr = new DefaultServerAttribute( attrRegistry.lookup( oldAttr.getName() ) );
Modification mod = new ServerModification( ModificationOperation.REMOVE_ATTRIBUTE, tmpAttr );
modList.add( mod );
}
- else if( oldAttr != null && newAttr != null ) // replace
+ else if ( oldAttr != null && newAttr != null ) // replace
{
+ // if attribute cannot be modified by user skip it
+ if ( oldAttr.isNoUserModification() )
+ {
+ continue;
+ }
+
// TODO need to have an efficient way to calculate delta of differences
// for performing the update operation currently it send the whole attribute
EntryAttribute tmpAttr = convertToEntryAttribute( newAttr );
Modification mod = new ServerModification( ModificationOperation.REPLACE_ATTRIBUTE, tmpAttr );
modList.add( mod );
}
- else if( oldAttr == null ) // add
+ else if ( oldAttr == null ) // add
{
EntryAttribute tmpAttr = convertToEntryAttribute( newAttr );
Modification mod = new ServerModification( ModificationOperation.ADD_ATTRIBUTE, tmpAttr );
modList.add( mod );
}
}
-
- session.modify( dn, modList );
}
-
-
-
+
+
+ /*
+ * converts a OLM Attribute to EntryAttribute
+ */
private EntryAttribute convertToEntryAttribute( Attribute attr ) throws Exception
{
- if( attr == null )
+ if ( attr == null )
{
return null;
}
-
- EntryAttribute entryAttr = new DefaultServerAttribute( attrRegistry.lookup( attr.getAttrName() ) );
-
- if( syntaxRegistry.lookup( attr.getSyntax() ).isHumanReadable() )
+
+ EntryAttribute entryAttr = new DefaultServerAttribute( attrRegistry.lookup( attr.getName() ) );
+
+ if ( syntaxRegistry.lookup( attr.getSyntax() ).isHumanReadable() )
{
- if( attr.isSingleValue() )
+ if ( attr.isSingleValue() )
{
- entryAttr.add( String.valueOf( attr.getAttrValue() ) );
+ entryAttr.add( String.valueOf( attr.getValue() ) );
}
else
{
- Iterator itr = attr.getAttrValues();
- while( itr.hasNext() )
+ Iterator itr = attr.getValues();
+ while ( itr.hasNext() )
{
entryAttr.add( String.valueOf( itr.next() ) );
}
@@ -351,16 +655,100 @@
}
else
{
- entryAttr.add( ( byte[] ) attr.getAttrValue() );
+ entryAttr.add( ( byte[] ) attr.getValue() );
}
-
+
return entryAttr;
}
-
+
private Class getClass( String propName ) throws Exception
{
String className = NAME_CLASS_MAP.getProperty( propName );
return Class.forName( className );
}
+
+
+ private EntryFieldInterceptor getEntryInterceptor( Entry entry )
+ {
+ return ( EntryFieldInterceptor ) ( ( InterceptFieldEnabled ) entry ).getInterceptFieldCallback();
+ }
+
+
+ private void setEntryInterceptor( Entry entry )
+ {
+ ( ( InterceptFieldEnabled ) entry ).setInterceptFieldCallback( new EntryFieldInterceptor() );
+ }
+
+
+ private Object convertToCorrectType( Object value, Class claz )
+ {
+ if ( value == null )
+ {
+ return null;
+ }
+
+ if ( claz == String.class )
+ {
+ return String.valueOf( value );
+ }
+ else if ( claz == Integer.class )
+ {
+ return Integer.valueOf( value.toString() );
+ }
+ else if ( claz == Long.class )
+ {
+ return Long.valueOf( value.toString() );
+ }
+ else if ( claz == Boolean.class )
+ {
+ return Boolean.valueOf( value.toString() );
+ }
+ else if ( claz == Short.class )
+ {
+ return Short.valueOf( value.toString() );
+ }
+
+ // this will help during early development to figure out the missing pieces
+ throw new IllegalArgumentException( "Invalid class type " + claz + " for the attribute value " + value );
+ }
+
+
+ /**
+ * @see #exists(LdapDN)
+ */
+ public boolean exists( String dn ) throws Exception
+ {
+ if ( dn == null )
+ {
+ return false;
+ }
+
+ return exists( new LdapDN( dn ) );
+ }
+
+
+ /**
+ *
+ * checks the existene of the given DN.
+ *
+ * @param dn the DN to be checked
+ * @return true if the DN exists, false otherwise
+ * @throws Exception if the search for given DN fails
+ */
+ public boolean exists( LdapDN dn ) throws Exception
+ {
+ if ( dn == null )
+ {
+ return false;
+ }
+
+ if ( !dn.isNormalized() )
+ {
+ dn.normalize( attrRegistry.getNormalizerMapping() );
+ }
+
+ return session.exists( dn );
+ }
+
}