You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by ak...@apache.org on 2005/02/01 00:07:11 UTC

svn commit: r149317 - in incubator/directory/apacheds/trunk/core/src: main/java/org/apache/ldap/server/jndi/JavaLdapSupport.java main/java/org/apache/ldap/server/jndi/ServerContext.java main/java/org/apache/ldap/server/jndi/ServerDirContext.java test/org/apache/ldap/server/jndi/ObjStateFactoryTest.java

Author: akarasulu
Date: Mon Jan 31 15:07:09 2005
New Revision: 149317

URL: http://svn.apache.org/viewcvs?view=rev&rev=149317
Log:
finished off adding support for object and state factories

Added:
    incubator/directory/apacheds/trunk/core/src/test/org/apache/ldap/server/jndi/ObjStateFactoryTest.java
Modified:
    incubator/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/JavaLdapSupport.java
    incubator/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/ServerContext.java
    incubator/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/ServerDirContext.java

Modified: incubator/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/JavaLdapSupport.java
URL: http://svn.apache.org/viewcvs/incubator/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/JavaLdapSupport.java?view=diff&r1=149316&r2=149317
==============================================================================
--- incubator/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/JavaLdapSupport.java (original)
+++ incubator/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/JavaLdapSupport.java Mon Jan 31 15:07:09 2005
@@ -159,16 +159,21 @@
          * objectClass: javaSerializedObject
          */
         entry.put( OBJECTCLASS_ATTR, TOP_ATTR );
+
         entry.put( OBJECTCLASS_ATTR, JOBJECT_ATTR );
+
         entry.put( OBJECTCLASS_ATTR, JCONTAINER_ATTR );
+
         entry.put( OBJECTCLASS_ATTR, JSERIALIZEDOBJ_ATTR );
 
         // Add the javaClassName and javaSerializedData attributes
         entry.put( JCLASSNAME_ATTR, obj.getClass().getName() );
+
         entry.put( JSERIALDATA_ATTR, serialize( obj ) );
 
         // Add all the class names this object can be cast to:
         Class [] classes = obj.getClass().getClasses();
+
         for ( int ii = 0; ii < classes.length; ii++ )
         {
             entry.put( JCLASSNAMES_ATTR, classes[ii].getName() );

Modified: incubator/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/ServerContext.java
URL: http://svn.apache.org/viewcvs/incubator/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/ServerContext.java?view=diff&r1=149316&r2=149317
==============================================================================
--- incubator/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/ServerContext.java (original)
+++ incubator/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/ServerContext.java Mon Jan 31 15:07:09 2005
@@ -18,9 +18,14 @@
 
 
 import java.util.Hashtable;
+import java.io.Serializable;
 import javax.naming.*;
+import javax.naming.spi.DirectoryManager;
+import javax.naming.spi.DirStateFactory;
 import javax.naming.directory.Attributes;
 import javax.naming.directory.SearchControls;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.Attribute;
 import javax.naming.ldap.Control;
 
 import org.apache.ldap.common.exception.LdapNoPermissionException;
@@ -40,15 +45,18 @@
  */
 public abstract class ServerContext implements Context
 {
-    /** */
+    /** property key used for deleting the old RDN on a rename */
     public static final String DELETE_OLD_RDN_PROP = "java.naming.ldap.deleteRDN";
 
     /** The interceptor proxy to the backend nexus */
     private final PartitionNexus nexusProxy;
+
     /** The cloned environment used by this Context */
     private final Hashtable env;
+
     /** The distinguished name of this Context */
     private final LdapName dn;
+
     /** The Principal associated with this context */
     private LdapPrincipal principal;
 
@@ -78,6 +86,7 @@
 
         // set references to cloned env and the proxy
         this.nexusProxy = nexusProxy;
+
         this.env = ( Hashtable ) env.clone();
 
         /* --------------------------------------------------------------------
@@ -86,18 +95,26 @@
          * ------------------------------------------------------------------ */
         if ( ! env.containsKey( Context.PROVIDER_URL ) )
         {
-            throw new ConfigurationException( "Expected property "
-                    + Context.PROVIDER_URL + " but could not find it in env!" );
+            String msg = "Expected property " + Context.PROVIDER_URL;
+
+            msg += " but could not find it in env!";
+
+            throw new ConfigurationException( msg );
         }
 
         url = ( String ) env.get( Context.PROVIDER_URL );
+
         if ( url == null )
         {
-            throw new ConfigurationException( "Expected value for property "
-                    + Context.PROVIDER_URL + " but it was set to null in env!" );
+            String msg = "Expected value for property " + Context.PROVIDER_URL;
+
+            msg += " but it was set to null in env!";
+
+            throw new ConfigurationException( msg );
         }
 
         dn = new LdapName( url );
+
         if ( ! nexusProxy.hasEntry( dn ) )
         {
             throw new NameNotFoundException( dn + " does not exist" );
@@ -115,13 +132,16 @@
      * @param env the environment properties used by this context
      * @param dn the distinguished name of this context
      */
-    protected ServerContext( LdapPrincipal principal, PartitionNexus nexusProxy,
-                          Hashtable env, Name dn )
+    protected ServerContext( LdapPrincipal principal, PartitionNexus nexusProxy, Hashtable env, Name dn )
     {
         this.dn = ( LdapName ) dn.clone();
+
         this.env = ( Hashtable ) env.clone();
+
         this.env.put( PROVIDER_URL, dn.toString() );
+
         this.nexusProxy = nexusProxy;
+
         this.principal = principal;
     }
 
@@ -245,32 +265,20 @@
      */
     public Context createSubcontext( Name name ) throws NamingException
     {
-        /* 
-         * Start building the server side attributes to be added directly to
-         * the backend.
-         * 
-         * The RDN from name can be a multivalued RDN based on more than one
-         * attribute using the '+' AVA concatenator in a name component.  Right
-         * now this code will bomb out because we presume single valued RDNs.
-         * 
-         * TODO Add multivalued RDN handling code 
-         */
         Attributes attributes = new LockableAttributesImpl();
+
         LdapName target = buildTarget( name );
+
         String rdn = name.get( name.size() - 1 );
+
         String rdnAttribute = NamespaceTools.getRdnAttribute( rdn );
+
         String rdnValue = NamespaceTools.getRdnValue( rdn );
 
-        /* 
-         * TODO Add code within the interceptor service managing operational
-         * attributes the ability to add the target user provided DN to the 
-         * attributes before normalization.  The result should have ths same
-         * affect as the following line within the interceptor.
-         * 
-         * attributes.put( BootstrapSchema.DN_ATTR, target.toString() );
-         */
         attributes.put( rdnAttribute, rdnValue );
+
         attributes.put( JavaLdapSupport.OBJECTCLASS_ATTR, JavaLdapSupport.JCONTAINER_ATTR );
+
         attributes.put( JavaLdapSupport.OBJECTCLASS_ATTR, JavaLdapSupport.TOP_ATTR );
         
         /*
@@ -283,8 +291,11 @@
         nexusProxy.add( target.toString(), target, attributes );
         
         ServerLdapContext ctx = new ServerLdapContext( principal, nexusProxy, env, target );
+
         Control [] controls = ( Control [] ) ( ( ServerLdapContext ) this ).getRequestControls().clone();
+
         ctx.setRequestControls( controls );
+
         return ctx;
     }
 
@@ -328,35 +339,90 @@
      */
     public void bind( Name name, Object obj ) throws NamingException
     {
-        if ( obj instanceof ServerLdapContext )
+        // First, use state factories to do a transformation
+        DirStateFactory.Result res = DirectoryManager.getStateToBind( obj, name, this, env, null );
+
+        Attributes outAttrs = res.getAttributes();
+
+        if ( outAttrs != null )
         {
-            throw new IllegalArgumentException( "Cannot bind a directory context object!" );
+            Name target = buildTarget( name );
+
+            nexusProxy.add( target.toString(), target, outAttrs );
+
+            return;
         }
 
-        /* 
-         * Start building the server side attributes to be added directly to
-         * the backend.
-         * 
-         * The RDN from name can be a multivalued RDN based on more than one
-         * attribute using the '+' AVA concatenator in a name component.  Right
-         * now this code will bomb out because we presume single valued RDNs.
-         * 
-         * TODO Add multivalued RDN handling code 
-         */
-        Attributes attributes = new LockableAttributesImpl();
-        Name target = buildTarget( name );
+        // Check for Referenceable
+        if ( obj instanceof Referenceable )
+        {
+            obj = ( ( Referenceable ) obj ).getReference();
 
-        // Serialize object into entry attributes and add it.
-        JavaLdapSupport.serialize( attributes, obj );
-        nexusProxy.add( target.toString(), target, attributes );
+            throw new NamingException( "Do not know how to store Referenceables yet!" );
+        }
+
+        // Store different formats
+        if ( obj instanceof Reference )
+        {
+            // Store as ref and add outAttrs
+
+            throw new NamingException( "Do not know how to store References yet!" );
+        }
+        else if ( obj instanceof Serializable )
+        {
+            // Serialize and add outAttrs
+
+            Attributes attributes = new LockableAttributesImpl();
+
+            if ( outAttrs != null && outAttrs.size() > 0 )
+            {
+                NamingEnumeration list = outAttrs.getAll();
+
+                while ( list.hasMore() )
+                {
+                    attributes.put( ( Attribute ) list.next() );
+                }
+            }
+
+            Name target = buildTarget( name );
+
+            // Serialize object into entry attributes and add it.
+
+            JavaLdapSupport.serialize( attributes, obj );
+
+            nexusProxy.add( target.toString(), target, attributes );
+        }
+        else if ( obj instanceof DirContext )
+        {
+            // Grab attributes and merge with outAttrs
+
+            Attributes attributes = ( ( DirContext ) obj ).getAttributes( "" );
+
+            if ( outAttrs != null && outAttrs.size() > 0 )
+            {
+                NamingEnumeration list = outAttrs.getAll();
+
+                while ( list.hasMore() )
+                {
+                    attributes.put( ( Attribute ) list.next() );
+                }
+            }
+
+            Name target = buildTarget( name );
+
+            nexusProxy.add( target.toString(), target, attributes );
+        }
+        else
+        {
+            throw new NamingException( "Can't find a way to bind: " + obj );
+        }
     }
 
 
     /**
      * @see javax.naming.Context#rename(java.lang.String, java.lang.String)
      */
-    public void rename( String oldName, String newName )
-        throws NamingException
+    public void rename( String oldName, String newName ) throws NamingException
     {
         rename( new LdapName( oldName ), new LdapName( newName ) );
     }
@@ -368,6 +434,7 @@
     public void rename( Name oldName, Name newName ) throws NamingException
     {
         Name oldDn = buildTarget( oldName );
+
         Name newDn = buildTarget( newName );
 
         if ( oldDn.size() == 0 )
@@ -376,9 +443,11 @@
         }
 
         Name oldBase = oldName.getSuffix( 1 );
+
         Name newBase = newName.getSuffix( 1 );
 
         String newRdn = newName.get( newName.size() - 1 );
+
         String oldRdn = oldName.get( oldName.size() - 1 );
                 
         boolean delOldRdn = true;
@@ -390,9 +459,12 @@
         if ( null != env.get( DELETE_OLD_RDN_PROP ) )
         {
             String delOldRdnStr = ( String ) env.get( DELETE_OLD_RDN_PROP );
-            delOldRdn = ! ( delOldRdnStr.equals( "false" ) ||
-                delOldRdnStr.equals( "no" ) ||
-                delOldRdnStr.equals( "0" ) );
+
+            delOldRdn = ! delOldRdnStr.equals( "false" );
+
+            delOldRdn = delOldRdn || delOldRdnStr.equals( "no" );
+
+            delOldRdn = delOldRdn || delOldRdnStr.equals( "0" );
         }
 
         /*
@@ -480,9 +552,26 @@
      */
     public Object lookup( Name name ) throws NamingException
     {
+        Object obj = null;
+
         LdapName target = buildTarget( name );
+
         Attributes attributes = nexusProxy.lookup( target );
-        
+
+        try
+        {
+            obj = DirectoryManager.getObjectInstance( null, name, this, env, attributes );
+        }
+        catch ( Exception e )
+        {
+            throw new NamingException( e.getMessage() );
+        }
+
+        if ( obj != null )
+        {
+            return obj;
+        }
+
         // First lets test and see if the entry is a serialized java object
         if ( attributes.get( JavaLdapSupport.JCLASSNAME_ATTR ) != null )
         {
@@ -495,6 +584,7 @@
             
         // Need to add controls to propagate extended ldap operational env
         Control [] controls = ( ( ServerLdapContext ) this ).getRequestControls();
+
         if ( null != controls )
         {    
             ctx.setRequestControls( ( Control [] ) controls.clone() );
@@ -584,8 +674,11 @@
     {
         // Conduct a special one level search at base for all objects
         Name base = buildTarget( name );
+
         PresenceNode filter = new PresenceNode( "objectClass" );
+
         SearchControls ctls = new SearchControls();
+
         ctls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
 
         return nexusProxy.search( base , getEnvironment(), filter, ctls );
@@ -602,8 +695,7 @@
 
 
     /**
-     * TODO Needs some serious testing here!
-     * @see javax.naming.Context#composeName(javax.naming.Name, 
+     * @see javax.naming.Context#composeName(javax.naming.Name,
      * javax.naming.Name)
      */
     public Name composeName( Name name, Name prefix ) throws NamingException
@@ -631,6 +723,7 @@
          
         // 1). Find the Dn for name and walk it from the head to tail
         Name fqn = buildTarget( name );
+
         String head = prefix.get( 0 );
         
         // 2). Walk the fqn trying to match for the head of the prefix
@@ -646,9 +739,12 @@
                 fqn.remove( 0 );
             }
         }
-        
-        throw new NamingException( "The prefix '" + prefix
-                + "' is not an ancestor of this "  + "entry '" + dn + "'" );
+
+        String msg = "The prefix '" + prefix + "' is not an ancestor of this ";
+
+        msg += "entry '" + dn + "'";
+
+        throw new NamingException( msg );
     }
     
     
@@ -673,6 +769,7 @@
         
         // Add to left hand side of cloned DN the relative name arg
         target.addAll( target.size(), relativeName );
+
         return target;
     }
 }

Modified: incubator/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/ServerDirContext.java
URL: http://svn.apache.org/viewcvs/incubator/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/ServerDirContext.java?view=diff&r1=149316&r2=149317
==============================================================================
--- incubator/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/ServerDirContext.java (original)
+++ incubator/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/ServerDirContext.java Mon Jan 31 15:07:09 2005
@@ -18,11 +18,12 @@
 
 
 import java.io.IOException;
+import java.io.Serializable;
 import java.text.ParseException;
 import java.util.Hashtable;
-import javax.naming.Name;
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
+import javax.naming.*;
+import javax.naming.spi.DirStateFactory;
+import javax.naming.spi.DirectoryManager;
 import javax.naming.directory.*;
 import javax.naming.ldap.Control;
 
@@ -70,8 +71,7 @@
      * @param env the environment properties used by this context
      * @param dn the distinguished name of this context
      */
-    protected ServerDirContext( LdapPrincipal principal, PartitionNexus nexusProxy,
-                             Hashtable env, Name dn )
+    protected ServerDirContext( LdapPrincipal principal, PartitionNexus nexusProxy, Hashtable env, Name dn )
     {
         super( principal, nexusProxy, env, dn );
     }
@@ -104,8 +104,7 @@
      * @see javax.naming.directory.DirContext#getAttributes(java.lang.String,
      *      java.lang.String[])
      */
-    public Attributes getAttributes( String name, String[] attrIds )
-        throws NamingException
+    public Attributes getAttributes( String name, String[] attrIds ) throws NamingException
     {
         return getAttributes( new LdapName( name ), attrIds );
     }
@@ -115,8 +114,7 @@
      * @see javax.naming.directory.DirContext#getAttributes(javax.naming.Name,
      *      java.lang.String[])
      */
-    public Attributes getAttributes( Name name, String[] attrIds )
-        throws NamingException
+    public Attributes getAttributes( Name name, String[] attrIds ) throws NamingException
     {
         return getNexusProxy().lookup( buildTarget( name ), attrIds );
     }
@@ -126,8 +124,7 @@
      * @see javax.naming.directory.DirContext#modifyAttributes(java.lang.String,
      *      int, javax.naming.directory.Attributes)
      */
-    public void modifyAttributes( String name, int modOp, Attributes attrs )
-            throws NamingException
+    public void modifyAttributes( String name, int modOp, Attributes attrs ) throws NamingException
     {
         modifyAttributes( new LdapName( name ), modOp, attrs );
     }
@@ -137,8 +134,7 @@
      * @see javax.naming.directory.DirContext#modifyAttributes(
      * javax.naming.Name,int, javax.naming.directory.Attributes)
      */
-    public void modifyAttributes( Name name, int modOp, Attributes attrs )
-        throws NamingException
+    public void modifyAttributes( Name name, int modOp, Attributes attrs ) throws NamingException
     {
         getNexusProxy().modify( buildTarget( name ), modOp, attrs );
     }
@@ -148,8 +144,7 @@
      * @see javax.naming.directory.DirContext#modifyAttributes(java.lang.String,
      *      javax.naming.directory.ModificationItem[])
      */
-    public void modifyAttributes( String name, ModificationItem[] mods )
-        throws NamingException
+    public void modifyAttributes( String name, ModificationItem[] mods ) throws NamingException
     {
         modifyAttributes( new LdapName( name ), mods );
     }
@@ -159,8 +154,7 @@
      * @see javax.naming.directory.DirContext#modifyAttributes(
      * javax.naming.Name, javax.naming.directory.ModificationItem[])
      */
-    public void modifyAttributes( Name name, ModificationItem[] mods )
-        throws NamingException
+    public void modifyAttributes( Name name, ModificationItem[] mods ) throws NamingException
     {
         getNexusProxy().modify( buildTarget( name ), mods );
     }
@@ -170,8 +164,7 @@
      * @see javax.naming.directory.DirContext#bind(java.lang.String,
      *      java.lang.Object, javax.naming.directory.Attributes)
      */
-    public void bind( String name, Object obj, Attributes attrs )
-        throws NamingException
+    public void bind( String name, Object obj, Attributes attrs ) throws NamingException
     {
         bind( new LdapName( name ), obj, attrs );
     }
@@ -193,26 +186,110 @@
         if ( null == attrs )
         {
             super.bind( name, obj );
+
+            return;
         }
+
         // No object binding so we just add the attributes
-        else if ( null == obj )
+        if ( null == obj )
         {
             Attributes clone = ( Attributes ) attrs.clone();
+
             Name target = buildTarget( name );
+
             getNexusProxy().add( target.toString(), target, clone );
+
+            return;
         }
-        // Need to perform serialization of object into a copy of attrs
-        else 
+
+        // First, use state factories to do a transformation
+        DirStateFactory.Result res = DirectoryManager.getStateToBind( obj, name, this, getEnvironment(), attrs );
+
+        Attributes outAttrs = res.getAttributes();
+
+        if ( outAttrs != attrs )
         {
-            if ( obj instanceof ServerLdapContext )
+            Name target = buildTarget( name );
+
+            Attributes attributes = ( Attributes ) attrs.clone();
+
+            if ( outAttrs != null && outAttrs.size() > 0 )
             {
-                throw new IllegalArgumentException( "Cannot bind a directory context object!" );
+                NamingEnumeration list = outAttrs.getAll();
+
+                while ( list.hasMore() )
+                {
+                    attributes.put( ( Attribute ) list.next() );
+                }
+            }
+
+            getNexusProxy().add( target.toString(), target, attributes );
+
+            return;
+        }
+
+        // Check for Referenceable
+        if ( obj instanceof Referenceable )
+        {
+            obj = ( ( Referenceable ) obj ).getReference();
+
+            throw new NamingException( "Do not know how to store Referenceables yet!" );
+        }
+
+        // Store different formats
+        if ( obj instanceof Reference )
+        {
+            // Store as ref and add outAttrs
+
+            throw new NamingException( "Do not know how to store References yet!" );
+        }
+        else if ( obj instanceof Serializable )
+        {
+            // Serialize and add outAttrs
+
+            Attributes attributes = ( Attributes ) attrs.clone();
+
+            if ( outAttrs != null && outAttrs.size() > 0 )
+            {
+                NamingEnumeration list = outAttrs.getAll();
+
+                while ( list.hasMore() )
+                {
+                    attributes.put( ( Attribute ) list.next() );
+                }
             }
 
-            Attributes clone = ( Attributes ) attrs.clone();
-            JavaLdapSupport.serialize( clone, obj );
             Name target = buildTarget( name );
-            getNexusProxy().add( target.toString(), target, clone );
+
+            // Serialize object into entry attributes and add it.
+
+            JavaLdapSupport.serialize( attributes, obj );
+
+            getNexusProxy().add( target.toString(), target, attributes );
+        }
+        else if ( obj instanceof DirContext )
+        {
+            // Grab attributes and merge with outAttrs
+
+            Attributes attributes = ( ( DirContext ) obj ).getAttributes( "" );
+
+            if ( outAttrs != null && outAttrs.size() > 0 )
+            {
+                NamingEnumeration list = outAttrs.getAll();
+
+                while ( list.hasMore() )
+                {
+                    attributes.put( ( Attribute ) list.next() );
+                }
+            }
+
+            Name target = buildTarget( name );
+
+            getNexusProxy().add( target.toString(), target, attributes );
+        }
+        else
+        {
+            throw new NamingException( "Can't find a way to bind: " + obj );
         }
     }
 
@@ -221,8 +298,7 @@
      * @see javax.naming.directory.DirContext#rebind(java.lang.String,
      *      java.lang.Object, javax.naming.directory.Attributes)
      */
-    public void rebind( String name, Object obj, Attributes attrs )
-        throws NamingException
+    public void rebind( String name, Object obj, Attributes attrs ) throws NamingException
     {
         rebind( new LdapName( name ), obj, attrs );
     }
@@ -249,8 +325,7 @@
      * @see javax.naming.directory.DirContext#createSubcontext(java.lang.String,
      *      javax.naming.directory.Attributes)
      */
-    public DirContext createSubcontext( String name, Attributes attrs )
-        throws NamingException
+    public DirContext createSubcontext( String name, Attributes attrs ) throws NamingException
     {
         return createSubcontext( new LdapName( name ), attrs );
     }
@@ -260,25 +335,31 @@
      * @see javax.naming.directory.DirContext#createSubcontext(
      * javax.naming.Name, javax.naming.directory.Attributes)
      */
-    public DirContext createSubcontext( Name name, Attributes attrs )
-        throws NamingException
+    public DirContext createSubcontext( Name name, Attributes attrs ) throws NamingException
     {
         if ( null == attrs )
         {
             return ( DirContext ) super.createSubcontext( name );
         }
 
-        // @todo again note that we presume single attribute name components
         LdapName target = buildTarget( name );
+
         String rdn = name.get( name.size() - 1 );
+
         String rdnAttribute = NamespaceTools.getRdnAttribute( rdn );
+
         String rdnValue = NamespaceTools.getRdnValue( rdn );
 
         // Clone the attributes and add the Rdn attributes
         Attributes attributes = ( Attributes ) attrs.clone();
-        if ( attributes.get( rdnAttribute ) == null ||
-             attributes.get( rdnAttribute ).size() == 0 ||
-            ( ! attributes.get( rdnAttribute ).contains( rdnValue ) ) )
+
+        boolean doRdnPut = attributes.get( rdnAttribute ) == null;
+
+        doRdnPut = doRdnPut || attributes.get( rdnAttribute ).size() == 0;
+
+        doRdnPut = doRdnPut || ! attributes.get( rdnAttribute ).contains( rdnValue );
+
+        if ( doRdnPut )
         {
             attributes.put( rdnAttribute, rdnValue );
         }
@@ -287,10 +368,10 @@
         getNexusProxy().add( target.toString(), target, attributes );
 
         // Initialize the new context
-        ServerLdapContext ctx = new ServerLdapContext( getPrincipal(), getNexusProxy(),
-                getEnvironment(), target );
+        ServerLdapContext ctx = new ServerLdapContext( getPrincipal(), getNexusProxy(), getEnvironment(), target );
 
         Control [] controls = ( ( ServerLdapContext ) this ).getRequestControls();
+
         if ( controls != null )
         {
         	controls = ( Control[] ) controls.clone();
@@ -301,31 +382,22 @@
         }
 
         ctx.setRequestControls( controls );
+
         return ctx;
     }
 
 
     /**
      * Presently unsupported operation!
-     *
-     * @param name TODO
-     * @return TODO
-     * @throws NamingException all the time.
-     * @see javax.naming.directory.DirContext#getSchema(javax.naming.Name)
      */
     public DirContext getSchema( Name name ) throws NamingException
     {
         throw new UnsupportedOperationException();
     }
-    
+
 
     /**
      * Presently unsupported operation!
-     * 
-     * @param name TODO
-     * @return TODO
-     * @throws NamingException all the time.
-     * @see javax.naming.directory.DirContext#getSchema(java.lang.String)
      */
     public DirContext getSchema( String name ) throws NamingException
     {
@@ -335,12 +407,6 @@
 
     /**
      * Presently unsupported operation!
-     * 
-     * @param name TODO
-     * @return TODO
-     * @throws NamingException all the time.
-     * @see javax.naming.directory.DirContext#getSchemaClassDefinition(
-     * javax.naming.Name)
      */
     public DirContext getSchemaClassDefinition( Name name ) throws NamingException
     {
@@ -350,12 +416,6 @@
 
     /**
      * Presently unsupported operation!
-     * 
-     * @param name TODO
-     * @return TODO
-     * @throws NamingException all the time.
-     * @see javax.naming.directory.DirContext#getSchemaClassDefinition(
-     * java.lang.String)
      */
     public DirContext getSchemaClassDefinition( String name ) throws NamingException
     {
@@ -394,27 +454,20 @@
      * @see javax.naming.directory.DirContext#search(java.lang.String,
      *      javax.naming.directory.Attributes, java.lang.String[])
      */
-    public NamingEnumeration search( String name, Attributes matchingAttributes,
-                                     String[] attributesToReturn )
-        throws NamingException
+    public NamingEnumeration search( String name, Attributes matchingAttributes, String[] attributesToReturn ) throws NamingException
     {
-        return search( new LdapName( name ), matchingAttributes,
-            attributesToReturn );
+        return search( new LdapName( name ), matchingAttributes, attributesToReturn );
     }
 
 
     /**
-     * TODO may need to refactor some of this functionality into a filter 
-     * utility class in commons.
-     * 
      * @see javax.naming.directory.DirContext#search(javax.naming.Name,
      *      javax.naming.directory.Attributes, java.lang.String[])
      */
-    public NamingEnumeration search( Name name, Attributes matchingAttributes,
-                                     String[] attributesToReturn )
-        throws NamingException
+    public NamingEnumeration search( Name name, Attributes matchingAttributes, String[] attributesToReturn ) throws NamingException
     {
         SearchControls ctls = new SearchControls();
+
         LdapName target = buildTarget( name );
 
         // If we need to return specific attributes add em to the SearchControls
@@ -427,6 +480,7 @@
         if ( null == matchingAttributes || matchingAttributes.size() <= 0 )
         {
             PresenceNode filter = new PresenceNode( "objectClass" );
+
             return getNexusProxy().search( target , getEnvironment(), filter, ctls );
         }
 
@@ -435,10 +489,13 @@
          * an attribute value assertion within one big AND filter expression.
          */
         Attribute attr = null;
+
         SimpleNode node = null;
+
         BranchNode filter = new BranchNode( BranchNode.AND );
+
         NamingEnumeration list = matchingAttributes.getAll();
-        
+
         // Loop through each attribute value pair
         while ( list.hasMore() )
         {
@@ -452,6 +509,7 @@
             if ( attr.size() == 0 )
             {
                 filter.addNode( new PresenceNode( attr.getID() ) );
+
                 continue;
             }
             
@@ -467,6 +525,7 @@
                 if ( val instanceof String )
                 {
                     node = new SimpleNode( attr.getID(), ( String ) val, SimpleNode.EQUALITY );
+
                     filter.addNode( node );
                 }
             }
@@ -495,6 +554,7 @@
             throws NamingException
     {
         ExprNode filterNode = null;
+
         LdapName target = buildTarget( name );
 
         if ( filter == null && getEnvironment().containsKey( "__filter__" ) )
@@ -505,11 +565,8 @@
         {
             try
             {
-                /*
-                 * TODO Added this parser initialization code to the FilterImpl
-                 * and have a static class parser that can be globally accessed.
-                 */
                 FilterParser parser = new FilterParserImpl();
+
                 filterNode = parser.parse( filter );
             }
             catch ( ParseException pe )
@@ -518,7 +575,9 @@
                     new InvalidSearchFilterException (
                     "Encountered parse exception while parsing the filter: '"
                     + filter + "'" );
+
                 isfe.setRootCause( pe );
+
                 throw isfe;
             }
             catch ( IOException ioe )
@@ -548,17 +607,14 @@
 
 
     /**
-     * TODO Factor out the filter variable code into the commons filter pkg &
-     * test it there.
-     * 
      * @see javax.naming.directory.DirContext#search(javax.naming.Name,
      *      java.lang.String, java.lang.Object[],
      *      javax.naming.directory.SearchControls)
      */
-    public NamingEnumeration search( Name name, String filterExpr,
-        Object[] filterArgs, SearchControls cons ) throws NamingException
+    public NamingEnumeration search( Name name, String filterExpr, Object[] filterArgs, SearchControls cons ) throws NamingException
     {
         int start;
+
         StringBuffer buf = new StringBuffer( filterExpr );
         
         // Scan until we hit the end of the string buffer 

Added: incubator/directory/apacheds/trunk/core/src/test/org/apache/ldap/server/jndi/ObjStateFactoryTest.java
URL: http://svn.apache.org/viewcvs/incubator/directory/apacheds/trunk/core/src/test/org/apache/ldap/server/jndi/ObjStateFactoryTest.java?view=auto&rev=149317
==============================================================================
--- incubator/directory/apacheds/trunk/core/src/test/org/apache/ldap/server/jndi/ObjStateFactoryTest.java (added)
+++ incubator/directory/apacheds/trunk/core/src/test/org/apache/ldap/server/jndi/ObjStateFactoryTest.java Mon Jan 31 15:07:09 2005
@@ -0,0 +1,260 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed 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.ldap.server.jndi;
+
+
+import java.util.Hashtable;
+import javax.naming.spi.DirObjectFactory;
+import javax.naming.spi.DirStateFactory;
+import javax.naming.Name;
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.naming.directory.*;
+
+
+/**
+ * Tests to make sure that object and state factories work.
+ *
+ * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory Project</a>
+ * @version $Rev$
+ */
+public class ObjStateFactoryTest extends AbstractJndiTest
+{
+    public void testObjectFactory() throws NamingException
+    {
+        super.sysRoot.addToEnvironment( Context.OBJECT_FACTORIES, PersonObjectFactory.class.getName() );
+
+        Object obj = super.sysRoot.lookup( "uid=akarasulu, ou=users" );
+
+        Attributes attrs = super.sysRoot.getAttributes( "uid=akarasulu, ou=users" );
+
+        assertEquals( Person.class, obj.getClass() );
+
+        Person me = ( Person ) obj;
+
+        assertEquals( attrs.get( "sn" ).get(), me.getLastname() );
+
+        assertEquals( attrs.get( "cn" ).get(), me.getCn() );
+
+        assertEquals( attrs.get( "userPassword" ).get(), me.getPassword() );
+
+        assertEquals( attrs.get( "telephonenumber" ).get(), me.getTelephoneNumber() );
+
+        assertNull( me.getSeealso() );
+
+        assertNull( me.getDescription() );
+    }
+
+
+    public void testStateFactory() throws NamingException
+    {
+        super.sysRoot.addToEnvironment( Context.STATE_FACTORIES, PersonStateFactory.class.getName() );
+
+        Person p = new Person( "Rodriguez", "Mr. Kerberos", "noices", "555-1212", "erodriguez", "committer" );
+
+        super.sysRoot.bind( "uid=erodriguez, ou=users", p );
+
+        Attributes attrs = super.sysRoot.getAttributes( "uid=erodriguez, ou=users" );
+
+        assertEquals( "Rodriguez", attrs.get( "sn" ).get() );
+
+        assertEquals( "Mr. Kerberos", attrs.get( "cn" ).get() );
+
+        assertEquals( "noices", attrs.get( "userPassword" ).get() );
+
+        assertEquals( "555-1212", attrs.get( "telephonenumber" ).get() );
+
+        assertEquals( "erodriguez", attrs.get( "seealso" ).get() );
+
+        assertEquals( "committer", attrs.get( "description" ).get() );
+
+    }
+
+
+    public static class PersonStateFactory implements DirStateFactory
+    {
+        public Result getStateToBind( Object obj, Name name, Context nameCtx, Hashtable environment, Attributes inAttrs ) throws NamingException
+        {
+            // Only interested in Person objects
+            if ( obj instanceof Person )
+            {
+
+                Attributes outAttrs;
+
+                if ( inAttrs == null )
+                {
+                    outAttrs = new BasicAttributes(true);
+                }
+                else
+                {
+                    outAttrs = ( Attributes ) inAttrs.clone();
+                }
+
+                // Set up object class
+                if ( outAttrs.get( "objectclass" ) == null )
+                {
+                    BasicAttribute oc = new BasicAttribute( "objectclass", "person" );
+
+                    oc.add( "top" );
+
+                    outAttrs.put( oc );
+                }
+
+                Person per = ( Person ) obj;
+
+                // mandatory attributes
+                if ( per.getLastname() != null )
+                {
+                    outAttrs.put( "sn", per.getLastname() );
+                }
+                else
+                {
+                    throw new SchemaViolationException( "Person must have surname" );
+                }
+
+                if ( per.getCn() != null )
+                {
+                    outAttrs.put( "cn", per.getCn() );
+                }
+                else
+                {
+                    throw new SchemaViolationException( "Person must have common name" );
+                }
+
+                // optional attributes
+                if ( per.getPassword() != null )
+                {
+                    outAttrs.put( "userPassword", per.getPassword() );
+                }
+                if ( per.getTelephoneNumber() != null )
+                {
+                    outAttrs.put( "telephoneNumber", per.getTelephoneNumber() );
+                }
+                if ( per.getSeealso() != null )
+                {
+                    outAttrs.put( "seeAlso", per.getSeealso() );
+                }
+                if ( per.getDescription() != null )
+                {
+                    outAttrs.put( "description", per.getDescription() );
+                }
+
+                return new DirStateFactory.Result( null, outAttrs );
+            }
+
+            return null;
+        }
+
+
+        public Object getStateToBind( Object obj, Name name, Context nameCtx, Hashtable environment ) throws NamingException
+        {
+            throw new UnsupportedOperationException( "Please use directory support overload with Attributes argument." );
+        }
+    }
+
+    public static class PersonObjectFactory implements DirObjectFactory
+    {
+        public Object getObjectInstance( Object obj, Name name, Context nameCtx, Hashtable environment, Attributes attrs ) throws Exception
+        {
+            // Only interested in Attributes with "person" objectclass
+            // System.out.println("object factory: " + attrs);
+            Attribute oc = (attrs != null ? attrs.get("objectclass") : null);
+            if (oc != null && oc.contains("person")) {
+                Attribute attr;
+            String passwd = null;
+
+            // Extract the password
+            attr = attrs.get("userPassword");
+            if (attr != null) {
+                Object pw = attr.get();
+
+                if ( pw instanceof String )
+                    passwd = ( String ) pw;
+                else
+                    passwd = new String((byte[]) pw);
+            }
+                Person per = new Person(
+                  (String)attrs.get("sn").get(),
+                  (String)attrs.get("cn").get(),
+              passwd,
+                  (attr=attrs.get("telephoneNumber")) != null ? (String)attr.get() : null,
+                  (attr=attrs.get("seealso")) != null ? (String)attr.get() : null,
+                  (attr=attrs.get("description")) != null ? (String)attr.get() : null);
+                return per;
+            }
+            return null;
+        }
+
+
+        public Object getObjectInstance( Object obj, Name name, Context nameCtx, Hashtable environment ) throws Exception
+        {
+            throw new UnsupportedOperationException( "Please use directory support overload with Attributes argument." );
+        }
+    }
+
+
+    public static class Person
+    {
+        private String sn, cn, pwd, tele, seealso, desc;
+
+        public Person( String sn, String cn, String pwd, String tele, String seealso, String desc )
+        {
+            this.sn = sn;
+            this.cn = cn;
+            this.pwd = pwd;
+            this.tele = tele;
+            this.seealso = seealso;
+            this.desc = desc;
+        }
+
+
+        public String getLastname()
+        {
+            return sn;
+        }
+
+
+        public String getCn()
+        {
+            return cn;
+        }
+
+
+        public String getPassword()
+        {
+            return pwd;
+        }
+
+
+        public String getTelephoneNumber()
+        {
+            return tele;
+        }
+
+
+        public String getSeealso()
+        {
+            return seealso;
+        }
+
+
+        public String getDescription()
+        {
+            return desc;
+        }
+    }
+}