You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2008/08/15 01:12:13 UTC

svn commit: r686082 [2/7] - in /directory: apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ apacheds/branches/bigbang/core-entry/src/test/java/org/apache/directory/server/core/entry/ apacheds/branches/bigbang/c...

Modified: directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/DefaultServerEntry.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/DefaultServerEntry.java?rev=686082&r1=686081&r2=686082&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/DefaultServerEntry.java (original)
+++ directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/DefaultServerEntry.java Thu Aug 14 16:12:09 2008
@@ -19,7 +19,6 @@
 package org.apache.directory.server.core.entry;
 
 
-import java.io.Externalizable;
 import java.io.IOException;
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
@@ -39,6 +38,7 @@
 import org.apache.directory.shared.ldap.entry.Entry;
 import org.apache.directory.shared.ldap.entry.EntryAttribute;
 import org.apache.directory.shared.ldap.entry.Value;
+import org.apache.directory.shared.ldap.entry.client.DefaultClientEntry;
 import org.apache.directory.shared.ldap.name.LdapDN;
 import org.apache.directory.shared.ldap.schema.AttributeType;
 import org.apache.directory.shared.ldap.util.StringTools;
@@ -55,7 +55,7 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-public final class DefaultServerEntry extends AbstractEntry<AttributeType> implements ServerEntry, Externalizable
+public final class DefaultServerEntry extends AbstractEntry<AttributeType> implements ServerEntry
 {
     /** Used for serialization */
     private static final long serialVersionUID = 2L;
@@ -208,6 +208,7 @@
     /* no protection ! */ DefaultServerEntry()
     {
         atRegistry = null;
+        dn = LdapDN.EMPTY_LDAPDN;
     }
 
 
@@ -223,7 +224,8 @@
      */
     public DefaultServerEntry( Registries registries )
     {
-        this.atRegistry = registries.getAttributeTypeRegistry();
+        atRegistry = registries.getAttributeTypeRegistry();
+        dn = LdapDN.EMPTY_LDAPDN;
 
         // Initialize the ObjectClass object
         initObjectClassAT( registries );
@@ -232,6 +234,83 @@
 
     /**
      * <p>
+     * Creates a new instance of DefaultServerEntry, copying 
+     * another entry, which can be a ClientEntry. 
+     * </p>
+     * <p>
+     * No attributes will be created.
+     * </p> 
+     * 
+     * @param registries The reference to the global registries
+     * @param entry the entry to copy
+     */
+    public DefaultServerEntry( Registries registries, Entry entry )
+    {
+        atRegistry = registries.getAttributeTypeRegistry();
+
+        // Initialize the ObjectClass object
+        initObjectClassAT( registries );
+
+        // We will clone the existing entry, because it may be normalized
+        if ( entry.getDn() != null )
+        {
+            dn = (LdapDN)entry.getDn().clone();
+        }
+        else
+        {
+            dn = LdapDN.EMPTY_LDAPDN;
+        }
+        
+        if ( !dn.isNormalized( ) )
+        {
+            try
+            {
+                // The dn must be normalized
+                dn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
+            }
+            catch ( NamingException ne )
+            {
+                LOG.warn( "The DN '" + entry.getDn() + "' cannot be normalized" );
+            }
+        }
+        
+        // Init the attributes map
+        attributes = new HashMap<AttributeType, EntryAttribute>( entry.size() );
+        
+        // and copy all the attributes
+        for ( EntryAttribute attribute:entry )
+        {
+            try
+            {
+                // First get the AttributeType
+                AttributeType attributeType = null;
+
+                if ( attribute instanceof ServerAttribute )
+                {
+                    attributeType = ((ServerAttribute)attribute).getAttributeType();
+                }
+                else
+                {
+                    attributeType = registries.getAttributeTypeRegistry().lookup( attribute.getId() );
+                }
+                
+                // Create a new ServerAttribute.
+                EntryAttribute serverAttribute = new DefaultServerAttribute( attributeType, attribute );
+                
+                // And store it
+                add( serverAttribute );
+            }
+            catch ( NamingException ne )
+            {
+                // Just log a warning
+                LOG.warn( "The attribute '" + attribute.getId() + "' cannot be stored" );
+            }
+        }
+    }
+
+
+    /**
+     * <p>
      * Creates a new instance of DefaultServerEntry, with a 
      * DN and registries. 
      * </p>
@@ -244,8 +323,16 @@
      */
     public DefaultServerEntry( Registries registries, LdapDN dn )
     {
-        this.dn = dn;
-        this.atRegistry = registries.getAttributeTypeRegistry();
+        if ( dn == null )
+        {
+            dn = LdapDN.EMPTY_LDAPDN;
+        }
+        else
+        {
+            this.dn = dn;
+        }
+        
+        atRegistry = registries.getAttributeTypeRegistry();
 
         // Initialize the ObjectClass object
         initObjectClassAT( registries );
@@ -271,8 +358,16 @@
      */
     public DefaultServerEntry( Registries registries, LdapDN dn, AttributeType... attributeTypes )
     {
-        this.dn = dn;
-        this.atRegistry = registries.getAttributeTypeRegistry();
+        if ( dn == null )
+        {
+            dn = LdapDN.EMPTY_LDAPDN;
+        }
+        else
+        {
+            this.dn = dn;
+        }
+
+        atRegistry = registries.getAttributeTypeRegistry();
 
         // Initialize the ObjectClass object
         initObjectClassAT( registries );
@@ -305,8 +400,16 @@
      */
     public DefaultServerEntry( Registries registries, LdapDN dn, AttributeType attributeType, String upId )
     {
-        this.dn = dn;
-        this.atRegistry = registries.getAttributeTypeRegistry();
+        if ( dn == null )
+        {
+            dn = LdapDN.EMPTY_LDAPDN;
+        }
+        else
+        {
+            this.dn = dn;
+        }
+        
+        atRegistry = registries.getAttributeTypeRegistry();
         // Initialize the ObjectClass object
 
         // Initialize the ObjectClass object
@@ -339,8 +442,16 @@
      */
     public DefaultServerEntry( Registries registries, LdapDN dn, String... upIds )
     {
-        this.dn = dn;
-        this.atRegistry = registries.getAttributeTypeRegistry();
+        if ( dn == null )
+        {
+            dn = LdapDN.EMPTY_LDAPDN;
+        }
+        else
+        {
+            this.dn = dn;
+        }
+        
+        atRegistry = registries.getAttributeTypeRegistry();
 
         initObjectClassAT( registries );
 
@@ -363,8 +474,16 @@
      */
     public DefaultServerEntry( Registries registries, LdapDN dn, ServerAttribute... attributes )
     {
-        this.dn = dn;
-        this.atRegistry = registries.getAttributeTypeRegistry();
+        if ( dn == null )
+        {
+            dn = LdapDN.EMPTY_LDAPDN;
+        }
+        else
+        {
+            this.dn = dn;
+        }
+        
+        atRegistry = registries.getAttributeTypeRegistry();
 
         initObjectClassAT( registries );
 
@@ -2115,6 +2234,27 @@
     }
 
 
+    /**
+     * Convert the ServerEntry to a ClientEntry
+     *
+     * @return An instance of ClientEntry
+     */
+    public Entry toClientEntry() throws NamingException
+    {
+        // Copy the DN
+        Entry clientEntry = new DefaultClientEntry( dn );
+        
+        // Convert each attribute 
+        for ( EntryAttribute serverAttribute:this )
+        {
+            EntryAttribute clientAttribute = ((ServerAttribute)serverAttribute).toClientAttribute();
+            clientEntry.add( clientAttribute );
+        }
+        
+        return clientEntry;
+    }
+    
+    
     //-------------------------------------------------------------------------
     // Object methods
     //-------------------------------------------------------------------------
@@ -2154,83 +2294,56 @@
     
 
     /**
-     * @see Externalizable#writeExternal(ObjectOutput)
-     * <p>
+     * @see java.io.Externalizable#writeExternal(ObjectOutput)
      * 
-     * This is the place where we serialize entries, and all theirs
-     * elements. the reason why we don't call the underlying methods
-     * (<code>ServerAttribute.write(), Value.write()</code>) is that we need
-     * access to the registries to read back the values.
-     * <p>
-     * The structure used to store the entry is the following :
-     * <li><b>[DN length]</b> : can be -1 if we don't have a DN, 0 if the 
-     * DN is empty, otherwise contains the DN's length.<p> 
-     * <b>NOTE :</b>This should be unnecessary, as the DN should always exists
-     * <p>
-     * </li>
-     * <li>
-     * <b>DN</b> : The entry's DN. Can be empty (rootDSE=<p>
-     * </li>
-     * We have to store the UPid, and all the values, if any.
+     * We can't use this method for a ServerEntry, as we have to feed the entry
+     * with an registries reference
      */
     public void writeExternal( ObjectOutput out ) throws IOException
     {
+        throw new IllegalStateException( "Cannot use standard serialization for a ServerEntry" );
+    }
+    
+    
+    /**
+     * Serialize a server entry.
+     * 
+     * The structure is the following :
+     * 
+     * <b>[DN]</b> : The entry DN. can be empty
+     * <b>[numberAttr]</b> : the bumber of attributes. Can be 0 
+     * <b>[attribute's oid]*</b> : The attribute's OID to get back 
+     * the attributeType on deserialization
+     * <b>[Attribute]*</b> The attribute
+     * 
+     * @param out the buffer in which the data will be serialized
+     * @throws IOException if the serialization failed
+     */
+    public void serialize( ObjectOutput out ) throws IOException
+    {
         // First, the DN
-        if ( dn == null )
-        {
-            // Write an empty DN
-            LdapDN.EMPTY_LDAPDN.writeExternal( out );
-        }
-        else
-        {
-            // Write the DN
-            dn.writeExternal( out );
-        }
+        // Write the DN
+        out.writeObject( dn );
         
         // Then the attributes. 
-        if ( attributes == null )
-        {
-            out.writeInt( -1 );
-        }
-        else
-        {
-            out.writeInt( attributes.size() );
+        out.writeInt( attributes.size() );
+        
+        // Iterate through the keys. We store the Attribute
+        // here, to be able to restore it in the readExternal :
+        // we need access to the registries, which are not available
+        // in the ServerAttribute class.
+        for ( AttributeType attributeType:attributes.keySet() )
+        {
+            // Write the oid to be able to restore the AttributeType when deserializing
+            // the attribute
+            String oid = attributeType.getOid();
+            out.writeUTF( oid );
             
-            // Iterate through the keys. We store the Attribute
-            // here, to be able to restore it in the readExternal :
-            // we need access to the registries, which are not available
-            // in the ServerAttribute class.
-            for ( AttributeType attributeType:attributes.keySet() )
-            {
-                // We store the OID, as the AttributeType might have no name
-                out.writeUTF( attributeType.getOid() );
-                
-                // And store the attribute.
-                EntryAttribute attribute = attributes.get( attributeType );
-
-                // Store the UP id
-                out.writeUTF( attribute.getUpId() );
-                
-                // The number of values
-                int nbValues = attribute.size();
-                
-                if ( nbValues == 0 ) 
-                {
-                    out.writeInt( 0 );
-                }
-                else 
-                {
-                    out.writeInt( nbValues );
+            // Get the attribute
+            DefaultServerAttribute attribute = (DefaultServerAttribute)attributes.get( attributeType );
 
-                    for ( Value<?> value:attribute )
-                    {
-                        value.writeExternal( out );
-                    }
-                }
-            }
-
-            // Note : we don't store the ObjectClassAttribute. I has already
-            // been stored as an attribute.
+            // Write the attribute
+            attribute.serialize( out );
         }
         
         out.flush();
@@ -2238,46 +2351,54 @@
 
     
     /**
-     * @see Externalizable#readExternal(ObjectInput)
+     * @see java.io.Externalizable#readExternal(ObjectInput)
+     * 
+     * We can't use this method for a ServerEntry, as we have to feed the entry
+     * with an registries reference
      */
     public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException
     {
+        throw new IllegalStateException( "Cannot use standard serialization for a ServerAttribute" );
+    }
+    
+    
+    /**
+     * Deserialize a server entry. 
+     * 
+     * @param in The buffer containing the serialized serverEntry
+     * @throws IOException if there was a problem when deserializing
+     * @throws ClassNotFoundException if we can't deserialize an expected object
+     */
+    public void deserialize( ObjectInput in ) throws IOException, ClassNotFoundException
+    {
         // Read the DN
         dn = (LdapDN)in.readObject();
         
         // Read the number of attributes
         int nbAttributes = in.readInt();
         
-        attributes = new HashMap<AttributeType, EntryAttribute>( nbAttributes );
-
         // Read the attributes
         for ( int i = 0; i < nbAttributes; i++ )
         {
+            // Read the attribute's OID
             String oid = in.readUTF();
             
             try
             {
                 AttributeType attributeType = atRegistry.lookup( oid );
                 
-                ServerAttribute attribute = new DefaultServerAttribute( attributeType );
-                
-                // Read the attribute upID
-                String upId = in.readUTF();
-                attribute.setUpId( upId, attributeType );
-                
-                // Read the number of values
-                int nbValues = in.readInt();
+                // Create the attribute we will read
+                DefaultServerAttribute attribute = new DefaultServerAttribute( attributeType );
                 
-                for ( int j = 0; j < nbValues; j++ )
-                {
-                    Value<?> value = (Value<?>)in.readObject();
-                    attribute.add( value );
-                }
+                // Read the attribute
+                attribute.deserialize( in );
                 
-                attributes.put(  attributeType, attribute );
+                attributes.put( attributeType, attribute );
             }
             catch ( NamingException ne )
             {
+                // We weren't able to find the OID. The attribute will not be added
+                LOG.warn( "Cannot read the attribute as it's OID ('" + oid + "') does not exist" );
                 
             }
         }
@@ -2369,7 +2490,18 @@
         StringBuilder sb = new StringBuilder();
         
         sb.append( "ServerEntry\n" );
-        sb.append( "    dn: " ).append( dn ).append( '\n' );
+        sb.append( "    dn" );
+        
+        if ( dn.isNormalized() )
+        {
+            sb.append( "[n]" );
+        }
+        else
+        {
+            sb.append(  "[]" );
+        }
+        
+        sb.append( ": " ).append( dn ).append( '\n' );
         
         // First dump the ObjectClass attribute
         if ( containsAttribute( OBJECT_CLASS_AT ) )

Modified: directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerAttribute.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerAttribute.java?rev=686082&r1=686081&r2=686082&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerAttribute.java (original)
+++ directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerAttribute.java Thu Aug 14 16:12:09 2008
@@ -22,6 +22,7 @@
 import javax.naming.NamingException;
 import javax.naming.directory.InvalidAttributeValueException;
 
+import org.apache.directory.shared.ldap.entry.EntryAttribute;
 import org.apache.directory.shared.ldap.entry.client.ClientAttribute;
 import org.apache.directory.shared.ldap.schema.AttributeType;
 
@@ -111,4 +112,12 @@
      * @throws NamingException if there is a failure to check syntaxes of values
      */
     boolean isValid() throws NamingException;
+
+
+    /**
+     * Convert the ServerAttribute to a ClientAttribute
+     *
+     * @return An instance of ClientAttribute
+     */
+    EntryAttribute toClientAttribute();
 }

Modified: directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerBinaryValue.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerBinaryValue.java?rev=686082&r1=686081&r2=686082&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerBinaryValue.java (original)
+++ directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerBinaryValue.java Thu Aug 14 16:12:09 2008
@@ -58,8 +58,8 @@
     private static final Logger LOG = LoggerFactory.getLogger( ServerBinaryValue.class );
 
     /** used to dynamically lookup the attributeType when/if deserializing */
-    @SuppressWarnings ( { "FieldCanBeLocal", "UnusedDeclaration" } )
-    private final String oid;
+    //@SuppressWarnings ( { "FieldCanBeLocal", "UnusedDeclaration" } )
+    //private final String oid;
 
     /** reference to the attributeType which is not serialized */
     private transient AttributeType attributeType;
@@ -143,7 +143,6 @@
         }
 
         this.attributeType = attributeType;
-        this.oid = attributeType.getOid();
     }
 
 
@@ -177,7 +176,7 @@
         this.normalizedValue = normalizedValue;
         this.valid = valid;
         this.same = same;
-        this.oid = attributeType.getOid();
+        //this.oid = attributeType.getOid();
     }
 
 
@@ -642,35 +641,86 @@
     /**
      * @see Externalizable#writeExternal(ObjectOutput)
      * 
+     * We can't use this method for a ServerBinaryValue, as we have to feed the value
+     * with an AttributeType object
+     */ 
+    public void writeExternal( ObjectOutput out ) throws IOException
+    {
+        throw new IllegalStateException( "Cannot use standard serialization for a ServerStringValue" );
+    }
+    
+    
+    /**
      * We will write the value and the normalized value, only
      * if the normalized value is different.
      * 
-     * The data will be stored following this structure :
+     * If the value is empty, a flag is written at the beginning with 
+     * the value true, otherwise, a false is written.
      * 
-     *  [UP value]
-     *  [Norm value] (will be null if normValue == upValue)
+     * The data will be stored following this structure :
+     *  [length] the wrapped length. Can be -1, if wrapped is null
+     *  [value length]
+     *  [UP value] if not empty
+     *  [normalized] (will be false if the value can't be normalized)
+     *  [same] (a flag set to true if the normalized value equals the UP value)
+     *  [Norm value] (the normalized value if different from the UP value, and not empty)
+     *  
+     *  @param out the buffer in which we will stored the serialized form of the value
+     *  @throws IOException if we can't write into the buffer
      */
-    public void writeExternal( ObjectOutput out ) throws IOException
+    public void serialize( ObjectOutput out ) throws IOException
     {
-        if ( getReference() != null )
+        if ( wrapped != null )
         {
-            out.writeInt( getReference().length );
-            out.write( getReference() );
+            // write a the wrapped length
+            out.writeInt( wrapped.length );
             
-            if ( same )
+            // Write the data if not empty
+            if ( wrapped.length > 0 )
             {
-                // If the normalized value is equal to the UP value,
-                // don't save it
-                out.writeInt( 0 );
-            }
-            else
-            {
-                out.writeInt( normalizedValue.length );
-                out.write( normalizedValue );
+                // The data
+                out.write( wrapped );
+                
+                // Normalize the data
+                try
+                {
+                    normalize();
+                    
+                    // Write a flag indicating that the data has been normalized
+                    out.writeBoolean( true );
+                    
+                    if ( Arrays.equals( getReference(), normalizedValue ) )
+                    {
+                        // Write the 'same = true' flag
+                        out.writeBoolean( true );
+                    }
+                    else
+                    {
+                        // Write the 'same = false' flag
+                        out.writeBoolean( false );
+                        
+                        // Write the normalized value length
+                        out.write( normalizedValue.length );
+                        
+                        if ( normalizedValue.length > 0 )
+                        {
+                            // Write the normalized value if not empty
+                            out.write( normalizedValue );
+                        }
+                    }
+                }
+                catch ( NamingException ne )
+                {
+                    // The value can't be normalized, we don't write the 
+                    // normalized value.
+                    normalizedValue = null;
+                    out.writeBoolean( false );
+                }
             }
         }
         else
         {
+            // Write -1 indicating that the value is null
             out.writeInt( -1 );
         }
         
@@ -680,68 +730,80 @@
     
     /**
      * @see Externalizable#readExternal(ObjectInput)
+     * 
+     * We can't use this method for a ServerBinaryValue, as we have to feed the value
+     * with an AttributeType object
      */
     public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException
     {
-        if ( in.available() == 0 )
+        throw new IllegalStateException( "Cannot use standard serialization for a ServerStringValue" );
+    }
+    
+
+    /**
+     * 
+     * Deserialize a ServerBinaryValue. 
+     *
+     * @param in the buffer containing the bytes with the serialized value
+     * @throws IOException 
+     * @throws ClassNotFoundException
+     */
+    public void deserialize( ObjectInput in ) throws IOException, ClassNotFoundException
+    {
+        // The UP value length
+        int wrappedLength = in.readInt();
+        
+        if ( wrappedLength == -1 )
         {
-            set( null );
-            normalizedValue = null;
+            // If the value is null, the length will be set to -1
+            same = true;
+            wrapped = null;
+        }
+        else if ( wrappedLength == 0 )
+        {
+             wrapped = StringTools.EMPTY_BYTES;
+             same = true;
+             normalized = true;
+             normalizedValue = wrapped;
         }
         else
         {
-            int wrappedLength = in.readInt();
-            byte[] wrappedBytes = null;
+            wrapped = new byte[wrappedLength];
+            
+            // Read the data
+            in.read( wrapped, 0, wrappedLength );
             
-            switch ( wrappedLength )
+            // Check if we have a normalized value
+            normalized = in.readBoolean();
+            
+            if ( normalized )
             {
-                case -1 :
-                    // No value, no normalized value
-                    same = true;
-                    setNormalized( false );
-                    break;
-                    
-                case 0 :
-                    // Empty value, so is the normalized value
-                    wrappedBytes = StringTools.EMPTY_BYTES;
-                    normalizedValue = wrappedBytes;
-                    setNormalized( true );
-                    same = true;
-                    break;
-                    
-                default :
-                    wrappedBytes = new byte[wrappedLength];
-                    in.readFully( wrappedBytes );
-                    
+                // Read the 'same' flag
+                same = in.readBoolean();
+                
+                if ( !same )
+                {
+                    // Read the normalizedvalue length
                     int normalizedLength = in.readInt();
-                    
-                    // The normalized length should be either 0 or N, 
-                    // but it can't be -1
-                    switch ( normalizedLength )
+                
+                    if ( normalizedLength > 0 )
                     {
-                        case -1 :
-                            String message = "The normalized value cannot be null when the User Provide value is not";
-                            LOG.error(  message  );
-                            throw new IOException( message );
-                            
-                        case 0 :
-                            normalizedValue = StringTools.EMPTY_BYTES;
-                            same = true;
-                            setNormalized( false );
-                            break;
-                            
-                        default :
-                            same = false;
-                            normalizedValue = new byte[normalizedLength];
-                            in.readFully( normalizedValue );
-                            setNormalized( true );
-                            break;
+                        normalizedValue = new byte[normalizedLength];
+                        
+                        // Read the normalized value
+                        in.read( normalizedValue, 0, normalizedLength );
                     }
-                    
-                    break;
+                    else
+                    {
+                        normalizedValue = StringTools.EMPTY_BYTES;
+                    }
+                }
+                else
+                {
+                    normalizedValue = new byte[wrappedLength];
+                    System.arraycopy( wrapped, 0, normalizedValue, 0, wrappedLength );
+                }
             }
-            
-            set( wrappedBytes );
         }
     }
 }

Modified: directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerEntry.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerEntry.java?rev=686082&r1=686081&r2=686082&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerEntry.java (original)
+++ directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerEntry.java Thu Aug 14 16:12:09 2008
@@ -551,4 +551,12 @@
      * A clone method to produce a clone of the current object
      */
     Entry clone();
+    
+    
+    /**
+     * Convert the ServerEntry to a ClientEntry
+     *
+     * @return An instance of ClientEntry
+     */
+    Entry toClientEntry() throws NamingException;
 }

Modified: directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerEntrySerializer.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerEntrySerializer.java?rev=686082&r1=686081&r2=686082&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerEntrySerializer.java (original)
+++ directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerEntrySerializer.java Thu Aug 14 16:12:09 2008
@@ -22,19 +22,10 @@
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
-import java.io.ObjectInput;
 import java.io.ObjectInputStream;
-import java.io.ObjectOutput;
 import java.io.ObjectOutputStream;
 
-import javax.naming.NamingException;
-
 import org.apache.directory.server.schema.registries.Registries;
-import org.apache.directory.shared.ldap.entry.EntryAttribute;
-import org.apache.directory.shared.ldap.entry.Value;
-import org.apache.directory.shared.ldap.name.LdapDN;
-import org.apache.directory.shared.ldap.name.LdapDNSerializer;
-import org.apache.directory.shared.ldap.schema.AttributeType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -60,12 +51,6 @@
     /** The registries reference */
     private transient Registries registries;
 
-    /** Flag used for ServerStringValue */
-    private static final transient boolean HR_VALUE = true;
-
-    /** Flag used for streamed values */
-    private static final transient boolean STREAMED_VALUE = true;
-
 
     /**
      * Creates a new instance of ServerEntrySerializer.
@@ -93,60 +78,45 @@
      * <p>
      * </li>
      * <li>
-     * <b>DN</b> : The entry's DN. Can be empty (rootDSE=<p>
+     * <b>DN</b> : The entry's DN. Can be empty (rootDSE)<p>
+     * </li>
+     * <li>
+     * <b>[nb attributes]</b> The number of attributes
+     * </li>
+     * <br>
+     * For each attribute :
+     * <li>
+     * <b>[upId]</b> The attribute user provided ID (it can't be null)
+     * </li>
+     * <li>
+     * <b>[nb values]</b> The number of values
+     * </li>
+     * <br>
+     * For each value :
+     * <li>
+     *  <b>[is valid]</b> if the value is valid
+     * </li>
+     * <li>
+     *  <b>[HR flag]</b> if the value is a String
+     * </li>
+     * <li>
+     *  <b>[Streamed flag]</b> if the value is streamed
+     * </li>
+     * <li>
+     *  <b>[UP value]</b> the user provided value
+     * </li>
+     * <li>
+     *  <b>[Norm value]</b> (will be null if normValue == upValue)
      * </li>
-     * We have to store the UPid, and all the values, if any.
      */
     public byte[] serialize( Object object ) throws IOException
     {
-        ServerEntry entry = ( ServerEntry ) object;
-
+        DefaultServerEntry entry = ( DefaultServerEntry ) object;
+        
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         ObjectOutputStream out = new ObjectOutputStream( baos );
 
-        // First, the DN
-        if ( entry.getDn() == null )
-        {
-            // Write an empty DN
-            LdapDNSerializer.serialize( LdapDN.EMPTY_LDAPDN, out );
-        }
-        else
-        {
-            // Write the DN
-            LdapDNSerializer.serialize( entry.getDn(), out );
-        }
-
-        // Then the attributes.
-        out.writeInt( entry.size() );
-
-        // Iterate through the attributes. We store the Attribute
-        // here, to be able to restore it in the readExternal :
-        // we need access to the registries, which are not available
-        // in the ServerAttribute class.
-        for ( EntryAttribute attribute : entry )
-        {
-            // We store the OID, as the AttributeType might have no name
-            out.writeUTF( ( ( ServerAttribute ) attribute ).getAttributeType().getOid() );
-
-            // And store the attribute.
-            // Store the UP id
-            out.writeUTF( attribute.getUpId() );
-
-            // The number of values
-            out.writeInt( attribute.size() );
-
-            for ( Value<?> value : attribute )
-            {
-                try
-                {
-                    serializeValue( value, out );
-                }
-                catch ( NamingException ne )
-                {
-                    // TODO Handle this exception
-                }
-            }
-        }
+        entry.serialize( out );
 
         // Note : we don't store the ObjectClassAttribute. I has already
         // been stored as an attribute.
@@ -162,166 +132,7 @@
         return baos.toByteArray();
     }
 
-
-    /**
-     * We will write the value and the normalized value, only
-     * if the normalized value is different.
-     * 
-     * The data will be stored following this structure :
-     *
-     *  [is valid]
-     *  [HR flag]
-     *  [Streamed flag]
-     *  [UP value]
-     *  [Norm value] (will be null if normValue == upValue)
-     */
-    private void serializeValue( Value<?> value, ObjectOutput out ) throws IOException, NamingException
-    {
-        out.writeBoolean( value.isValid() );
-
-        if ( value instanceof ServerStringValue )
-        {
-            out.writeBoolean( HR_VALUE );
-            out.writeBoolean( !STREAMED_VALUE );
-            ServerStringValue ssv = ( ServerStringValue ) value;
-
-            if ( ssv.get() == null )
-            {
-                // Write two empty string for UP and normalized
-                out.writeUTF( "" );
-                out.writeUTF( "" );
-            }
-            else
-            {
-                // Save the UP value and the normalized value
-                out.writeUTF( ssv.get() );
-                ssv.normalize();
-                out.writeUTF( ssv.getNormalizedValue() );
-            }
-        }
-        else if ( value instanceof ServerBinaryValue )
-        {
-            out.writeBoolean( !HR_VALUE );
-            out.writeBoolean( !STREAMED_VALUE );
-            ServerBinaryValue sbv = ( ServerBinaryValue ) value;
-
-            if ( sbv.get() == null )
-            {
-                out.writeInt( 0 );
-                out.writeInt( 0 );
-            }
-            else
-            {
-                // Save the UP value and the normalized value if !=
-                out.writeInt( sbv.get().length );
-                out.write( sbv.get() );
-
-                out.writeBoolean( sbv.isSame() );
-
-                if ( !sbv.isSame() )
-                {
-                    sbv.normalize();
-
-                    out.writeInt( sbv.getNormalizedValueReference().length );
-                    out.write( sbv.getNormalizedValueReference() );
-                }
-            }
-        }
-
-        out.flush();
-    }
-
-
-    /**
-     * We will write the value and the normalized value, only
-     * if the normalized value is different.
-     * 
-     * The data will be stored following this structure :
-     *
-     *  [is valid]
-     *  [HR flag]
-     *  [Streamed flag]
-     *  [UP value]
-     *  [Norm value] (will be null if normValue == upValue)
-     */
-    private Value<?> deserializeValue( ObjectInput in, AttributeType attributeType ) throws IOException
-    {
-        boolean isValid = in.readBoolean();
-        boolean isHR = in.readBoolean();
-        boolean isStreamed = in.readBoolean();
-
-        if ( isHR )
-        {
-            if ( !isStreamed )
-            {
-                String value = in.readUTF();
-
-                if ( value.length() == 0 )
-                {
-                    value = null;
-                }
-
-                String normalized = in.readUTF();
-
-                if ( normalized.length() == 0 )
-                {
-                    normalized = null;
-                }
-
-                Value<?> ssv = new ServerStringValue( attributeType, value, normalized, isValid );
-
-                return ssv;
-            }
-            else
-            {
-                return null;
-            }
-        }
-        else
-        {
-            if ( !isStreamed )
-            {
-                int length = in.readInt();
-
-                byte[] value = new byte[length];
-
-                if ( length != 0 )
-                {
-                    in.read( value );
-                }
-
-                byte[] normalized = null;
-                boolean same = in.readBoolean();
-
-                // Now, if the normalized value is different from the wrapped value,
-                // read the normalized value.
-                if ( !same )
-                {
-                    length = in.readInt();
-
-                    normalized = new byte[length];
-                    if ( length != 0 )
-                    {
-                        in.read( normalized );
-                    }
-                }
-                else
-                {
-                    normalized = value;
-                }
-
-                Value<?> sbv = new ServerBinaryValue( attributeType, value, normalized, same, isValid );
-
-                return sbv;
-            }
-            else
-            {
-                return null;
-            }
-        }
-    }
-
-
+    
     /**
      *  Deserialize a ServerEntry
      */
@@ -329,52 +140,17 @@
     {
         ObjectInputStream in = new ObjectInputStream( new ByteArrayInputStream( bytes ) );
 
+        DefaultServerEntry serverEntry = new DefaultServerEntry( registries );
+        
         try
         {
-            // First, read the DN
-            LdapDN dn = LdapDNSerializer.deserialize( in );
-
-            // Read the number of attributes
-            int nbAttrs = in.readInt();
-
-            ServerEntry serverEntry = new DefaultServerEntry( registries, dn );
-
-            // Read all the attributes
-            for ( int i = 0; i < nbAttrs; i++ )
-            {
-                // The oid
-                String oid = in.readUTF();
-
-                AttributeType attributeType = registries.getAttributeTypeRegistry().lookup( oid );
-
-                // The UP id
-                String upId = in.readUTF();
-
-                // The number of values
-                int nbValues = in.readInt();
-
-                ServerAttribute serverAttribute = new DefaultServerAttribute( upId, attributeType );
-
-                for ( int j = 0; j < nbValues; j++ )
-                {
-                    Value<?> value = deserializeValue( in, attributeType );
-                    serverAttribute.add( value );
-                }
-
-                serverEntry.put( serverAttribute );
-            }
-
-            if ( IS_DEBUG )
-            {
-                LOG.debug( "<------------------------------------------------" );
-                LOG.debug( "Deserialize " + serverEntry );
-            }
-
+            serverEntry.deserialize( in );
+            
             return serverEntry;
         }
-        catch ( NamingException ne )
+        catch ( ClassNotFoundException cnfe )
         {
-            // TODO Handle this exception
+            LOG.error( "Cannot deserialize the entry :" + cnfe.getMessage() );
             return null;
         }
     }

Modified: directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerEntryUtils.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerEntryUtils.java?rev=686082&r1=686081&r2=686082&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerEntryUtils.java (original)
+++ directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerEntryUtils.java Thu Aug 14 16:12:09 2008
@@ -28,7 +28,6 @@
 import javax.naming.NamingException;
 import javax.naming.directory.Attribute;
 import javax.naming.directory.Attributes;
-import javax.naming.directory.BasicAttribute;
 import javax.naming.directory.BasicAttributes;
 import javax.naming.directory.DirContext;
 import javax.naming.directory.InvalidAttributeIdentifierException;
@@ -102,7 +101,7 @@
         return attributes;
     }
 
-    
+
     /**
      * Convert a BasicAttribute or a AttributeImpl to a ServerAtribute
      *
@@ -166,7 +165,7 @@
             return null;
         }
     }
-    
+
 
     /**
      * Convert a BasicAttributes or a AttributesImpl to a ServerEntry
@@ -219,53 +218,6 @@
 
 
     /**
-     * Convert a ServerEntry into a BasicAttributes. The DN is lost
-     * during this conversion, as the Attributes object does not store
-     * this element.
-     *
-     * @return An instance of a BasicAttributes() object
-     */
-    public static Attributes toBasicAttributes( ServerEntry entry )
-    {
-        Attributes attributes = new BasicAttributes( true );
-
-        for ( AttributeType attributeType:entry.getAttributeTypes() )
-        {
-            Attribute attribute = new BasicAttribute( attributeType.getName(), true );
-            
-            EntryAttribute attr = entry.get( attributeType );
-            
-            for ( Value<?> value:attr )
-            {
-                attribute.add( value );
-            }
-            
-            attributes.put( attribute );
-        }
-        
-        return attributes;
-    }
-    
-    
-    /**
-     * Convert a ServerAttributeEntry into a BasicAttribute.
-     *
-     * @return An instance of a BasicAttribute() object
-     */
-    public static Attribute toBasicAttribute( ServerAttribute attr )
-    {
-        Attribute attribute = new BasicAttribute( attr.getUpId(), false );
-
-        for ( Value<?> value:attr )
-        {
-            attribute.add( value.get() );
-        }
-        
-        return attribute;
-    }
-
-
-    /**
      * Convert a ServerAttributeEntry into a AttributeImpl.
      *
      * @return An instance of a BasicAttribute() object
@@ -409,7 +361,14 @@
     }
 
 
-    public static Modification toModification( ModificationItemImpl modificationImpl, AttributeType attributeType ) 
+    /**
+     * Convert a ModificationItemImpl to an instance of a ServerModification object
+     *
+     * @param modificationImpl the modification instance to convert
+     * @param attributeType the associated attributeType
+     * @return a instance of a ServerModification object
+     */
+    private static Modification toServerModification( ModificationItemImpl modificationImpl, AttributeType attributeType ) 
     {
         Modification modification = new ServerModification( 
             modificationImpl.getModificationOp(),
@@ -419,7 +378,7 @@
         
     }
 
-
+    
     public static List<ModificationItemImpl> toModificationItemImpl( List<Modification> modifications )
     {
         if ( modifications != null )
@@ -440,17 +399,26 @@
     }
     
     
-    public static List<Modification> toServerModification( List<ModificationItemImpl> modificationImpls, 
+    /**
+     * 
+     * Convert a list of ModificationItemImpl to a list of 
+     *
+     * @param modificationImpls
+     * @param atRegistry
+     * @return
+     * @throws NamingException
+     */
+    public static List<Modification> convertToServerModification( List<ModificationItemImpl> modificationImpls, 
         AttributeTypeRegistry atRegistry ) throws NamingException
     {
         if ( modificationImpls != null )
         {
-            List<Modification> modifications = new ArrayList<Modification>();
+            List<Modification> modifications = new ArrayList<Modification>( modificationImpls.size() );
 
             for ( ModificationItemImpl modificationImpl: modificationImpls )
             {
                 AttributeType attributeType = atRegistry.lookup( modificationImpl.getAttribute().getID() );
-                modifications.add( toModification( modificationImpl, attributeType ) );
+                modifications.add( toServerModification( modificationImpl, attributeType ) );
             }
         
             return modifications;
@@ -497,7 +465,7 @@
                 
                 // TODO : handle options
                 AttributeType attributeType = atRegistry.lookup( id );
-                modificationsList.add( toModification( (ModificationItemImpl)modification, attributeType ) );
+                modificationsList.add( toServerModification( (ModificationItemImpl)modification, attributeType ) );
             }
         
             return modificationsList;

Modified: directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerModification.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerModification.java?rev=686082&r1=686081&r2=686082&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerModification.java (original)
+++ directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerModification.java Thu Aug 14 16:12:09 2008
@@ -19,11 +19,22 @@
  */
 package org.apache.directory.server.core.entry;
 
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+import javax.naming.NamingException;
 import javax.naming.directory.DirContext;
 
+import org.apache.directory.server.schema.registries.AttributeTypeRegistry;
+import org.apache.directory.server.schema.registries.Registries;
 import org.apache.directory.shared.ldap.entry.EntryAttribute;
 import org.apache.directory.shared.ldap.entry.Modification;
 import org.apache.directory.shared.ldap.entry.ModificationOperation;
+import org.apache.directory.shared.ldap.entry.client.ClientModification;
+import org.apache.directory.shared.ldap.schema.AttributeType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * An internal implementation for a ModificationItem. The name has been
@@ -34,6 +45,11 @@
  */
 public class ServerModification implements Modification
 {
+    public static final long serialVersionUID = 1L;
+    
+    /** logger for reporting errors that might not be handled properly upstream */
+    private static final Logger LOG = LoggerFactory.getLogger( ServerModification.class );
+
     /** The modification operation */
     private ModificationOperation operation;
     
@@ -41,6 +57,23 @@
     private EntryAttribute attribute;
  
     
+    //-------------------------------------------------------------------------
+    // Constructors
+    //-------------------------------------------------------------------------
+    /**
+     * Create a new instance of a ServerModification.
+     */
+    public ServerModification()
+    {
+    }
+    
+    
+    /**
+     * Create a new instance of a ServerModification.
+     * 
+     * @param operation the Modification operation (one of add, replace or remove)
+     * @param attribute the modified attribute
+     */
     public ServerModification( ModificationOperation operation, EntryAttribute attribute )
     {
         this.operation = operation;
@@ -48,6 +81,12 @@
     }
     
     
+    /**
+     * Create a new instance of a ServerModification.
+     * 
+     * @param operation the Modification operation (one of add, replace or remove)
+     * @param attribute the modified attribute
+     */
     public ServerModification( int operation, EntryAttribute attribute )
     {
         setOperation( operation );
@@ -55,6 +94,38 @@
     }
     
     
+    public ServerModification( Registries registries, Modification modification )
+    {
+        operation = modification.getOperation();
+        
+        EntryAttribute modAttribute = modification.getAttribute();
+        
+        try
+        {
+            AttributeType at = null;
+            
+            if ( modAttribute instanceof ServerAttribute )
+            {
+                at = ((ServerAttribute)modAttribute).getAttributeType();
+            }
+            else
+            {
+                at = registries.getAttributeTypeRegistry().lookup( modAttribute.getId() );
+            }
+            
+            attribute = new DefaultServerAttribute( at, modAttribute );
+        }
+        catch ( NamingException ne )
+        {
+            // The attributeType is incorrect. Log, but do nothing otherwise.
+            LOG.error( "The attribute '" + modAttribute.getId() + "' is incorrect" );
+        }
+    }
+    
+    
+    //-------------------------------------------------------------------------
+    // API
+    //-------------------------------------------------------------------------
     /**
      *  @return the operation
      */
@@ -118,7 +189,24 @@
         this.attribute = (ServerAttribute)attribute;
     }
     
+
+    /**
+     * Convert the current ServerModification to a ClientModification instance 
+     *
+     * @return a new ClientModification instance
+     */
+    public Modification toClientModification()
+    {
+        ModificationOperation newOperation = operation;
+        EntryAttribute newAttribute = ((ServerAttribute)attribute).toClientAttribute();
+        Modification newModification = new ClientModification( newOperation, newAttribute );
+        
+        return newModification;
+    }
     
+    //-------------------------------------------------------------------------
+    // Overloaded Object class methods
+    //-------------------------------------------------------------------------
     /**
      * Compute the modification @see Object#hashCode
      * @return the instance's hash code 
@@ -134,6 +222,41 @@
     }
     
     
+    /**
+     * @see Object#equals(Object)
+     */
+    public boolean equals( Object that )
+    {
+        // Shortcut
+        if ( this == that )
+        {
+            return true;
+        }
+        
+        if ( ! ( that instanceof ServerModification ) )
+        {
+            return false;
+        }
+        
+        ServerModification modification = (ServerModification)that;
+        
+        if ( operation != modification.getOperation() )
+        {
+            return false;
+        }
+        
+        if ( attribute == null )
+        {
+            return modification.getAttribute() == null;
+        }
+        
+        return attribute.equals( modification.getAttribute() );
+    }
+    
+    
+    /**
+     * Create a clone instance
+     */
     public ServerModification clone()
     {
         try
@@ -149,6 +272,83 @@
         }
     }
     
+    
+    /**
+     * @see java.io.Externalizable#writeExternal(ObjectOutput)
+     * 
+     * We can't use this method for a ServerModification.
+     */
+    public void writeExternal( ObjectOutput out ) throws IOException
+    {
+        throw new IllegalStateException( "Cannot use standard serialization for a ServerEntry" );
+    }
+    
+    
+    /**
+     * @see java.io.Externalizable#readExternal(ObjectInput)
+     * 
+     * We can't use this method for a ServerModification.
+     */
+    public void readExternal( ObjectInput in ) throws IOException
+    {
+        throw new IllegalStateException( "Cannot use standard serialization for a ServerEntry" );
+    }
+    
+    
+    /**
+     * Deserialize a ServerModification
+     * 
+     * @param in The buffer containing the serialized value
+     * @param atRegistry The AttributeType registry
+     * @throws IOException If we weren't able to deserialize the data
+     * @throws ClassNotFoundException if we weren't able to construct a Modification instance
+     * @throws NamingException If we didn't found the AttributeType in the registries
+     */
+    public void deserialize( ObjectInput in, AttributeTypeRegistry atRegistry ) throws IOException, ClassNotFoundException, NamingException
+    {
+        // Read the operation
+        int op = in.readInt();
+        
+        operation = ModificationOperation.getOperation( op );
+        
+        // Read the attribute OID
+        String oid = in.readUTF();
+        
+        // Lookup for tha associated AttributeType
+        AttributeType attributeType = atRegistry.lookup( oid );
+        
+        attribute = new DefaultServerAttribute( attributeType );
+        
+        // Read the attribute
+        ((DefaultServerAttribute)attribute).deserialize( in );
+    }
+    
+    
+    /**
+     * Serialize a ServerModification.
+     */
+    public void serialize( ObjectOutput out ) throws IOException
+    {
+        if ( attribute == null )
+        {
+            throw new IOException( "Cannot serialize a Modification with no attribute" );
+        }
+        
+        // Write the operation
+        out.writeInt( operation.getValue() );
+        
+        AttributeType at = ((DefaultServerAttribute)attribute).getAttributeType();
+        
+        // Write the attribute's oid
+        out.writeUTF( at.getOid() );
+        
+        // Write the attribute
+        ((DefaultServerAttribute)attribute).serialize( out );
+        
+        out.flush();
+    }
+    
+    
     /**
      * @see Object#toString()
      */

Modified: directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerStringValue.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerStringValue.java?rev=686082&r1=686081&r2=686082&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerStringValue.java (original)
+++ directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerStringValue.java Thu Aug 14 16:12:09 2008
@@ -109,6 +109,7 @@
     public ServerStringValue( AttributeType attributeType )
     {
         super();
+        
         if ( attributeType == null )
         {
             throw new IllegalArgumentException( "The AttributeType parameter should not be null" );
@@ -564,39 +565,70 @@
     /**
      * @see Externalizable#writeExternal(ObjectOutput)
      * 
+     * We can't use this method for a ServerStringValue, as we have to feed the value
+     * with an AttributeType object
+     */ 
+    public void writeExternal( ObjectOutput out ) throws IOException
+    {
+        throw new IllegalStateException( "Cannot use standard serialization for a ServerStringValue" );
+    }
+    
+    
+    /**
      * We will write the value and the normalized value, only
      * if the normalized value is different.
      * 
-     * The data will be stored following this structure :
+     * If the value is empty, a flag is written at the beginning with 
+     * the value true, otherwise, a false is written.
      * 
+     * The data will be stored following this structure :
+     *  [empty value flag]
      *  [UP value]
-     *  [Norm value] (will be null if normValue == upValue)
+     *  [normalized] (will be false if the value can't be normalized)
+     *  [same] (a flag set to true if the normalized value equals the UP value)
+     *  [Norm value] (the normalized value if different from the UP value)
+     *  
+     *  @param out the buffer in which we will stored the serialized form of the value
+     *  @throws IOException if we can't write into the buffer
      */
-    public void writeExternal( ObjectOutput out ) throws IOException
+    public void serialize( ObjectOutput out ) throws IOException
     {
-        if ( get() != null )
+        if ( wrapped != null )
         {
-            out.writeUTF( get() );
+            // write a flag indicating that the value is not null
+            out.writeBoolean( true );
+            
+            // Write the data
+            out.writeUTF( wrapped );
             
+            // Normalize the data
             try
             {
                 normalize();
+                out.writeBoolean( true );
+                
+                if ( wrapped.equals( normalizedValue ) )
+                {
+                    out.writeBoolean( true );
+                }
+                else
+                {
+                    out.writeBoolean( false );
+                    out.writeUTF( normalizedValue );
+                }
             }
             catch ( NamingException ne )
             {
+                // The value can't be normalized, we don't write the 
+                // normalized value.
                 normalizedValue = null;
+                out.writeBoolean( false );
             }
-            
-            if ( get().equals( normalizedValue ) )
-            {
-                // If the normalized value is equal to the UP value,
-                // don't save it
-                out.writeUTF( "" );
-            }
-            else
-            {
-                out.writeUTF( normalizedValue );
-            }
+        }
+        else
+        {
+            // Write a flag indicating that the value is null
+            out.writeBoolean( false );
         }
         
         out.flush();
@@ -605,31 +637,55 @@
     
     /**
      * @see Externalizable#readExternal(ObjectInput)
+     * 
+     * We can't use this method for a ServerStringValue, as we have to feed the value
+     * with an AttributeType object
      */
     public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException
     {
-        if ( in.available() == 0 )
+        throw new IllegalStateException( "Cannot use standard serialization for a ServerStringValue" );
+    }
+    
+
+    /**
+     * 
+     * Deserialize a ServerStringValue. 
+     *
+     * @param in the buffer containing the bytes with the serialized value
+     * @throws IOException 
+     * @throws ClassNotFoundException
+     */
+    public void deserialize( ObjectInput in ) throws IOException, ClassNotFoundException
+    {
+        // If the value is null, the flag will be set to false
+        if ( !in.readBoolean() )
         {
             set( null );
             normalizedValue = null;
+            return;
         }
-        else
+        
+        // Read the value
+        String wrapped = in.readUTF();
+        
+        set( wrapped );
+        
+        // Read the normalized flag
+        normalized = in.readBoolean();
+        
+        if ( normalized )
         {
-            String wrapped = in.readUTF();
-            
-            set( wrapped );
-            
-            normalizedValue = in.readUTF();
-            
-            if ( ( normalizedValue.length() == 0 ) &&  ( wrapped.length() != 0 ) )
+            normalized = true;
+
+            // Read the 'same' flag
+            if ( in.readBoolean() )
             {
-                // In this case, the normalized value is equal to the UP value
                 normalizedValue = wrapped;
-                setNormalized( true );
             }
             else
             {
-                setNormalized( false );
+                // The normalized value is different. Read it
+                normalizedValue = in.readUTF();
             }
         }
     }

Modified: directory/apacheds/branches/bigbang/core-entry/src/test/java/org/apache/directory/server/core/entry/DefaultServerAttributeTest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-entry/src/test/java/org/apache/directory/server/core/entry/DefaultServerAttributeTest.java?rev=686082&r1=686081&r2=686082&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core-entry/src/test/java/org/apache/directory/server/core/entry/DefaultServerAttributeTest.java (original)
+++ directory/apacheds/branches/bigbang/core-entry/src/test/java/org/apache/directory/server/core/entry/DefaultServerAttributeTest.java Thu Aug 14 16:12:09 2008
@@ -27,6 +27,11 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.fail;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
@@ -34,7 +39,7 @@
 import java.util.List;
 import java.util.Set;
 
-import javax.naming.directory.Attribute;
+import javax.naming.NamingException;
 import javax.naming.directory.InvalidAttributeValueException;
 
 import org.apache.directory.server.schema.bootstrap.ApacheSchema;
@@ -51,20 +56,13 @@
 import org.apache.directory.server.schema.registries.Registries;
 import org.apache.directory.shared.ldap.entry.EntryAttribute;
 import org.apache.directory.shared.ldap.entry.Value;
+import org.apache.directory.shared.ldap.entry.client.ClientAttribute;
 import org.apache.directory.shared.ldap.entry.client.ClientBinaryValue;
 import org.apache.directory.shared.ldap.entry.client.ClientStringValue;
 import org.apache.directory.shared.ldap.entry.client.DefaultClientAttribute;
 import org.apache.directory.shared.ldap.schema.AttributeType;
 import org.apache.directory.shared.ldap.util.StringTools;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNotSame;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
 import org.junit.BeforeClass;
 import org.junit.Test;
 
@@ -133,6 +131,81 @@
         atPwd = registries.getAttributeTypeRegistry().lookup( "userpassword" );
     }
 
+    /**
+     * Serialize a DefaultServerAttribute
+     */
+    private ByteArrayOutputStream serializeValue( DefaultServerAttribute value ) throws IOException
+    {
+        ObjectOutputStream oOut = null;
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+        try
+        {
+            oOut = new ObjectOutputStream( out );
+            value.serialize( oOut );
+        }
+        catch ( IOException ioe )
+        {
+            throw ioe;
+        }
+        finally
+        {
+            try
+            {
+                if ( oOut != null )
+                {
+                    oOut.flush();
+                    oOut.close();
+                }
+            }
+            catch ( IOException ioe )
+            {
+                throw ioe;
+            }
+        }
+        
+        return out;
+    }
+    
+    
+    /**
+     * Deserialize a DefaultServerAttribute
+     */
+    private DefaultServerAttribute deserializeValue( ByteArrayOutputStream out, AttributeType at ) throws IOException, ClassNotFoundException
+    {
+        ObjectInputStream oIn = null;
+        ByteArrayInputStream in = new ByteArrayInputStream( out.toByteArray() );
+
+        try
+        {
+            oIn = new ObjectInputStream( in );
+
+            DefaultServerAttribute value = new DefaultServerAttribute( at );
+            value.deserialize( oIn );
+            
+            return value;
+        }
+        catch ( IOException ioe )
+        {
+            throw ioe;
+        }
+        finally
+        {
+            try
+            {
+                if ( oIn != null )
+                {
+                    oIn.close();
+                }
+            }
+            catch ( IOException ioe )
+            {
+                throw ioe;
+            }
+        }
+    }
+
+    
     @Test public void testAddOneValue() throws Exception
     {
         AttributeType at = TestServerEntryUtils.getIA5StringAttributeType();
@@ -245,13 +318,11 @@
         attr.add( "Test2" );
         attr.add( "Test3" );
         
-        Attribute attribute = ServerEntryUtils.toBasicAttribute( attr );
-        
-        assertEquals( "1.1",attribute.getID() );
-        assertEquals( 3, attribute.size() );
-        assertTrue( attribute.contains( "Test1" ) );
-        assertTrue( attribute.contains( "Test2" ) );
-        assertTrue( attribute.contains( "Test3" ) );
+        assertEquals( "1.1",attr.getId() );
+        assertEquals( 3, attr.size() );
+        assertTrue( attr.contains( "Test1" ) );
+        assertTrue( attr.contains( "Test2" ) );
+        assertTrue( attr.contains( "Test3" ) );
     }
 
 
@@ -1922,4 +1993,156 @@
         clone = attr.clone();
         assertEquals( attr, clone );
     }
+    
+    
+    /**
+     * Test the copy constructor of a ServerAttribute
+     */
+    @Test 
+    public void testCopyConstructorServerAttribute() throws InvalidAttributeValueException
+    {
+        EntryAttribute attribute = new DefaultServerAttribute( atCN );
+        
+        EntryAttribute copy = new DefaultServerAttribute( atCN, attribute );
+        
+        assertEquals( copy, attribute );
+
+        EntryAttribute attribute2 = new DefaultServerAttribute( atCN, "test" );
+        
+        EntryAttribute copy2 = new DefaultServerAttribute( atCN, attribute2 );
+        
+        assertEquals( copy2, attribute2 );
+        attribute2.add( "test2" );
+        assertNotSame( copy2, attribute2 );
+        assertEquals( "test", copy2.getString() );
+    }
+    
+    
+    /**
+     * Test the copy constructor of a ClientAttribute
+     */
+    @Test 
+    public void testCopyConstructorClientAttribute() throws InvalidAttributeValueException
+    {
+        EntryAttribute attribute = new DefaultClientAttribute( "commonName" );
+        attribute.put( "test" );
+        
+        ServerAttribute copy = new DefaultServerAttribute( atCN, attribute );
+
+        assertEquals( atCN, copy.getAttributeType() );
+        assertEquals( "test", copy.getString() );
+        assertTrue( copy.isHR() );
+        
+        attribute.add( "test2" );
+        assertFalse( copy.contains( "test2" ) );
+    }
+    
+    
+    /**
+     * Test the conversion method 
+     */
+    @Test 
+    public void testToClientAttribute()
+    {
+        ServerAttribute attribute = new DefaultServerAttribute( atCN, "test", "test2" );
+        
+        EntryAttribute clientAttribute = attribute.toClientAttribute();
+        
+        assertTrue( clientAttribute instanceof ClientAttribute );
+        assertFalse( clientAttribute instanceof ServerAttribute );
+        
+        assertTrue( clientAttribute.contains( "test", "test2" ) );
+        assertEquals( "cn", clientAttribute.getId() );
+        
+        attribute.remove( "test", "test2" );
+        assertTrue( clientAttribute.contains( "test", "test2" ) );
+    }
+    
+    
+    /**
+     * Test the serialization of a complete server attribute
+     */
+    @Test
+    public void testSerializeCompleteAttribute() throws NamingException, IOException, ClassNotFoundException
+    {
+        DefaultServerAttribute dsa = new DefaultServerAttribute( atCN );
+        dsa.setHR( true );
+        dsa.setUpId( "CommonName" );
+        dsa.add( "test1", "test2" );
+
+        DefaultServerAttribute dsaSer = deserializeValue( serializeValue( dsa ), atCN );
+        assertEquals( dsa.toString(), dsaSer.toString() );
+        assertEquals( "commonname", dsaSer.getId() );
+        assertEquals( "CommonName", dsaSer.getUpId() );
+        assertEquals( "test1", dsaSer.getString() );
+        assertTrue( dsaSer.contains( "test2", "test1" ) );
+        assertTrue( dsaSer.isHR() );
+        assertTrue( dsaSer.isValid() );
+    }
+    
+    
+    /**
+     * Test the serialization of a server attribute with no value
+     */
+    @Test
+    public void testSerializeAttributeWithNoValue() throws NamingException, IOException, ClassNotFoundException
+    {
+        DefaultServerAttribute dsa = new DefaultServerAttribute( atCN );
+        dsa.setHR( true );
+        dsa.setId( "cn" );
+
+        DefaultServerAttribute dsaSer = deserializeValue( serializeValue( dsa ), atCN );
+        assertEquals( dsa.toString(), dsaSer.toString() );
+        assertEquals( "cn", dsaSer.getId() );
+        assertEquals( "cn", dsaSer.getUpId() );
+        assertEquals( 0, dsaSer.size() );
+        assertTrue( dsaSer.isHR() );
+        assertTrue( dsaSer.isValid() );
+    }
+    
+    
+    /**
+     * Test the serialization of a server attribute with a null value
+     */
+    @Test
+    public void testSerializeAttributeNullValue() throws NamingException, IOException, ClassNotFoundException
+    {
+        DefaultServerAttribute dsa = new DefaultServerAttribute( atCN );
+        dsa.setHR( true );
+        dsa.setUpId( "CommonName" );
+        dsa.add( (String)null );
+
+        DefaultServerAttribute dsaSer = deserializeValue( serializeValue( dsa ), atCN );
+        assertEquals( dsa.toString(), dsaSer.toString() );
+        assertEquals( "commonname", dsaSer.getId() );
+        assertEquals( "CommonName", dsaSer.getUpId() );
+        assertNull( dsaSer.getString() );
+        assertEquals( 1, dsaSer.size() );
+        assertTrue( dsaSer.contains( (String)null ) );
+        assertTrue( dsaSer.isHR() );
+        assertFalse( dsaSer.isValid() );
+    }
+    
+    
+    /**
+     * Test the serialization of a server attribute with a binary value
+     */
+    @Test
+    public void testSerializeAttributeBinaryValue() throws NamingException, IOException, ClassNotFoundException
+    {
+        DefaultServerAttribute dsa = new DefaultServerAttribute( atPwd );
+        dsa.setHR( false );
+        byte[] password = StringTools.getBytesUtf8( "secret" );
+        dsa.add( password );
+
+        DefaultServerAttribute dsaSer = deserializeValue( serializeValue( dsa ), atPwd );
+        assertEquals( dsa.toString(), dsaSer.toString() );
+        assertEquals( "userpassword", dsaSer.getId() );
+        assertEquals( "userPassword", dsaSer.getUpId() );
+        assertTrue( Arrays.equals( dsa.getBytes(), dsaSer.getBytes() ) );
+        assertEquals( 1, dsaSer.size() );
+        assertTrue( dsaSer.contains( password ) );
+        assertFalse( dsaSer.isHR() );
+        assertTrue( dsaSer.isValid() );
+    }
 }

Modified: directory/apacheds/branches/bigbang/core-entry/src/test/java/org/apache/directory/server/core/entry/DefaultServerEntryTest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-entry/src/test/java/org/apache/directory/server/core/entry/DefaultServerEntryTest.java?rev=686082&r1=686081&r2=686082&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core-entry/src/test/java/org/apache/directory/server/core/entry/DefaultServerEntryTest.java (original)
+++ directory/apacheds/branches/bigbang/core-entry/src/test/java/org/apache/directory/server/core/entry/DefaultServerEntryTest.java Thu Aug 14 16:12:09 2008
@@ -27,8 +27,8 @@
 
 import javax.naming.InvalidNameException;
 import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
 import javax.naming.directory.Attributes;
-import javax.naming.directory.BasicAttributes;
 import javax.naming.directory.NoSuchAttributeException;
 
 import org.apache.directory.server.schema.bootstrap.ApacheSchema;
@@ -49,7 +49,9 @@
 import org.apache.directory.shared.ldap.entry.EntryAttribute;
 import org.apache.directory.shared.ldap.entry.Value;
 import org.apache.directory.shared.ldap.entry.client.ClientBinaryValue;
+import org.apache.directory.shared.ldap.entry.client.ClientEntry;
 import org.apache.directory.shared.ldap.entry.client.ClientStringValue;
+import org.apache.directory.shared.ldap.entry.client.DefaultClientEntry;
 import org.apache.directory.shared.ldap.message.AttributesImpl;
 import org.apache.directory.shared.ldap.name.LdapDN;
 import org.apache.directory.shared.ldap.schema.AttributeType;
@@ -141,7 +143,7 @@
     {
         Entry entry = new DefaultServerEntry();
         assertNotNull( entry );
-        assertNull( entry.getDn() );
+        assertEquals( LdapDN.EMPTY_LDAPDN, entry.getDn() );
         assertEquals( 0, entry.size() );
     }
     
@@ -154,7 +156,7 @@
     {
         Entry entry = new DefaultServerEntry( registries );
         assertNotNull( entry );
-        assertNull( entry.getDn() );
+        assertEquals( LdapDN.EMPTY_LDAPDN, entry.getDn() );
         assertEquals( 0, entry.size() );
     }
     
@@ -1319,7 +1321,7 @@
         assertEquals( entry1, entry2 );
         entry2.setDn( EXAMPLE_DN );
         
-        assertNull( entry1.getDn() );
+        assertEquals( LdapDN.EMPTY_LDAPDN,entry1.getDn() );
         
         entry1.setDn( EXAMPLE_DN );
         entry2 = entry1.clone();
@@ -3762,7 +3764,7 @@
     {
         Entry entry = new DefaultServerEntry( registries );
          
-        assertNull( entry.getDn() );
+        assertEquals( LdapDN.EMPTY_LDAPDN, entry.getDn() );
          
         entry.setDn( EXAMPLE_DN );
         assertEquals( EXAMPLE_DN, entry.getDn() );
@@ -3835,41 +3837,6 @@
 
 
     /**
-     * Test a conversion from a ServerEntry to an BasicAttributes
-     */
-    @Test public void testToBasicAttributes() throws InvalidNameException, Exception
-    {
-        LdapDN dn = new LdapDN( "cn=test" );
-        DefaultServerEntry entry = new DefaultServerEntry( registries,dn );
-        
-        AttributeType OBJECT_CLASS_AT = registries.getAttributeTypeRegistry().lookup( SchemaConstants.OBJECT_CLASS_AT );
-        
-        entry.put( "objectClass", OBJECT_CLASS_AT, "top", "person", "inetOrgPerson", "organizationalPerson" );
-        
-        Attributes attributes = ServerEntryUtils.toBasicAttributes( entry );
-        
-        assertNotNull( attributes );
-        assertTrue( attributes instanceof BasicAttributes );
-        
-        Set<String> expected = new HashSet<String>();
-        expected.add( "objectClass" );
-        expected.add( "cn" );
-     
-        for ( NamingEnumeration<String> ids = attributes.getIDs(); ids.hasMoreElements();)
-        {
-            String id = ids.nextElement();
-            
-            assertTrue( expected.contains( id ) );
-            expected.remove( id );
-            
-        }
-
-        // We should still have the ObjectClass Attribute
-        assertEquals( 1, expected.size() );
-    }
-    
-    
-    /**
      * Test method for toString().
      */
     @Test
@@ -3877,7 +3844,7 @@
     {
         ServerEntry entry = new DefaultServerEntry( registries, EXAMPLE_DN );
         
-        assertEquals( "ServerEntry\n    dn: dc=example,dc=com\n", entry.toString() );
+        assertEquals( "ServerEntry\n    dn[]: dc=example,dc=com\n", entry.toString() );
         
         Value<String> strValueTop = new ClientStringValue( "top" );
         Value<String> strValuePerson = new ClientStringValue( "person" );
@@ -3892,7 +3859,7 @@
 
         String expected = 
             "ServerEntry\n" +
-            "    dn: dc=example,dc=com\n" +
+            "    dn[]: dc=example,dc=com\n" +
             "    ObjectClass: top\n" +
             "    ObjectClass: person\n" +
             "    ObjectClass: ''\n" +
@@ -3902,5 +3869,84 @@
 
         assertEquals( expected, entry.toString() );
     }
+
+    
+    
+    /**
+     * Test the copy constructor of a ServerEntry
+     */
+    @Test 
+    public void testCopyConstructorServerEntry() throws NamingException
+    {
+        Entry serverEntry = new DefaultServerEntry( registries );
+        serverEntry.add( "cn", "test1", "test2" );
+        serverEntry.add( "objectClass", "top", "person" );
+        
+        Entry copyEntry = new DefaultServerEntry( registries, serverEntry );
+        
+        assertEquals( copyEntry, serverEntry );
+        assertTrue( copyEntry.contains( "objectClass", "top", "person" ) );
+        assertTrue( copyEntry.contains( "cn", "test1", "test2" ) );
+        
+        serverEntry.removeAttributes( "cn" );
+
+        assertNotSame( copyEntry, serverEntry );
+        assertTrue( copyEntry.contains( "objectClass", "top", "person" ) );
+        assertTrue( copyEntry.contains( "cn", "test1", "test2" ) );
+    }
+    
+    
+    /**
+     * Test the copy constructor of a ClientEntry
+     */
+    @Test 
+    public void testCopyConstructorClientEntry() throws NamingException
+    {
+        Entry clientEntry = new DefaultClientEntry();
+        clientEntry.setDn( new LdapDN( "ou=system" ) );
+        clientEntry.add( "cn", "test1", "test2" );
+        clientEntry.add( "objectClass", "top", "person" );
+        
+        Entry copyEntry = new DefaultServerEntry( registries, clientEntry );
+        
+        assertTrue( copyEntry instanceof ServerEntry );
+        assertTrue( copyEntry.contains( "objectClass", "top", "person" ) );
+        assertTrue( copyEntry.contains( "cn", "test1", "test2" ) );
+        
+        clientEntry.removeAttributes( "cn" );
+
+        assertTrue( copyEntry.contains( "objectClass", "top", "person" ) );
+        assertTrue( copyEntry.contains( "cn", "test1", "test2" ) );
+    }
+    
+    
+    /**
+     * Test the conversion method 
+     */
+    @Test 
+    public void testToClientEntry() throws NamingException
+    {
+        LdapDN dn = new LdapDN( "ou=system" );
+        ServerEntry serverEntry = new DefaultServerEntry( registries );
+        serverEntry.setDn( dn );
+        serverEntry.add( "cn", "test1", "test2" );
+        serverEntry.add( "objectClass", "top", "person" );
+        
+        Entry clientEntry = serverEntry.toClientEntry();
+        
+        assertTrue( clientEntry instanceof ClientEntry );
+        assertFalse( clientEntry instanceof ServerEntry );
+        
+        assertTrue( clientEntry.containsAttribute( "cn", "objectClass" ) );
+        assertEquals( dn, clientEntry.getDn() );
+        
+        serverEntry.removeAttributes( "cn" );
+        assertTrue( clientEntry
+            .contains( "cn", "test1", "test2" ) );
+        
+        serverEntry.remove(  "objectClass", "person" );
+        assertTrue( clientEntry
+            .contains( "objectClass", "top", "person" ) );
+    }
 }
 

Modified: directory/apacheds/branches/bigbang/core-entry/src/test/java/org/apache/directory/server/core/entry/ServerBinaryValueTest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-entry/src/test/java/org/apache/directory/server/core/entry/ServerBinaryValueTest.java?rev=686082&r1=686081&r2=686082&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core-entry/src/test/java/org/apache/directory/server/core/entry/ServerBinaryValueTest.java (original)
+++ directory/apacheds/branches/bigbang/core-entry/src/test/java/org/apache/directory/server/core/entry/ServerBinaryValueTest.java Thu Aug 14 16:12:09 2008
@@ -110,7 +110,82 @@
         at.setSyntax( s );
     }
     
+    
+    /**
+     * Serialize a ServerBinaryValue
+     */
+    private ByteArrayOutputStream serializeValue( ServerBinaryValue value ) throws IOException
+    {
+        ObjectOutputStream oOut = null;
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+        try
+        {
+            oOut = new ObjectOutputStream( out );
+            value.serialize( oOut );
+        }
+        catch ( IOException ioe )
+        {
+            throw ioe;
+        }
+        finally
+        {
+            try
+            {
+                if ( oOut != null )
+                {
+                    oOut.flush();
+                    oOut.close();
+                }
+            }
+            catch ( IOException ioe )
+            {
+                throw ioe;
+            }
+        }
+        
+        return out;
+    }
+    
+    
+    /**
+     * Deserialize a ServerBinaryValue
+     */
+    private ServerBinaryValue deserializeValue( ByteArrayOutputStream out, AttributeType at ) throws IOException, ClassNotFoundException
+    {
+        ObjectInputStream oIn = null;
+        ByteArrayInputStream in = new ByteArrayInputStream( out.toByteArray() );
+
+        try
+        {
+            oIn = new ObjectInputStream( in );
 
+            ServerBinaryValue value = new ServerBinaryValue( at );
+            value.deserialize( oIn );
+
+            return value;
+        }
+        catch ( IOException ioe )
+        {
+            throw ioe;
+        }
+        finally
+        {
+            try
+            {
+                if ( oIn != null )
+                {
+                    oIn.close();
+                }
+            }
+            catch ( IOException ioe )
+            {
+                throw ioe;
+            }
+        }
+    }
+    
+    
     /**
      * Test the constructor with bad AttributeType
      */
@@ -472,28 +547,17 @@
         byte[] v1Norm = StringTools.getBytesUtf8( "Test   Test" );
         
         // First check with a value which will be normalized
-        ServerBinaryValue sv = new ServerBinaryValue( at, v1 );
+        ServerBinaryValue sbv = new ServerBinaryValue( at, v1 );
         
-        sv.normalize();
-        byte[] normalized = sv.getNormalizedValueReference();
+        sbv.normalize();
+        byte[] normalized = sbv.getNormalizedValueReference();
         
         assertTrue( Arrays.equals( v1Norm, normalized ) );
-        assertTrue( Arrays.equals( v1, sv.getReference() ) );
+        assertTrue( Arrays.equals( v1, sbv.getReference() ) );
         
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        ObjectOutputStream out = new ObjectOutputStream( baos );
+        ServerBinaryValue sbvSer = deserializeValue( serializeValue( sbv ), at );
         
-        sv.writeExternal( out );
-        
-        ObjectInputStream in = null;
-
-        byte[] data = baos.toByteArray();
-        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
-        
-        ServerBinaryValue sv2 = new ServerBinaryValue( at );
-        sv2.readExternal( in );
-        
-        assertEquals( sv, sv2 );
+        assertEquals( sbv, sbvSer );
     }
 
 
@@ -506,29 +570,17 @@
         byte[] v1Norm = StringTools.getBytesUtf8( "test" );
 
         // First check with a value which will be normalized
-        ServerBinaryValue sv = new ServerBinaryValue( at, v1 );
+        ServerBinaryValue sbv = new ServerBinaryValue( at, v1 );
         
-        sv.normalize();
-        byte[] normalized = sv.getNormalizedValueReference();
+        sbv.normalize();
+        byte[] normalized = sbv.getNormalizedValueReference();
         
         assertTrue( Arrays.equals( v1Norm, normalized ) );
-        assertTrue( Arrays.equals( v1, sv.get() ) );
-        
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        ObjectOutputStream out = new ObjectOutputStream( baos );
-        
-        sv.writeExternal( out );
-        
-        ObjectInputStream in = null;
-
-        byte[] data = baos.toByteArray();
-        
-        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+        assertTrue( Arrays.equals( v1, sbv.get() ) );
         
-        ServerBinaryValue sv2 = new ServerBinaryValue( at );
-        sv2.readExternal( in );
+        ServerBinaryValue sbvSer = deserializeValue( serializeValue( sbv ), at );
         
-        assertEquals( sv, sv2 );
+        assertEquals( sbv, sbvSer );
    }
 
 
@@ -538,29 +590,17 @@
     @Test public void testNullBinaryValueSerialization() throws NamingException, IOException, ClassNotFoundException
     {
         // First check with a value which will be normalized
-        ServerBinaryValue sv = new ServerBinaryValue( at );
+        ServerBinaryValue sbv = new ServerBinaryValue( at );
         
-        sv.normalize();
-        byte[] normalized = sv.getNormalizedValueReference();
+        sbv.normalize();
+        byte[] normalized = sbv.getNormalizedValueReference();
         
         assertEquals( null, normalized );
-        assertEquals( null, sv.get() );
-        
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        ObjectOutputStream out = new ObjectOutputStream( baos );
-        
-        sv.writeExternal( out );
-        
-        ObjectInputStream in = null;
-
-        byte[] data = baos.toByteArray();
-        
-        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+        assertEquals( null, sbv.get() );
         
-        ServerBinaryValue sv2 = new ServerBinaryValue( at );
-        sv2.readExternal( in );
+        ServerBinaryValue sbvSer = deserializeValue( serializeValue( sbv ), at );
         
-        assertEquals( sv, sv2 );
+        assertEquals( sbv, sbvSer );
    }
 
 
@@ -570,28 +610,39 @@
     @Test public void testEmptyBinaryValueSerialization() throws NamingException, IOException, ClassNotFoundException
     {
         // First check with a value which will be normalized
-        ServerBinaryValue sv = new ServerBinaryValue( at, StringTools.EMPTY_BYTES );
+        ServerBinaryValue sbv = new ServerBinaryValue( at, StringTools.EMPTY_BYTES );
         
-        sv.normalize();
-        byte[] normalized = sv.getNormalizedValueReference();
+        sbv.normalize();
+        byte[] normalized = sbv.getNormalizedValueReference();
         
         assertTrue( Arrays.equals( StringTools.EMPTY_BYTES, normalized ) );
-        assertTrue( Arrays.equals( StringTools.EMPTY_BYTES, sv.get() ) );
-        
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        ObjectOutputStream out = new ObjectOutputStream( baos );
+        assertTrue( Arrays.equals( StringTools.EMPTY_BYTES, sbv.get() ) );
         
-        sv.writeExternal( out );
+        ServerBinaryValue sbvSer = deserializeValue( serializeValue( sbv ), at );
         
-        ObjectInputStream in = null;
+        assertEquals( sbv, sbvSer );
+   }
 
-        byte[] data = baos.toByteArray();
+
+    /**
+     * Test serialization of a BinaryValue which is the same than the value
+     */
+    @Test public void testSameNormalizedBinaryValueSerialization() throws NamingException, IOException, ClassNotFoundException
+    {
+        byte[] v1 = StringTools.getBytesUtf8( "test" );
+        byte[] v1Norm = StringTools.getBytesUtf8( "test" );
+
+        // First check with a value which will be normalized
+        ServerBinaryValue sbv = new ServerBinaryValue( at, v1 );
         
-        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+        sbv.normalize();
+        byte[] normalized = sbv.getNormalizedValueReference();
+        
+        assertTrue( Arrays.equals( v1Norm, normalized ) );
+        assertTrue( Arrays.equals( v1, sbv.get() ) );
         
-        ServerBinaryValue sv2 = new ServerBinaryValue( at );
-        sv2.readExternal( in );
+        ServerBinaryValue sbvSer = deserializeValue( serializeValue( sbv ), at );
         
-        assertEquals( sv, sv2 );
+        assertEquals( sbv, sbvSer );
    }
 }
\ No newline at end of file